вступление
В первых выпусках 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 clientKubernetesClient client = new DefaultKubernetesClient();//Create a serviceService myservice = ...;client.services().inNamespace("fabric8").create(myservice);//Create a service inlineService jenkins = client.services().inNamespace("fabric8").createNew() .withNewMetadata() .withName("jenkins") .addToLabels("component", "jenkins") .endMetadata() .done();//List servicesServiceList serviceList = client.services().inNamespace("fabric8").list();//Watch servicesclient.services().inNamespace("fabric8").watch(new Watcher<Service>() { @Override public void eventReceived(Action action, Service resource) { logger.info("{}: {}", action, resource); }});//Delete by labelBoolean deleted = client.services().withLabel("component", "jenkins").delete();//Close clientclient.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 configConfig 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 configOpenshiftConfig 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 clientAssert.assertNotNull(client.services().inNamespace("fabric8").withName("fabric8-console-service").get());Assert.assertNotNull(client.services().inNamespace("default").withName("fabric8-console-service").get());//Verify the clientEasyMock.verify(client); |
Фреймворк можно легко комбинировать с другими компонентами Fabric8 , такими как расширение CDI . Вам просто нужно создать метод @Produces, который возвращает макет.
Наслаждайтесь!
| Ссылка: | Fabric8 Kubernetes и Openshift Java DSL от нашего партнера по JCG Иоанниса Канеллоса в блоге |