вступление
В первых выпусках Fabric8 v2 использовался клиент Kubernetes на основе JAX-RS, который использовал ApacheCXF . Клиент был великолепен, но мы всегда хотели предложить что-то более тонкое, с меньшим количеством зависимостей (чтобы его было легче принять) . Мы также хотели дать ему возможность поднять его и построить вокруг него DSL, чтобы его было легче использовать и читать.
Новый клиент в настоящее время живет по адресу: https://github.com/fabric8io/kubernetes-client и предоставляет следующие модули:
- Клиент Kubernetes .
- Клиент Openshift .
- Поддельные рамки для всего вышеперечисленного (на основе EasyMock )
Первый взгляд на клиента
Давайте кратко рассмотрим, как вы можете создавать, перечислять и удалять вещи с помощью клиента:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
//Instantiate the client KubernetesClient client = new DefaultKubernetesClient(); //Create a service Service myservice = ...; client.services().inNamespace( "fabric8" ).create(myservice); //Create a service inline Service jenkins = client.services().inNamespace( "fabric8" ).createNew() .withNewMetadata() .withName( "jenkins" ) .addToLabels( "component" , "jenkins" ) .endMetadata() .done(); //List services ServiceList serviceList = client.services().inNamespace( "fabric8" ).list(); //Watch services client.services().inNamespace( "fabric8" ).watch( new Watcher<Service>() { @Override public void eventReceived(Action action, Service resource) { logger.info( "{}: {}" , action, resource); } }); //Delete by label Boolean deleted = client.services().withLabel( "component" , "jenkins" ).delete(); //Close client client.close(); |
Вышеприведенный фрагмент в значительной степени говорит само за себя (и в этом прелесть использования DSL), но у меня все еще есть пост в блоге, поэтому я предоставлю как можно больше подробностей.
Модель клиентского домена
Вы можете думать о клиенте как о соединении двух вещей:
- Доменная модель Кубернетеса .
- DSL вокруг модели.
Модель предметной области — это набор объектов, представляющих данные, которыми обмениваются клиент и Kubernetes / Openshift . Необработанный формат данных — JSON. Эти объекты JSON довольно сложны, а их структура довольно строгая, поэтому создание их вручную — не тривиальная задача.
Нам нужно было иметь способ манипулировать этими объектами JSON в Java (и иметь возможность воспользоваться преимуществами завершения кода и т. Д.), Но также максимально приближаться к исходному формату. Использование POJO-представления объектов JSON можно использовать для манипуляций, но оно не совсем похоже на JSON, а также не совсем подходит для JSON с глубоким вложением. Поэтому вместо этого мы решили создать гибкие компоновщики поверх тех POJO, которые использовали точно такую же структуру с оригинальным JSON.
Например, вот объект JSON службы Kubernetes :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
{ "kind" : "Service" , "metadata" : { "name" : "kubernetes" , "namespace" : "default" , "labels" : { "component" : "apiserver" , "provider" : "kubernetes" } }, "spec" : { "ports" : [ { "name" : "" , "protocol" : "TCP" , "port" : 443 , "targetPort" : 443 } ], "selector" : null , "portalIP" : "172.30.17.2" , "sessionAffinity" : "None" }, "status" : {} } |
Java-эквивалент с использованием Fluent Builders может быть:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
Service srv = new ServiceBuilder() .withNewMetadata() .withName( "kubernetes" ) .addToLabels( "component" , "apiserver" ) .addToLabels( "provider" , "kubernetes" ) .endMetadata() .withNewSpec() .addNewPort() .withProtocol( "TCP" ) .withPort( 443 ) .withNewTargetPort( 443 ) .endPort() .withPortalIP( "172.30.17.2" ) .withSessionAffinity( "None" ) .endSpec() .build(); |
Модель предметной области основана на собственном проекте: модель Кубернетеса из Fabric8 . Модель генерируется из кода Kubernetes и Openshift после долгого процесса:
- Перейти исходная схема преобразования JSON
- Преобразование схемы JSON POJO
- Поколение Свободных Строителей
Свободные строители созданы с помощью крошечного проекта sundrio , о котором я расскажу в следующем посте.
Получение экземпляра клиента
Получение экземпляра клиентского экземпляра по умолчанию довольно тривиально, поскольку предоставляется пустой конструктор. Когда используется пустой конструктор, клиент будет использовать настройки по умолчанию:
- URL Kubernetes
- Системное свойство « kubernetes.master »
- Переменная среды « KUBERNETES_MASTER »
- Из файла « .kube / config » внутри домашнего пользователя.
- Использование DNS: « https: //kubernetes.default.svc «
- Путь к служебной учетной записи « /var/run/secrets/kubernetes.io/serviceaccount/ »
Более точная конфигурация может быть предоставлена путем передачи экземпляра объекта Config .
1
2
3
4
5
6
7
8
|
//Client with custom config Config config = new ConfigBuilder() .withMasterUrl(url) .withTrustCerts( true ) .withOauthToken(mytoken) .build(); KubernetesClient = new DefaultKubernetesClient(config); |
Клиентские расширения и адаптеры
Для поддержки расширений Kubernetes (например, Openshift ) клиент использует понятие Расширения и Адаптера . Идея довольно проста. Клиент расширения расширяет клиент по умолчанию и реализует Расширение . Каждый экземпляр клиента может быть адаптирован к Расширению, если адаптер можно найти с помощью ServiceLoader Java (извините, отец).
Вот пример того, как адаптировать любой экземпляр клиента к экземпляру OpenshiftClient :
1
2
|
KubernetesClient client = new DefaultKubernetesClinet(); OpenShiftClient oc = client.adapt(OpenShiftClient. class ); |
Приведенный выше код будет работать только в том случае, если / oapi существует в списке корневых путей, возвращаемых клиентом Kubernetes (т. Е. Клиент указывает на установку с открытой сменой). Если нет, он выдаст исключение IllegalArugementException.
Если пользователь пишет код, связанный с Openshift, он всегда может напрямую создать экземпляр экземпляра клиента openshift по умолчанию .
1
2
3
4
5
6
7
8
|
//Openshift client with custom config OpenshiftConfig config = new OpenshiftConfigBuilder() .withMasterUrl(url) .withOpenShiftUrl(openshiftUrl) .withTrustCerts( true ) .build(); OpenshiftClient client = new DefaultOpenshiftClient(config); |
Тестирование и издевательство
Насмешка над клиентом, который разговаривает с внешней системой, является довольно распространенным случаем. Когда клиент плоский
(не поддерживает связывание методов). Насмешка тривиальна, и существуют тонны фреймворков, которые можно использовать для этой работы. Однако при использовании DSL все усложняется и требует много стандартного кода для соединения частей. Если причина не очевидна, давайте просто скажем, что с mocks вы определяете поведение mock для каждого вызова метода. DSL, как правило, имеют гораздо больше методов (с меньшим количеством аргументов) по сравнению с эквивалентными плоскими объектами. Это само по себе увеличивает работу, необходимую для определения поведения. Более того, эти методы соединяются вместе, возвращая промежуточные объекты, а это значит, что их тоже нужно смоделировать, что еще больше увеличивает нагрузку и сложность.
Чтобы удалить весь шаблон и сделать насмешку над клиентом довольно простой для использования, мы объединили DSL клиента с DSL среды для насмешек : EasyMock . Это означает, что точкой входа в этот DSL является сам DSL клиента Kubernetes, но методы терминала были изменены, чтобы они возвращали «Установщики ожиданий». Пример должен облегчить понимание этого.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
KubernetesMockClient mock = new KubernetesMockClient(); //Define the behaviour mock.services().inNamespace(or( "default" , "fabric8" )).withName( "fabric8-console-service" ).get().andReturn( new ServiceBuilder() .withNewMetadata().withName( "fabric8-console-service" ).endMetadata() .withNewSpec() .addNewPort() .withProtocol( "TCP" ) .withPort( 80 ) .withNewTargetPort( 9090 ) .endPort() .endSpec() .build() ).anyTimes(); //Get an instance of the client mock KubernetesClient client = mock.replay(); //Use the client Assert.assertNotNull(client.services().inNamespace( "fabric8" ).withName( "fabric8-console-service" ).get()); Assert.assertNotNull(client.services().inNamespace( "default" ).withName( "fabric8-console-service" ).get()); //Verify the client EasyMock.verify(client); |
Фреймворк можно легко комбинировать с другими компонентами Fabric8 , такими как расширение CDI . Вам просто нужно создать метод @Produces, который возвращает макет.
Наслаждайтесь!
Ссылка: | Fabric8 Kubernetes и Openshift Java DSL от нашего партнера по JCG Иоанниса Канеллоса в блоге |