From f49b79fe40867dae2373bfb9ac7a306dd13fb49d Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Sat, 25 Apr 2020 09:06:57 -0400 Subject: [PATCH] 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 --- .gitignore | 1 + bindep.txt | 2 + .../crds/identity.openstack.org_services.yaml | 24 ++++++ chart/templates/clusterrole.yaml | 20 +++++ chart/templates/crds.yaml | 8 +- chart/templates/deployment.yaml | 7 ++ chart/test-values.yaml | 2 + .../samples/identity_v1alpha1_services.yaml | 8 ++ devstack/override-defaults | 31 ++++++++ devstack/plugin.sh | 51 ++++++++++++ devstack/settings | 20 +++++ openstack_operator/openstack/__init__.py | 0 .../openstack/identity/__init__.py | 0 .../openstack/identity/services.py | 79 +++++++++++++++++++ openstack_operator/utils.py | 9 +++ playbooks/functional/devstack.yaml | 3 + playbooks/functional/run.yaml | 19 +++++ requirements.txt | 1 + tox.ini | 2 + zuul.d/functional-jobs.yaml | 2 + 20 files changed, 284 insertions(+), 5 deletions(-) create mode 100644 bindep.txt create mode 100644 chart/crds/identity.openstack.org_services.yaml create mode 100644 chart/test-values.yaml create mode 100644 config/samples/identity_v1alpha1_services.yaml create mode 100644 devstack/override-defaults create mode 100755 devstack/plugin.sh create mode 100644 devstack/settings create mode 100644 openstack_operator/openstack/__init__.py create mode 100644 openstack_operator/openstack/identity/__init__.py create mode 100644 openstack_operator/openstack/identity/services.py diff --git a/.gitignore b/.gitignore index 109fa9c3..ccae98f5 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ doc/build __pycache__ *.egg* .stestr +openrc diff --git a/bindep.txt b/bindep.txt new file mode 100644 index 00000000..64b038ba --- /dev/null +++ b/bindep.txt @@ -0,0 +1,2 @@ +gcc [compile] +libc-dev [compile] diff --git a/chart/crds/identity.openstack.org_services.yaml b/chart/crds/identity.openstack.org_services.yaml new file mode 100644 index 00000000..9a4d9d71 --- /dev/null +++ b/chart/crds/identity.openstack.org_services.yaml @@ -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: [] diff --git a/chart/templates/clusterrole.yaml b/chart/templates/clusterrole.yaml index 7bea1980..23314dad 100644 --- a/chart/templates/clusterrole.yaml +++ b/chart/templates/clusterrole.yaml @@ -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: diff --git a/chart/templates/crds.yaml b/chart/templates/crds.yaml index d9956984..441b6d19 100644 --- a/chart/templates/crds.yaml +++ b/chart/templates/crds.yaml @@ -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 -}} \ No newline at end of file +{{- range $path, $bytes := .Files.Glob "crds/*.openstack.org_*.yaml" }} +{{ $.Files.Get $path }} +{{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index 80e7f188..1bd8bc2e 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -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: diff --git a/chart/test-values.yaml b/chart/test-values.yaml new file mode 100644 index 00000000..6916598d --- /dev/null +++ b/chart/test-values.yaml @@ -0,0 +1,2 @@ +--- +secretName: devstack diff --git a/config/samples/identity_v1alpha1_services.yaml b/config/samples/identity_v1alpha1_services.yaml new file mode 100644 index 00000000..3efddd40 --- /dev/null +++ b/config/samples/identity_v1alpha1_services.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: identity.openstack.org/v1alpha1 +kind: Service +metadata: + name: heat +spec: + type: orchestration + description: Heat Orchestration Service diff --git a/devstack/override-defaults b/devstack/override-defaults new file mode 100644 index 00000000..a7ef98ef --- /dev/null +++ b/devstack/override-defaults @@ -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 +function get_or_create_service { + cat < 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) diff --git a/openstack_operator/utils.py b/openstack_operator/utils.py index 6aaee014..e7ae264f 100644 --- a/openstack_operator/utils.py +++ b/openstack_operator/utils.py @@ -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) diff --git a/playbooks/functional/devstack.yaml b/playbooks/functional/devstack.yaml index 4205f206..e7c2b5d0 100644 --- a/playbooks/functional/devstack.yaml +++ b/playbooks/functional/devstack.yaml @@ -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 diff --git a/playbooks/functional/run.yaml b/playbooks/functional/run.yaml index 4abd9a18..96820e42 100755 --- a/playbooks/functional/run.yaml +++ b/playbooks/functional/run.yaml @@ -15,11 +15,30 @@ # limitations under the License. - hosts: all + pre_tasks: + - name: Create secret for DevStack credentials + shell: | + cat <