Add zuul-registry deployment
This change adds an optional registry configuration to the spec: registry: image: docker.io/zuul/zuul-registry:latest count: 0 storage-size: 20 public-url: https://registry:9000 The operator expect a {{ cr_name }}-registry-tls secret to be provided for tls and user configuration. If the secret is missing, the operator creates self signed certificates and generates the user password. Depends-On: https://review.opendev.org/710644 Change-Id: I0c054485b0ad01d53ddcff93f7bcbf34d1810325
This commit is contained in:
parent
4a12041754
commit
c6d35be4d6
@ -28,6 +28,7 @@
|
|||||||
allowed-projects: zuul/zuul-operator
|
allowed-projects: zuul/zuul-operator
|
||||||
requires:
|
requires:
|
||||||
- zuul-container-image
|
- zuul-container-image
|
||||||
|
- zuul-registry-container-image
|
||||||
- nodepool-container-image
|
- nodepool-container-image
|
||||||
provides:
|
provides:
|
||||||
- zuul-operator-container-image
|
- zuul-operator-container-image
|
||||||
|
@ -83,6 +83,20 @@ let Schemas =
|
|||||||
}
|
}
|
||||||
, default = { image = None Text, count = None Natural }
|
, default = { image = None Text, count = None Natural }
|
||||||
}
|
}
|
||||||
|
, Registry =
|
||||||
|
{ Type =
|
||||||
|
{ image : Optional Text
|
||||||
|
, count : Optional Natural
|
||||||
|
, storage-size : Optional Natural
|
||||||
|
, public-url : Optional Text
|
||||||
|
}
|
||||||
|
, default =
|
||||||
|
{ image = None Text
|
||||||
|
, count = None Natural
|
||||||
|
, storage-size = None Natural
|
||||||
|
, public-url = None Text
|
||||||
|
}
|
||||||
|
}
|
||||||
, Launcher =
|
, Launcher =
|
||||||
{ Type = { image : Optional Text, config : UserSecret }
|
{ Type = { image : Optional Text, config : UserSecret }
|
||||||
, default.image = None Text
|
, default.image = None Text
|
||||||
@ -128,6 +142,7 @@ let Input =
|
|||||||
, executor : Schemas.Executor.Type
|
, executor : Schemas.Executor.Type
|
||||||
, web : Schemas.Web.Type
|
, web : Schemas.Web.Type
|
||||||
, scheduler : Schemas.Scheduler.Type
|
, scheduler : Schemas.Scheduler.Type
|
||||||
|
, registry : Schemas.Registry.Type
|
||||||
, launcher : Schemas.Launcher.Type
|
, launcher : Schemas.Launcher.Type
|
||||||
, database : Optional UserSecret
|
, database : Optional UserSecret
|
||||||
, zookeeper : Optional UserSecret
|
, zookeeper : Optional UserSecret
|
||||||
@ -142,6 +157,7 @@ let Input =
|
|||||||
, merger = Schemas.Merger.default
|
, merger = Schemas.Merger.default
|
||||||
, web = Schemas.Web.default
|
, web = Schemas.Web.default
|
||||||
, scheduler = Schemas.Scheduler.default
|
, scheduler = Schemas.Scheduler.default
|
||||||
|
, registry = Schemas.Registry.default
|
||||||
, executor = Schemas.Executor.default
|
, executor = Schemas.Executor.default
|
||||||
, launcher = Schemas.Launcher.default
|
, launcher = Schemas.Launcher.default
|
||||||
, connections = Schemas.Connections.default
|
, connections = Schemas.Connections.default
|
||||||
|
@ -12,6 +12,14 @@ The resources expect secrets to be created by the zuul ansible role:
|
|||||||
* `client.pem`
|
* `client.pem`
|
||||||
* `client.key`
|
* `client.key`
|
||||||
|
|
||||||
|
* `${name}-registry-tls` with:
|
||||||
|
|
||||||
|
* `cert.pem`
|
||||||
|
* `cert.key`
|
||||||
|
* `secret` a password
|
||||||
|
* `username` the user name with write access
|
||||||
|
* `password` the user password
|
||||||
|
|
||||||
* `${name}-database-password` with a `password` key, (unless an input.database db uri is provided).
|
* `${name}-database-password` with a `password` key, (unless an input.database db uri is provided).
|
||||||
-}
|
-}
|
||||||
let Prelude = ../Prelude.dhall
|
let Prelude = ../Prelude.dhall
|
||||||
@ -72,6 +80,11 @@ let {- The Kubernetes resources of a Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let DefaultNat =
|
||||||
|
\(value : Optional Natural)
|
||||||
|
-> \(default : Natural)
|
||||||
|
-> merge { None = default, Some = \(some : Natural) -> some } value
|
||||||
|
|
||||||
let DefaultText =
|
let DefaultText =
|
||||||
\(value : Optional Text)
|
\(value : Optional Text)
|
||||||
-> \(default : Text)
|
-> \(default : Text)
|
||||||
@ -568,6 +581,38 @@ in \(input : Input)
|
|||||||
[ { path = "zuul.conf", content = mkZuulConf input zk-hosts } ]
|
[ { path = "zuul.conf", content = mkZuulConf input zk-hosts } ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let etc-zuul-registry =
|
||||||
|
Volume::{
|
||||||
|
, name = input.name ++ "-secret-registry"
|
||||||
|
, dir = "/etc/zuul"
|
||||||
|
, files =
|
||||||
|
[ { path = "registry.yaml"
|
||||||
|
, content =
|
||||||
|
let public-url =
|
||||||
|
DefaultText
|
||||||
|
input.registry.public-url
|
||||||
|
"https://registry:9000"
|
||||||
|
|
||||||
|
in ''
|
||||||
|
registry:
|
||||||
|
address: '0.0.0.0'
|
||||||
|
port: 9000
|
||||||
|
public-url: ${public-url}
|
||||||
|
tls-cert: /etc/zuul-registry/cert.pem
|
||||||
|
tls-key: /etc/zuul-registry/cert.key
|
||||||
|
secret: "%(ZUUL_REGISTRY_secret)"
|
||||||
|
storage:
|
||||||
|
driver: filesystem
|
||||||
|
root: /var/lib/zuul
|
||||||
|
users:
|
||||||
|
- name: "%(ZUUL_REGISTRY_username)"
|
||||||
|
pass: "%(ZUUL_REGISTRY_password)"
|
||||||
|
access: write
|
||||||
|
''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
let etc-nodepool =
|
let etc-nodepool =
|
||||||
Volume::{
|
Volume::{
|
||||||
, name = input.name ++ "-secret-nodepool"
|
, name = input.name ++ "-secret-nodepool"
|
||||||
@ -876,6 +921,72 @@ in \(input : Input)
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
, Registry =
|
||||||
|
let registry-volumes =
|
||||||
|
[ etc-zuul-registry
|
||||||
|
, Volume::{
|
||||||
|
, name = input.name ++ "-registry-tls"
|
||||||
|
, dir = "/etc/zuul-registry"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
let registry-env =
|
||||||
|
mkEnvVarSecret
|
||||||
|
( Prelude.List.map
|
||||||
|
Text
|
||||||
|
EnvSecret
|
||||||
|
( \(key : Text)
|
||||||
|
-> { name = "ZUUL_REGISTRY_${key}"
|
||||||
|
, key = key
|
||||||
|
, secret =
|
||||||
|
input.name ++ "-registry-tls"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
[ "secret", "username", "password" ]
|
||||||
|
)
|
||||||
|
|
||||||
|
in KubernetesComponent::{
|
||||||
|
, Service = Some
|
||||||
|
(mkService "registry" "registry" 9000)
|
||||||
|
, StatefulSet = Some
|
||||||
|
( mkStatefulSet
|
||||||
|
Component::{
|
||||||
|
, name = "registry"
|
||||||
|
, count =
|
||||||
|
DefaultNat input.registry.count 0
|
||||||
|
, data-dir = zuul-data-dir
|
||||||
|
, volumes = registry-volumes
|
||||||
|
, claim-size =
|
||||||
|
DefaultNat
|
||||||
|
input.registry.storage-size
|
||||||
|
20
|
||||||
|
, container = Kubernetes.Container::{
|
||||||
|
, name = "registry"
|
||||||
|
, image = zuul-image "registry"
|
||||||
|
, args = Some
|
||||||
|
[ "zuul-registry"
|
||||||
|
, "-c"
|
||||||
|
, "/etc/zuul/registry.yaml"
|
||||||
|
, "serve"
|
||||||
|
]
|
||||||
|
, imagePullPolicy = Some "IfNotPresent"
|
||||||
|
, ports = Some
|
||||||
|
[ Kubernetes.ContainerPort::{
|
||||||
|
, name = Some "registry"
|
||||||
|
, containerPort = 9000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, env = Some registry-env
|
||||||
|
, volumeMounts = Some
|
||||||
|
( mkVolumeMount
|
||||||
|
( registry-volumes
|
||||||
|
# zuul-data-dir
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
, Nodepool =
|
, Nodepool =
|
||||||
let nodepool-image =
|
let nodepool-image =
|
||||||
@ -1008,13 +1119,17 @@ in \(input : Input)
|
|||||||
{ apiVersion = "v1"
|
{ apiVersion = "v1"
|
||||||
, kind = "List"
|
, kind = "List"
|
||||||
, items =
|
, items =
|
||||||
[ mkSecret etc-zuul, mkSecret etc-nodepool ]
|
[ mkSecret etc-zuul
|
||||||
|
, mkSecret etc-nodepool
|
||||||
|
, mkSecret etc-zuul-registry
|
||||||
|
]
|
||||||
# mkUnion Components.Backend.Database
|
# mkUnion Components.Backend.Database
|
||||||
# mkUnion Components.Backend.ZooKeeper
|
# mkUnion Components.Backend.ZooKeeper
|
||||||
# mkUnion Components.Zuul.Scheduler
|
# mkUnion Components.Zuul.Scheduler
|
||||||
# mkUnion Components.Zuul.Executor
|
# mkUnion Components.Zuul.Executor
|
||||||
# mkUnion Components.Zuul.Web
|
# mkUnion Components.Zuul.Web
|
||||||
# mkUnion Components.Zuul.Merger
|
# mkUnion Components.Zuul.Merger
|
||||||
|
# mkUnion Components.Zuul.Registry
|
||||||
# mkUnion Components.Nodepool.Launcher
|
# mkUnion Components.Nodepool.Launcher
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ spec:
|
|||||||
scheduler:
|
scheduler:
|
||||||
config:
|
config:
|
||||||
secretName: zuul-yaml-conf
|
secretName: zuul-yaml-conf
|
||||||
|
registry:
|
||||||
|
count: 1
|
||||||
launcher:
|
launcher:
|
||||||
config:
|
config:
|
||||||
secretName: nodepool-yaml-conf
|
secretName: nodepool-yaml-conf
|
||||||
|
@ -13,6 +13,8 @@ merger:
|
|||||||
scheduler:
|
scheduler:
|
||||||
config:
|
config:
|
||||||
secretName: zuul-yaml-conf
|
secretName: zuul-yaml-conf
|
||||||
|
registry:
|
||||||
|
count: 0
|
||||||
launcher:
|
launcher:
|
||||||
config:
|
config:
|
||||||
secretName: nodepool-yaml-conf
|
secretName: nodepool-yaml-conf
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
command: python3 -m pip install --user openshift
|
command: python3 -m pip install --user openshift
|
||||||
roles:
|
roles:
|
||||||
- role: clear-firewall
|
- role: clear-firewall
|
||||||
|
- role: install-podman
|
||||||
- role: install-kubernetes
|
- role: install-kubernetes
|
||||||
vars:
|
vars:
|
||||||
minikube_dns_resolvers:
|
minikube_dns_resolvers:
|
||||||
|
@ -132,6 +132,8 @@
|
|||||||
kubernetes:
|
kubernetes:
|
||||||
secretName: nodepool-kube-config
|
secretName: nodepool-kube-config
|
||||||
key: kube.config
|
key: kube.config
|
||||||
|
registry:
|
||||||
|
count: 1
|
||||||
|
|
||||||
- name: Wait maximum 4 minutes for the scheduler deployment
|
- name: Wait maximum 4 minutes for the scheduler deployment
|
||||||
shell: |
|
shell: |
|
||||||
@ -164,3 +166,27 @@
|
|||||||
- name: Wait an extra 2 minutes for the services to settle
|
- name: Wait an extra 2 minutes for the services to settle
|
||||||
pause:
|
pause:
|
||||||
minutes: 2
|
minutes: 2
|
||||||
|
|
||||||
|
- name: Test the registry
|
||||||
|
block:
|
||||||
|
- name: Get registry service ip
|
||||||
|
command: kubectl get svc registry -o "jsonpath={.spec.clusterIP}"
|
||||||
|
register: _registry_ip
|
||||||
|
|
||||||
|
- name: Add registry to /etc/hosts
|
||||||
|
become: yes
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/hosts
|
||||||
|
regexp: "^.* registry$"
|
||||||
|
line: "{{ _registry_ip.stdout_lines[0] }} registry"
|
||||||
|
|
||||||
|
- name: Get registry password
|
||||||
|
command: kubectl get secret zuul-registry-tls -o "jsonpath={.data.password}"
|
||||||
|
register: _registry_password
|
||||||
|
|
||||||
|
- name: Test registry login
|
||||||
|
command: >
|
||||||
|
podman login
|
||||||
|
--tls-verify=false registry:9000
|
||||||
|
-u zuul
|
||||||
|
-p "{{ _registry_password.stdout_lines[0] | b64decode }}"
|
||||||
|
29
roles/zuul-ensure-registry-tls/tasks/main.yaml
Normal file
29
roles/zuul-ensure-registry-tls/tasks/main.yaml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
- name: Check if registry tls cert exists
|
||||||
|
set_fact:
|
||||||
|
registry_certs: "{{ lookup('k8s', api_version='v1', kind='Secret', namespace=namespace, resource_name=zuul_name + '-registry-tls') }}"
|
||||||
|
|
||||||
|
- name: Generate and store certs
|
||||||
|
when: registry_certs.data is not defined
|
||||||
|
block:
|
||||||
|
- name: Generate certs
|
||||||
|
command: "{{ item }}"
|
||||||
|
loop:
|
||||||
|
# Server
|
||||||
|
- "openssl req -new -newkey rsa:2048 -nodes -keyout registry-{{ zuul_name }}.key -out registry-{{ zuul_name }}.csr -subj '/C=US/ST=Texas/L=Austin/O=Zuul/CN=server-{{ zuul_name }}'"
|
||||||
|
- "openssl x509 -req -days 3650 -in registry-{{ zuul_name }}.csr -out registry-{{ zuul_name }}.pem -CA ca-{{ zuul_name }}.pem -CAkey ca-{{ zuul_name }}.key -CAcreateserial"
|
||||||
|
|
||||||
|
- name: Create k8s secret
|
||||||
|
k8s:
|
||||||
|
state: "{{ state }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ zuul_name }}-registry-tls"
|
||||||
|
stringData:
|
||||||
|
username: "zuul"
|
||||||
|
password: "{{ lookup('password', '/dev/null') }}"
|
||||||
|
secret: "{{ lookup('password', '/dev/null') }}"
|
||||||
|
cert.key: "{{ lookup('file', 'registry-' + zuul_name + '.key') }}"
|
||||||
|
cert.pem: "{{ lookup('file', 'registry-' + zuul_name + '.pem') }}"
|
@ -10,4 +10,5 @@ raw_spec: "{{ vars['_operator_zuul-ci_org_zuul_spec'] | default(spec) }}"
|
|||||||
# Provide sensible default for non optional attributes:
|
# Provide sensible default for non optional attributes:
|
||||||
spec_defaults:
|
spec_defaults:
|
||||||
web: {}
|
web: {}
|
||||||
|
registry: {}
|
||||||
externalConfig: {}
|
externalConfig: {}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
- zuul-lookup-conf
|
- zuul-lookup-conf
|
||||||
- zuul-ensure-gearman-tls
|
- zuul-ensure-gearman-tls
|
||||||
|
|
||||||
|
- include_role:
|
||||||
|
name: zuul-ensure-registry-tls
|
||||||
|
when: (raw_spec['registry']['count'] | default(0)) | int > 0
|
||||||
|
|
||||||
- include_role:
|
- include_role:
|
||||||
name: zuul-ensure-database-password
|
name: zuul-ensure-database-password
|
||||||
# when the user does not provide a db_uri
|
# when the user does not provide a db_uri
|
||||||
|
Loading…
x
Reference in New Issue
Block a user