Commit 7a2ef470 authored by Joao Esteves Marcal's avatar Joao Esteves Marcal Committed by Alexandre Lossent
Browse files

LanDB Operator

parent e83b2bac
.vscode/*
secrets.sh
secrets.yaml
\ No newline at end of file
variables:
DOCKERFILE_PATH: build/Dockerfile
include:
- project: 'paas-tools/infrastructure-ci'
file: 'docker-images-ci-templates/DockerImages.gitlab-ci.yml'
---
services: docker
language: python
install:
- pip3 install docker molecule ansible-lint yamllint flake8 openshift jmespath
script:
- molecule test -s test-local
# delegated-domains-provisioner
# LanDB Operator
This is an Ansible operator that consumes information from three CRDs
(`DelegatedDomain`, `DelegatedDomainAlias` and `LandbSet`) to then update LanDB through their SOAP calls.
## How it works
Together with the Ansible roles there is also a Python script that implements all the logic of actually communicating with LanDB SOAP. Hence, once a CRD is created an Ansible role will be used to fetch the necessary information from the CRs and from Openshift to then call the Python script with the right parameters.
Usefulness of the different CRD:
- `DelegatedDomain`: Allows us to publish a delegated domain;
- `DelegatedDomainAlias`: Allows us to publish an alias to a delegated domain;
- `LandbSet`: Allows us to publish a LanDB set that will contain the all the nodes of a cluster filtered by the `labelSelector` provided;
For more information on the capabilities of the script the use can run `python3 roles/files/main.py -h` note that not all [LanDB calls](https://network.cern.ch/sc/soap/6/description.html) are implemented
## Usefull links
- [LanDB SOAP API description](https://network.cern.ch/sc/soap/6/description.html)
- [LanDB SOAP WSDL](https://network.cern.ch/sc/soap/soap.fcgi?v=6&WSDL)
- [Zeep doc](https://docs.python-zeep.org/en/master/client.html) (Python SOAP lib)
- [LanDB Sets](https://landb.cern.ch/landb/portal/sets/displaySets)
- [Ansible Operator doc](https://sdk.operatorframework.io/docs/ansible/quickstart/)
\ No newline at end of file
FROM quay.io/operator-framework/ansible-operator:v0.17.1
# We have to change to USER 0 to be able to install Python packages
# without the flag --user
# If we were not able to use this we would need an SCC to run the container
# as the packages would only be intalled for the user ansible-operator (1001)
# which is outside of the default range of users ID used ranges: [1000800000, 1000809999]
USER 0
# Copy python scrip requirements and install them with pip
COPY requirements.txt ${HOME}/requirements.txt
RUN pip-3.6 install --no-cache-dir -r ${HOME}/requirements.txt
USER 1001
COPY requirements.yml ${HOME}/requirements.yml
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
&& chmod -R ug+rwx ${HOME}/.ansible
COPY watches.yaml ${HOME}/watches.yaml
COPY roles/ ${HOME}/roles/
apiVersion: v2
name: landb-operator
description: Deploys the LanDB Ansible operator
version: 0.1.0
icon: https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/OpenShift-LogoType.svg/1200px-OpenShift-LogoType.svg.png
keywords:
- openshift
- okd4
- landb
- operator
- ansible
maintainers:
- name: CERN IT-CDA-WF
email: openshift-admins@cern.ch
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: delegateddomainaliases.webservices.cern.ch
spec:
group: webservices.cern.ch
names:
kind: DelegatedDomainAlias
listKind: DelegatedDomainAliasList
plural: delegateddomainaliases
singular: delegateddomainalias
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: DelegatedDomainAlias is the Schema for the delegateddomainaliases
API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: DelegatedDomainAliasSpec defines the desired state of DelegatedDomainAlias
properties:
alias:
description: Alias we want to add to the DNS delegated domain
minLength: 1
type: string
domain:
description: DSN delegated domain we want to add the alias to
minLength: 1
type: string
view:
description: View of the desired delegated domain we want to add the alias to
enum:
- internal
- external
type: string
type: object
status:
description: DelegatedDomainAliasStatus defines the observed state of DelegatedDomainAlias
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: delegateddomains.webservices.cern.ch
spec:
group: webservices.cern.ch
names:
kind: DelegatedDomain
listKind: DelegatedDomainList
plural: delegateddomains
singular: delegateddomain
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: DelegatedDomain is the Schema for the delegateddomains API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: DelegatedDomainSpec defines the desired state of DelegatedDomain
properties:
description:
description: Description of the delegated dns domain
minLength: 1
type: string
domain:
description: Domain desired for the delegated dns domain
minLength: 1
type: string
keyname:
description: Keyname allowed to add lanDB delegated dns domain
minLength: 1
type: string
view:
description: View of the desired delegated domain
enum:
- internal
- external
type: string
type: object
status:
description: DelegatedDomainStatus defines the observed state of DelegatedDomain
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: landbsets.webservices.cern.ch
spec:
group: webservices.cern.ch
names:
kind: LandbSet
listKind: LandbSetList
plural: landbsets
singular: landbset
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: LandbSet is the Schema for the landbsets API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: LandbSetSpec defines the desired state of LandbSet
properties:
description:
description: Description of the landb set
minLength: 1
type: string
domain:
description: Domain of landb set https://network.cern.ch/sc/html/help/domain.html
enum:
- GPN
- TN
- EN
minLength: 1
type: string
labelSelector:
description: LabelSelector to filter the nodes that are going to be
added to the set
type: string
setName:
description: SetName name of the set to be created
minLength: 1
type: string
type:
description: Type derives from type of network it can be INTER for internet
or INTRA for intranet
enum:
- INTER
- INTRA
minLength: 1
type: string
type: object
status:
description: LandbSetStatus defines the observed state of LandbSet
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: landb-operator
annotations:
description: The landb operator, is responsible of reconciling DelegatedDomains, DelegatedDomainsAliases and LandbSets
spec:
replicas: 1
selector:
matchLabels:
name: landb-operator
template:
metadata:
labels:
name: landb-operator
spec:
serviceAccountName: landb-operator
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
tolerations:
{{ toYaml .Values.tolerations | indent 8 }}
containers:
- name: landb-operator
image: {{ .Values.image }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
args:
- "--max-workers"
- {{ .Values.maxWorkers | quote }}
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
name: runner
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OPERATOR_NAME
value: "landb-operator"
- name: ANSIBLE_GATHERING
value: explicit
- name: LANDB_USER
valueFrom:
secretKeyRef:
name: landb-operator-credentials
key: user
- name: LANDB_PASSWORD
valueFrom:
secretKeyRef:
name: landb-operator-credentials
key: password
- name: LANDB_RESPONSIBLE
value: {{ .Values.landb.responsible }}
volumes:
- name: runner
emptyDir: {}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: landb-operator
rules:
# Default rules that come with using operator-sdk
# but reviewed and tests to follow the principle of
# least privileges needed
- apiGroups:
- monitoring.coreos.com
resources:
- servicemonitors
verbs:
- get
- create
- apiGroups:
- ""
resources:
- configmaps
- services
- services/finalizers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resourceNames:
- landb-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- apps
resources:
- replicasets
- deployments
verbs:
- get
# Access to all the resources that will be
# managed by this operator
- apiGroups:
- webservices.cern.ch
resources:
- delegateddomains
- delegateddomains/status
- delegateddomainaliases
- delegateddomainaliases/status
- landbsets
- landbsets/status
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
---
# Since nodes are a cluster resource we need a different type
# of resource, we need access to nodes to allow us to build our
# machine sets that we will publish to landb
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app: {{ .Release.Name }}-landb-operator
name: {{ .Release.Name }}-landb-operator
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
\ No newline at end of file
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: landb-operator
subjects:
- kind: ServiceAccount
name: landb-operator
roleRef:
kind: Role
name: landb-operator
apiGroup: rbac.authorization.k8s.io
---
# Here we use .Release.Name as we foresee we might have
# multiple deployments of this operator in different namespaces
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: {{ .Release.Name }}-landb-operator
name: {{ .Release.Name }}-landb-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ .Release.Name }}-landb-operator
subjects:
- kind: ServiceAccount
name: landb-operator
namespace: {{ .Release.Namespace }}
\ No newline at end of file
# Secret that contains the user and password to access landb SOAP
apiVersion: v1
kind: Secret
metadata:
name: landb-operator-credentials
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Release.Name }}
type: Opaque
data:
user: {{ .Values.landb.user | b64enc }}
password: {{ .Values.landb.password | b64enc }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: landb-operator
\ No newline at end of file
# configures the operator deployment
image: gitlab-registry.cern.ch/paas-tools/operators/landb-operator:init
imagePullPolicy: Always
# we want many workers to handle a large number of resources
maxWorkers: 20
# LanDB credentials and responsible of lanDB sets
landb:
user: ""
password: ""
# Person (name, not first Name) or e-group responsible by the lanDB set
responsible: ""
nodeSelector: {}
tolerations: []
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: delegateddomainaliases.webservices.cern.ch
spec:
group: webservices.cern.ch
names:
kind: DelegatedDomainAlias
listKind: DelegatedDomainAliasList
plural: delegateddomainaliases
singular: delegateddomainalias
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: DelegatedDomainAlias is the Schema for the delegateddomainaliases
API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: DelegatedDomainAliasSpec defines the desired state of DelegatedDomainAlias
properties:
alias:
description: Alias we want to add to the DNS delegated domain
minLength: 1
type: string
domain:
description: DSN delegated domain we want to add the alias to
minLength: 1
type: string
view:
description: View of the desired delegated domain we want to add the alias to
enum:
- internal
- external
type: string
type: object
status:
description: DelegatedDomainAliasStatus defines the observed state of DelegatedDomainAlias
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: delegateddomains.webservices.cern.ch
spec:
group: webservices.cern.ch
names:
kind: DelegatedDomain
listKind: DelegatedDomainList
plural: delegateddomains
singular: delegateddomain
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: DelegatedDomain is the Schema for the delegateddomains API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object