Add service CRD
This introduces a CRD for enabling/removing services from Keystone, it also introduces a basic DevStack plugin framework so that we can test things from it. It also adds a framework for the operator to setup SDK clients. Change-Id: I183e560c6b32de2ce7adefeb1daa26def675bbe3
This commit is contained in:
parent
923c8b3035
commit
f49b79fe40
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,3 +28,4 @@ doc/build
|
||||
__pycache__
|
||||
*.egg*
|
||||
.stestr
|
||||
openrc
|
||||
|
2
bindep.txt
Normal file
2
bindep.txt
Normal file
@ -0,0 +1,2 @@
|
||||
gcc [compile]
|
||||
libc-dev [compile]
|
24
chart/crds/identity.openstack.org_services.yaml
Normal file
24
chart/crds/identity.openstack.org_services.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: services.identity.openstack.org
|
||||
spec:
|
||||
group: identity.openstack.org
|
||||
names:
|
||||
kind: Service
|
||||
listKind: ServiceList
|
||||
plural: services
|
||||
singular: service
|
||||
scope: Cluster
|
||||
version: v1alpha1
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
@ -109,6 +109,26 @@ rules:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- identity.openstack.org
|
||||
resources:
|
||||
- services
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- identity.openstack.org
|
||||
resources:
|
||||
- services/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- infrastructure.vexxhost.cloud
|
||||
resources:
|
||||
|
@ -8,8 +8,6 @@
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if .Values.crd.dns }}
|
||||
{{- range $path, $bytes := .Files.Glob "crds/dns.openstack.org*.yaml" }}
|
||||
{{ $.Files.Get $path }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- range $path, $bytes := .Files.Glob "crds/*.openstack.org_*.yaml" }}
|
||||
{{ $.Files.Get $path }}
|
||||
{{- end }}
|
||||
|
@ -21,6 +21,11 @@ spec:
|
||||
- name: operator
|
||||
image: vexxhost/openstack-operator:latest
|
||||
command: ["/usr/local/bin/kopf"]
|
||||
{{- with .Values.secretName }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ . }}
|
||||
{{- end }}
|
||||
args:
|
||||
- run
|
||||
- -m
|
||||
@ -28,6 +33,8 @@ spec:
|
||||
- -m
|
||||
- openstack_operator.memcached
|
||||
- -m
|
||||
- openstack_operator.openstack.identity.services
|
||||
- -m
|
||||
- openstack_operator.rabbitmq
|
||||
resources:
|
||||
limits:
|
||||
|
2
chart/test-values.yaml
Normal file
2
chart/test-values.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
---
|
||||
secretName: devstack
|
8
config/samples/identity_v1alpha1_services.yaml
Normal file
8
config/samples/identity_v1alpha1_services.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
apiVersion: identity.openstack.org/v1alpha1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: heat
|
||||
spec:
|
||||
type: orchestration
|
||||
description: Heat Orchestration Service
|
31
devstack/override-defaults
Normal file
31
devstack/override-defaults
Normal file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Gets or creates service
|
||||
# Usage: get_or_create_service <name> <type> <description>
|
||||
function get_or_create_service {
|
||||
cat <<EOF | kubectl apply -f-
|
||||
---
|
||||
apiVersion: identity.openstack.org/v1alpha1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ${1//_/-}
|
||||
spec:
|
||||
type: $2
|
||||
description: $3
|
||||
EOF
|
||||
}
|
||||
export -f get_or_create_service
|
51
devstack/plugin.sh
Executable file
51
devstack/plugin.sh
Executable file
@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
function copy_minikube_config {
|
||||
mkdir ~stack/.kube
|
||||
|
||||
sudo cp ~zuul/.kube/config ~stack/.kube/config
|
||||
sudo cp ~zuul/.minikube/ca.crt ~stack/.kube/ca.crt
|
||||
sudo cp ~zuul/.minikube/profiles/minikube/client.crt ~stack/.kube/client.crt
|
||||
sudo cp ~zuul/.minikube/profiles/minikube/client.key ~stack/.kube/client.key
|
||||
sudo chown -Rv stack:stack ~stack/.kube
|
||||
|
||||
sed -i s%/home/zuul/.minikube/profiles/minikube%/opt/stack/.kube% ~/.kube/config
|
||||
sed -i s%/home/zuul/.minikube/ca.crt%/opt/stack/.kube/ca.crt% ~/.kube/config
|
||||
|
||||
kubectl cluster-info
|
||||
}
|
||||
|
||||
if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
|
||||
copy_minikube_config
|
||||
|
||||
elif [[ "$1" == "stack" && "$2" == "install" ]]; then
|
||||
:
|
||||
|
||||
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
|
||||
:
|
||||
|
||||
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
|
||||
:
|
||||
fi
|
||||
|
||||
if [[ "$1" == "unstack" ]]; then
|
||||
:
|
||||
fi
|
||||
|
||||
if [[ "$1" == "clean" ]]; then
|
||||
:
|
||||
fi
|
20
devstack/settings
Normal file
20
devstack/settings
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
define_plugin openstack-operator
|
||||
|
||||
disable_service etcd3
|
||||
disable_service rabbit
|
0
openstack_operator/openstack/__init__.py
Normal file
0
openstack_operator/openstack/__init__.py
Normal file
0
openstack_operator/openstack/identity/__init__.py
Normal file
0
openstack_operator/openstack/identity/__init__.py
Normal file
79
openstack_operator/openstack/identity/services.py
Normal file
79
openstack_operator/openstack/identity/services.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Services Operator
|
||||
|
||||
This operator helps manage the creation and removal of services inside
|
||||
Keystone using custom resources.
|
||||
"""
|
||||
|
||||
import kopf
|
||||
|
||||
from openstack_operator import utils
|
||||
|
||||
|
||||
def _get_service(conn, name, service_type):
|
||||
"""Get a service from Keystone
|
||||
|
||||
This method will retrieve the service from Keystone, raise an error if it
|
||||
found more than one or return None if it couldn't find it
|
||||
"""
|
||||
|
||||
services = conn.search_services(name_or_id=name,
|
||||
filters={"type": service_type})
|
||||
|
||||
if len(services) > 1:
|
||||
raise RuntimeError("Found multiple services with name and type")
|
||||
if len(services) == 0:
|
||||
return None
|
||||
return services[0]
|
||||
|
||||
|
||||
@kopf.on.resume('identity.openstack.org', 'v1alpha1', 'services')
|
||||
@kopf.on.create('identity.openstack.org', 'v1alpha1', 'services')
|
||||
def create_or_resume(name, spec, **_):
|
||||
"""Create or resume controller
|
||||
|
||||
This function runs when a new resource is created or when the controller
|
||||
is first started. It creates or updates the appropriate service.
|
||||
"""
|
||||
|
||||
conn = utils.get_openstack_connection()
|
||||
service = _get_service(conn, name, spec["type"])
|
||||
|
||||
if service:
|
||||
service = conn.update_service(service.id, name=name,
|
||||
type=spec["type"],
|
||||
description=spec["description"])
|
||||
return
|
||||
|
||||
service = conn.create_service(name=name, type=spec["type"],
|
||||
description=spec["description"])
|
||||
|
||||
|
||||
@kopf.on.delete('identity.openstack.org', 'v1alpha1', 'services')
|
||||
def delete(name, spec, **_):
|
||||
"""Delete a service
|
||||
|
||||
This function runs when the servce CR is deleted and removes the record
|
||||
from Keystone.
|
||||
"""
|
||||
|
||||
conn = utils.get_openstack_connection()
|
||||
service = _get_service(conn, name, spec["type"])
|
||||
|
||||
if not service:
|
||||
return
|
||||
|
||||
conn.delete_service(service)
|
@ -23,7 +23,9 @@ import operator
|
||||
import os
|
||||
|
||||
import jinja2
|
||||
import openstack
|
||||
import kopf
|
||||
from pbr import version
|
||||
import pykube
|
||||
import yaml
|
||||
|
||||
@ -31,6 +33,7 @@ from openstack_operator import objects
|
||||
|
||||
|
||||
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
VERSION = version.VersionInfo('openstack_operator').version_string()
|
||||
|
||||
|
||||
def to_yaml(value):
|
||||
@ -147,3 +150,9 @@ def get_ready_pod_ips(namespace, selector):
|
||||
servers = sorted([p.obj["status"]["podIP"] for p in ready_pods])
|
||||
|
||||
return servers
|
||||
|
||||
|
||||
def get_openstack_connection():
|
||||
"""Get an instance of OpenStack SDK."""
|
||||
return openstack.connect(cloud="envvars", app_name='openstack-operator',
|
||||
app_version=VERSION)
|
||||
|
@ -55,6 +55,9 @@
|
||||
name: write-devstack-local-conf
|
||||
vars:
|
||||
devstack_localrc: "{{ _devstack_localrc | combine(_devstack_localrc_extra) }}"
|
||||
- name: Copy Zuul repo into devstack working directory
|
||||
become: true
|
||||
command: rsync -av src/opendev.org/vexxhost/openstack-operator /opt/stack
|
||||
|
||||
# Changes that run through devstack-tempest are likely to have an impact on
|
||||
# the devstack part of the job, so we keep devstack in the main play to
|
||||
|
@ -15,11 +15,30 @@
|
||||
# limitations under the License.
|
||||
|
||||
- hosts: all
|
||||
pre_tasks:
|
||||
- name: Create secret for DevStack credentials
|
||||
shell: |
|
||||
cat <<EOF | kubectl apply -f-
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: devstack
|
||||
stringData:
|
||||
OS_INSECURE: "true"
|
||||
OS_AUTH_URL: http://{{ hostvars['controller']['nodepool']['private_ipv4'] }}/identity
|
||||
OS_AUTH_TYPE: password
|
||||
OS_PROJECT_DOMAIN_ID: default
|
||||
OS_PROJECT_NAME: admin
|
||||
OS_USER_DOMAIN_ID: default
|
||||
OS_USERNAME: admin
|
||||
OS_PASSWORD: secretadmin
|
||||
EOF
|
||||
roles:
|
||||
- role: helm-template
|
||||
vars:
|
||||
helm_release_name: openstack-operator
|
||||
helm_chart: ./chart
|
||||
helm_values_file: ./chart/test-values.yaml
|
||||
tasks:
|
||||
# TODO(mnaser): Generate all manifests and ensure git is not dirty
|
||||
- include_tasks: tests/memcached.yaml
|
||||
|
@ -1,2 +1,3 @@
|
||||
kopf
|
||||
Jinja2
|
||||
openstacksdk
|
||||
|
2
tox.ini
2
tox.ini
@ -4,6 +4,8 @@ envlist = py37
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
passenv =
|
||||
OS_*
|
||||
deps =
|
||||
-rtest-requirements.txt
|
||||
-rrequirements.txt
|
||||
|
@ -10,6 +10,8 @@
|
||||
devstack_services:
|
||||
etcd3: false
|
||||
rabbit: false
|
||||
devstack_plugins:
|
||||
openstack-operator: https://opendev.org/vexxhost/openstack-operator
|
||||
docker_use_buildset_registry: true
|
||||
minikube_dns_resolvers: [1.1.1.1, 8.8.8.8]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user