diff --git a/README.md b/README.md index 545d0525843ec6c0c3f88397d344ca137671b8f3..3433878852c8ad75a1532911cfdb53e6ca3a7a7e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # LanDB Operator -This is an Ansible operator that consumes information from three CRDs +This is an Ansible operator that consumes information from three CRDs (`DelegatedDomain`, `DelegatedDomainAlias` and `LandbSet`) to then update LanDB through their SOAP calls. +Note that this Ansible Operator is based on [version 0.17.1](https://v0-17-x.sdk.operatorframework.io/docs/ansible/) ("pre-v1.0.0"). + ## 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. @@ -11,7 +13,10 @@ 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; +- `LandbSet`: Allows us to publish a LanDB set that will contain the all the cluster's public-facing IP addresses: nodes and services of type `LoadBalancer`. + Optionally filter nodes with `labelSelector` and filter Loadbalancer services with `loadbalancerLabelSelector` and `loadbalancerNamespace`. + If no label selector or namespace are specified then all resources will be added to the LanDB set. + You can use a dummy label selector like `none=` if you don't want to include any nodes / loadbalancers in the set. 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 @@ -20,7 +25,7 @@ For more information on the capabilities of the script the use can run `python3 The landb-operator is basically a wrapper to a python script that implements multiple commands to run against the LanDB SOAP API hence, if we have a valid and working deployment of the operator we are able to access the pod/container and run ourselves some manual commands in case we need to preform some emergency operations or simply clean up some unused resources from LanDB. #### Accessing the pod/container -To acces the pod/container where the landb-operator we have to first get the name of the pod, for that we can run, +To acces the pod/container where the landb-operator we have to first get the name of the pod, for that we can run, `oc get pods -n openshift-cern-landb`. After we have the pod name we can spawn a bash shell on it with the command: ```bash oc exec -it ${LANDB_POD_NAME} -n openshift-cern-landb -- /bin/bash @@ -32,7 +37,7 @@ Now we are ready to directly run any command in the python script. #### Listing all the LanDB sets -LanDB only provides us with a SOAP call that allows us to search through all the LanDB sets names that match a given pattern. We can do this by +LanDB only provides us with a SOAP call that allows us to search through all the LanDB sets names that match a given pattern. We can do this by running the following command. ```bash @@ -44,7 +49,7 @@ Since all our OKD4 clusters start with the name "IT OKD" we can list them all wi python3.6 ${HOME}/roles/files/main.py --landb-user ${LANDB_USER} --landb-password ${LANDB_PASSWORD} --command set-search --landb-set-name "%it okd%" ``` -#### Get more information about a lanDB Set +#### Get more information about a LanDB Set If we want to get more information about a set we can run: ```bash @@ -91,10 +96,11 @@ python3.6 ${HOME}/roles/files/main.py --landb-user ${LANDB_USER} --landb-passwor The `--unprotected-command` flag is necessary as this command is protected by an owership string. -## Usefull links +## Useful 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 +- [Ansible Operator Quickstart](https://v0-17-x.sdk.operatorframework.io/docs/ansible/quickstart/) +- [Ansible Operator Development](https://v0-17-x.sdk.operatorframework.io/docs/ansible/development-tips/) diff --git a/build/Dockerfile b/build/Dockerfile index bf778acd6485fb88daf75ab4bc8b44629a7bce7e..8ad772932fc38df5c8c93613d9b721b48be66057 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,3 +1,5 @@ +FROM quay.io/openshift/origin-cli:4.7 as okd-cli + FROM quay.io/operator-framework/ansible-operator:v0.17.1 # We have to change to USER 0 to be able to install Python packages @@ -7,6 +9,12 @@ FROM quay.io/operator-framework/ansible-operator:v0.17.1 # which is outside of the default range of users ID used ranges: [1000800000, 1000809999] USER 0 +# Install "oc" and "dig" commands +COPY --from=okd-cli /usr/bin/oc /usr/local/bin/ +RUN yum install -y \ + bind-utils \ + && yum clean all && rm -rf /var/cache/yum/* + # 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 diff --git a/chart/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml b/chart/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml index 8118b45cee69cd0b37bc9cd244d6e2c5edcb3b66..d883ed84f13cf81d941954026501b392e7c8f3da 100644 --- a/chart/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml +++ b/chart/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml @@ -1,4 +1,4 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: delegateddomainaliases.landb.operator.cern.ch @@ -10,50 +10,48 @@ spec: 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 + subresources: + status: {} + schema: + 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 diff --git a/chart/crds/landb.operator.cern.ch_delegateddomains_crd.yaml b/chart/crds/landb.operator.cern.ch_delegateddomains_crd.yaml index 4793a7a3674f1a563a027c472da2184f67bd766d..bd4443c776ff8b4d2183758da7c9d4e76846d20d 100644 --- a/chart/crds/landb.operator.cern.ch_delegateddomains_crd.yaml +++ b/chart/crds/landb.operator.cern.ch_delegateddomains_crd.yaml @@ -1,4 +1,4 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: delegateddomains.landb.operator.cern.ch @@ -10,54 +10,52 @@ spec: 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 - + subresources: + status: {} + schema: + 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 diff --git a/chart/crds/landb.operator.cern.ch_landbsets_crd.yaml b/chart/crds/landb.operator.cern.ch_landbsets_crd.yaml index e8f088a5d323906cdc5c5c48b10f0b804efdc8bd..92673c2b111869343cea7632acbb2aa931f43f30 100644 --- a/chart/crds/landb.operator.cern.ch_landbsets_crd.yaml +++ b/chart/crds/landb.operator.cern.ch_landbsets_crd.yaml @@ -1,4 +1,4 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: landbsets.landb.operator.cern.ch @@ -10,59 +10,66 @@ spec: 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: - 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 + subresources: + status: {} + schema: + 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: + 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 filters the nodes that are going to be + added to the set (empty will include all nodes) + type: string + loadbalancerLabelSelector: + description: LoadbalancerLabelSelector filters Kubernetes Services of type loadbalancer + that are going to be added to the set (empty will include all loadbalancers) + type: string + loadbalancerNamespace: + description: LoadbalancerNamespace specifies in which namespace to look for Kubernetes Services + of type loadbalancer. Defaults to openshift-ingress. Use empty string to include all namespaces. + 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 diff --git a/chart/templates/_landb-set-template.yaml b/chart/templates/_landb-set-template.yaml index a3968b194d1ef3f212692aa5307b8c7b9ceb2f16..bd7fd4e4f51cb89dcd0e2b908fe0ff6d1c4344a2 100644 --- a/chart/templates/_landb-set-template.yaml +++ b/chart/templates/_landb-set-template.yaml @@ -1,4 +1,4 @@ -{{define "landbSet.cr"}} +{{- define "landbSet.cr" }} apiVersion: landb.operator.cern.ch/v1alpha1 kind: LandbSet metadata: @@ -7,7 +7,9 @@ metadata: spec: setName: {{ .Values.setName | quote }} labelSelector: {{ .Values.labelSelector | quote }} + loadbalancerLabelSelector: {{ .Values.loadbalancerLabelSelector | quote }} + loadbalancerNamespace: {{ .Values.loadbalancerNamespace | quote }} type: "INTER" domain: "GPN" --- -{{- end }} \ No newline at end of file +{{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index e35c11335e2bb5c96e090e4b63e85b9ecee18e5e..41fe1a7b4a53df939414aa2daa55169e88da855b 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -4,7 +4,7 @@ kind: Deployment metadata: name: landb-operator annotations: - description: The landb operator, is responsible of reconciling DelegatedDomains, DelegatedDomainsAliases and LandbSets + description: The LanDB operator is responsible of reconciling DelegatedDomains, DelegatedDomainsAliases and LandbSets spec: replicas: 1 selector: @@ -27,6 +27,8 @@ spec: args: - "--max-workers" - {{ .Values.maxWorkers | quote }} + - "--ansible-verbosity" + - {{ .Values.logVerbosity | quote }} volumeMounts: - mountPath: /tmp/ansible-operator/runner name: runner @@ -55,6 +57,8 @@ spec: value: {{ .Values.landb.responsible }} - name: CLUSTER_NAME value: {{ .Values.clusterName }} + - name: ANSIBLE_DEBUG_LOGS + value: {{ .Values.ansibleDebugLogs | quote }} volumes: - name: runner emptyDir: {} diff --git a/chart/templates/role.yaml b/chart/templates/role.yaml index f67bae196cfabb28955d10cd9ab92790046dd949..11aabb07488cec7657a3df036e633eb7d8a738bb 100644 --- a/chart/templates/role.yaml +++ b/chart/templates/role.yaml @@ -57,7 +57,6 @@ rules: - update --- - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -65,17 +64,21 @@ metadata: app: {{ .Release.Name }}-landb-operator name: {{ .Release.Name }}-landb-operator rules: -# 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 - apiGroups: - "" resources: + # Since nodes are a cluster-level resource, access to this resource + # needs to be declared in a ClusterRole + # This is required to build the machine sets that we will published to LanDB - nodes + # Allow retrieving services from all namespaces + # This is required for the LBaaS integration + - services verbs: - get - list - watch + # Access to all the resources that will be # managed by this operator in all namespaces # since we want to deploy this operator to watch @@ -97,4 +100,3 @@ rules: - patch - update - watch - diff --git a/chart/values.yaml b/chart/values.yaml index b5bdf049c3307b0e1e0d0bc6186613770e51dc52..45d946b76e4ddd814891018eef8b2ab27a9957ea 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -2,14 +2,23 @@ image: gitlab-registry.cern.ch/paas-tools/operators/landb-operator:protection imagePullPolicy: Always -# Namespace/s where the operator will look for CRs to resconsile +# Namespace/s where the operator will look for CRs to reconcile # "" == all namespaces watchNamespace: "" # we want many workers to handle a large number of resources maxWorkers: 20 -# Name of the cluster where the operator is deployed, this will +# Ansible logging verbosity (0-7) +# https://v0-17-x.sdk.operatorframework.io/docs/ansible/reference/advanced_options/#ansible-verbosity +# Note that this verbosity can be overriden by each CR with the following annotation +# annotations: +# "ansible.operator-sdk/verbosity": "4" +logVerbosity: 2 +# https://v0-17-x.sdk.operatorframework.io/docs/ansible/quickstart/#additional-ansible-debug +ansibleDebugLogs: "False" # "True" or "False" (as string!) + +# Name of the cluster where the operator is deployed, this will # then be used to build the ownership string for delegated domains clusterName: "" @@ -25,12 +34,15 @@ tolerations: [] # Name of the landb set will match the template provided by setNameTemplate # where %s will be the name of cluster. -# name is simply the name of the LandbSet CR in openshift +# name is simply the name of the LandbSet CR in openshift landbSetInstances: [] # Example in landbSetInstances in prod cluster # - name: "landb-sync-all-nodes" # setName: "IT OKD PROD ALL NODES" # labelSelector: "" +# loadbalancerLabelSelector: "invalid=" # - name: "landb-sync-router-nodes" # setName: "IT OKD PROD ROUTER NODES" -# labelSelector: node-role.kubernetes.io/router= \ No newline at end of file +# labelSelector: node-role.kubernetes.io/router= +# loadbalancerLabelSelector: "" +# loadbalancerNamespace: "openshift-ingress" diff --git a/deploy/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml b/deploy/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml deleted file mode 100644 index 8118b45cee69cd0b37bc9cd244d6e2c5edcb3b66..0000000000000000000000000000000000000000 --- a/deploy/crds/landb.operator.cern.ch_delegateddomainaliases_crd.yaml +++ /dev/null @@ -1,59 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: delegateddomainaliases.landb.operator.cern.ch -spec: - group: landb.operator.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 diff --git a/deploy/crds/landb.operator.cern.ch_delegateddomains_crd.yaml b/deploy/crds/landb.operator.cern.ch_delegateddomains_crd.yaml deleted file mode 100644 index 4793a7a3674f1a563a027c472da2184f67bd766d..0000000000000000000000000000000000000000 --- a/deploy/crds/landb.operator.cern.ch_delegateddomains_crd.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: delegateddomains.landb.operator.cern.ch -spec: - group: landb.operator.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 - diff --git a/deploy/crds/landb.operator.cern.ch_landbsets_crd.yaml b/deploy/crds/landb.operator.cern.ch_landbsets_crd.yaml deleted file mode 100644 index e9c16cabdace0b09a580ae1b5a6ad3b460697189..0000000000000000000000000000000000000000 --- a/deploy/crds/landb.operator.cern.ch_landbsets_crd.yaml +++ /dev/null @@ -1,72 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: landbsets.landb.operator.cern.ch -spec: - group: landb.operator.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 diff --git a/deploy/crds/landb.operator.cern.ch_v1alpha1_delegateddomain_cr.yaml b/deploy/crds/landb.operator.cern.ch_v1alpha1_delegateddomain_cr.yaml deleted file mode 100644 index 141f4d988cf50c0850c42204b8cb51cbe3753581..0000000000000000000000000000000000000000 --- a/deploy/crds/landb.operator.cern.ch_v1alpha1_delegateddomain_cr.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: landb.operator.cern.ch/v1alpha1 -kind: DelegatedDomain -metadata: - name: test-delegateddomain -spec: - domain: clu-estevesm-app.cern.ch - view: internal - description: "test" - keyname: itwebservices-internal \ No newline at end of file diff --git a/deploy/crds/landb.operator.cern.ch_v1alpha1_delegateddomainalias_cr.yaml b/deploy/crds/landb.operator.cern.ch_v1alpha1_delegateddomainalias_cr.yaml deleted file mode 100644 index 9ddc06f391c38fa505ebce1cfd3b63a0ffc3deb8..0000000000000000000000000000000000000000 --- a/deploy/crds/landb.operator.cern.ch_v1alpha1_delegateddomainalias_cr.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: landb.operator.cern.ch/v1alpha1 -kind: DelegatedDomainAlias -metadata: - name: test-delegateddomain -spec: - domain: clu-estevesm-app.cern.ch - view: internal - alias: estevesm-test \ No newline at end of file diff --git a/deploy/crds/landb.operator.cern.ch_v1alpha1_landbset_cr.yaml b/deploy/crds/landb.operator.cern.ch_v1alpha1_landbset_cr.yaml deleted file mode 100644 index eae8fd428994f262221dbd55936dd2b2db062ea7..0000000000000000000000000000000000000000 --- a/deploy/crds/landb.operator.cern.ch_v1alpha1_landbset_cr.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: landb.operator.cern.ch/v1alpha1 -apiVersion: landb.operator.cern.ch/v1alpha1 -kind: LandbSet -metadata: - name: test-set -spec: - setName: "Test Set" - labelSelector: node-role.kubernetes.io/worker= - Description: "This is a NICE set" \ No newline at end of file diff --git a/deploy/operator.yaml b/deploy/operator.yaml deleted file mode 100644 index 7f4618c6366e3a7983b543f4d9caa924c9a0bf29..0000000000000000000000000000000000000000 --- a/deploy/operator.yaml +++ /dev/null @@ -1,40 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: delegated-domains-operator -spec: - replicas: 1 - selector: - matchLabels: - name: delegated-domains-operator - template: - metadata: - labels: - name: delegated-domains-operator - spec: - serviceAccountName: delegated-domains-operator - containers: - - name: delegated-domains-operator - # Replace this with the built image name - image: gitlab-registry.cern.ch/paas-tools/operators/landb-operator:latest - imagePullPolicy: "Always" - 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: "delegated-domains-operator" - - name: ANSIBLE_GATHERING - value: explicit - volumes: - - name: runner - emptyDir: {} diff --git a/deploy/role.yaml b/deploy/role.yaml deleted file mode 100644 index 7bbcb89af55317b6b341fe5fa1373820e86a7f89..0000000000000000000000000000000000000000 --- a/deploy/role.yaml +++ /dev/null @@ -1,80 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - creationTimestamp: null - name: delegated-domains-operator -rules: -- apiGroups: - - "" - resources: - - pods - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - apps - resourceNames: - - delegated-domains-operator - resources: - - deployments/finalizers - verbs: - - update -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get -- apiGroups: - - landb.operator.cern.ch - resources: - - '*' - verbs: - - create - - delete - - get - - list - - patch - - update - - watch diff --git a/deploy/role_binding.yaml b/deploy/role_binding.yaml deleted file mode 100644 index ad9725a7172585a8873736078fbe636c054016c3..0000000000000000000000000000000000000000 --- a/deploy/role_binding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: delegated-domains-operator -subjects: -- kind: ServiceAccount - name: delegated-domains-operator -roleRef: - kind: Role - name: delegated-domains-operator - apiGroup: rbac.authorization.k8s.io diff --git a/deploy/service_account.yaml b/deploy/service_account.yaml deleted file mode 100644 index 8d1a699a23482cb7fd786d0c3239255bde763327..0000000000000000000000000000000000000000 --- a/deploy/service_account.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: delegated-domains-operator diff --git a/roles/delegateddomain/tasks/main.yml b/roles/delegateddomain/tasks/main.yml index f4efc93baec3926f50182b2bb042b4ee2053ab54..a580e8c7a2b53a2e502769b5fa4ef6ac445b92e6 100644 --- a/roles/delegateddomain/tasks/main.yml +++ b/roles/delegateddomain/tasks/main.yml @@ -6,7 +6,7 @@ # Variable names are transformed from camelcase to underscores # E.g. CR .spec.camelCase transformed into camel_case -# Definition for both variables landb_user and landb_password are in the file vars/main.yml +# Definition for both variables landb_user and landb_password are in the file vars/main.yml # Build ownership string that is going to be used to allow us to manage ownership of Delegated Domains # this ownership string will live in the description field of a Delegated Domain and it's limited to 255 chars @@ -14,7 +14,7 @@ set_fact: ownership_string: "MANAGED BY landb-operator CLUSTER='{{ cluster_name }}' NAMESPACE='{{ meta.namespace }}' NAME='{{ meta.name }}'" -# If are not deleting, then we will try to add domain as a delegated DNS domain to LanDB +# Try to add domain as a delegated DNS domain to LanDB # We use description as a parameter for both SOAP fields description and userDescription of SOAP call dnsDelegateAdd - name: Add delegated domain to LanDB script: ../files/main.py --landb-user '{{ landb_user }}' --landb-password '{{ landb_password }}' --command dns-delegate-add --domain '{{ domain }}' --view '{{ view }}' --keyname '{{ keyname }}' --description '{{ description }}' --ownership-string '{{ ownership_string }}' @@ -28,4 +28,3 @@ args: executable: python3 when: state == 'absent' - diff --git a/roles/delegateddomainalias/tasks/main.yml b/roles/delegateddomainalias/tasks/main.yml index c6f4ec463092cb6696af92b1db84468969de035f..b6877fe8d0a894a40b00b763b1f63e219901481a 100644 --- a/roles/delegateddomainalias/tasks/main.yml +++ b/roles/delegateddomainalias/tasks/main.yml @@ -6,9 +6,9 @@ # Variable names are transformed from camelcase to underscores # E.g. CR .spec.camelCase transformed into camel_case -# Definition for both variables landb_user and landb_password are in the file vars/main.yml - -# If are not deleting, then we will try to add domain as a delegated DNS domain to LanDB +# Definition for both variables landb_user and landb_password are in the file vars/main.yml + +# Try to add domain as a delegated DNS domain to LanDB # We use description as a parameter for both SOAP fields description and userDescription of SOAP call dnsDelegateAdd - name: Add alias to delegated domain script: ../files/main.py --landb-user '{{ landb_user }}' --landb-password '{{ landb_password }}' --command dns-delegate-alias-add --domain '{{ domain }}' --view '{{ view }}' --alias '{{ alias }}' @@ -22,4 +22,3 @@ args: executable: python3 when: state == 'absent' - diff --git a/roles/files/loadbalancers.sh b/roles/files/loadbalancers.sh new file mode 100755 index 0000000000000000000000000000000000000000..8235db330e4ee8a6c383291338ba049f5b349110 --- /dev/null +++ b/roles/files/loadbalancers.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -e +LABEL_SELECTOR="$1" +NAMESPACE="$2" + +# If a namespace was specified, only search that specific namespace, +# otherwise search all namespaces. +NS_FILTER= +if [ -n "$NAMESPACE" ]; then + NS_FILTER="-n ${NAMESPACE}" +else + NS_FILTER="-A" +fi + +# get the IP addresses of all load balancer services used in the cluster +# LABEL_SELECTOR may be empty +oc get services "${NS_FILTER}" -l "${LABEL_SELECTOR}" -o 'jsonpath={ .items[*].status.loadBalancer.ingress[0].ip }' | \ +# use tr to transform whitespace-separated jsonpath into lines, make sure IPs are unique +tr ' ' '\n' | sort | uniq | \ +# do a reverse DNS lookup of IPs for the hostnames (-n 1: one-by-one, only if input is given) +xargs -n 1 --no-run-if-empty dig @ip-dns-1.cern.ch @ip-dns-2.cern.ch +short -x | \ +# remove the trailing ".cern.ch.", we want the non-FQDN hostname +sed 's/\.cern\.ch\.$//' | \ +# join lines by commas and trim trailing comma +tr '\n' ',' | sed 's/\,$//' diff --git a/roles/files/main.py b/roles/files/main.py old mode 100644 new mode 100755 index b14b184e66975e24df2b35af46323bb8c2ebb55e..131c8c8e37097947de4217aa3059cf85b3e3638f --- a/roles/files/main.py +++ b/roles/files/main.py @@ -16,13 +16,13 @@ client = None auth_header = None args = None -# Python program to illustrate the intersection -# of two lists -def intersection(lst1, lst2): - # Use of hybrid method - temp = set(lst2) - lst3 = [value for value in lst1 if value in temp] - return lst3 +# Python program to illustrate the intersection +# of two lists +def intersection(lst1, lst2): + # Use of hybrid method + temp = set(lst2) + lst3 = [value for value in lst1 if value in temp] + return lst3 # Initialize soap client and authentication header def initializeClient(user, password): @@ -57,7 +57,7 @@ def dnsDelegatedRemove(domain, view): if not ex.message.startswith("NOTFOUND"): raise ex -# Searches all Delegated Domains that have a filed that matches search (domain, view, description, keyname) +# Searches all Delegated Domains that have a filed that matches search (domain, view, description, keyname) def dnsDelegatedSearch(search): return client.service.dnsDelegatedSearch(search, _soapheaders=auth_header) @@ -71,7 +71,7 @@ def dnsDelegatedGetByNameView(search, extra): else: raise ex -# This function searches for delegaed domains that match the string domain & view and then +# This function searches for delegaed domains that match the string domain & view and then # it asserts that Description of that domain matches the ownership_string def dnsCheckOwnership(domain, view, ownership_string): if ownership_string == "": @@ -102,7 +102,7 @@ def dnsDelegatedAliasRemove(domain, view, alias): # We ignore the error of not found to make this function reentrant except exceptions.Fault as ex: if not ex.message.startswith("NOTFOUND"): - raise ex + raise ex # -------------- END OF LANDB DNS DELGATED DOMAIN RELATED FUNCTIONS -------------- @@ -159,7 +159,7 @@ def getSetInfo(landb_set_name): else: raise ex -# This function searches for sets that match the set name and then +# This function searches for sets that match the set name and then # it asserts that Description of that set matches the ownership_string def setCheckOwnership(landb_set_name, ownership_string): if ownership_string == "": @@ -209,7 +209,7 @@ def main(): check ownership check for both Sets and Delegated domains, default is False') parser.add_argument('--ownership-string', dest='ownership_string', type=str, default="", help='string used to identify \ owner of resources, this will live in the description field of the resources. State modifying command require it') - + # Common but optional for some commands # Required for set-add and dns-delegate-* parser.add_argument('--domain', type=str, default="", help='if command is set-* then domain is domain of the \ @@ -218,7 +218,7 @@ def main(): # Parameters common to all set-* commands parser.add_argument('--landb-set-name', dest='landb_set_name', default="", type=str, help='name of the new \ lanDB set to be created') - + # Parameters specific to set-add parser.add_argument('--person-name', dest='person_name', default="", type=str, help='name of the person who\'s going \ to be responsible by the landb set') @@ -230,12 +230,12 @@ def main(): parser.add_argument('--address', type=str, default="", help='FQDN to be added to the set provided') # Parameters specfic to set-update - parser.add_argument('--node-list', dest='node_list', type=str, default="", help='List of K8S nodes to be added to the set provided') + parser.add_argument('--node-list', dest='node_list', type=str, default="", help='List of K8S nodes to be added to the set provided') # Parameters common to all dns-delegate-* parser.add_argument('--view', type=str, default="", help='view of the DNS delegated domain') - - # Parameters specific to dns-delegate-add + + # Parameters specific to dns-delegate-add parser.add_argument('--keyname', type=str, default="", help='name of the DNS key with privileges to add/remove \ lanDB delegated domains') parser.add_argument('--description', type=str, default="", help='description of the dns delegated \ @@ -256,24 +256,26 @@ def main(): if args.command.startswith("set-"): if args.landb_set_name == "": print("When using set commands, you have to at least provide --landb-set-name") - return + return 1 elif args.command == 'set-search': list_of_sets = searchSet(args.landb_set_name) if list_of_sets == []: print("ERROR: No sets found that matched the provided name/expression") - return + return 1 print(json.dumps(helpers.serialize_object(list_of_sets, dict))) - return + return 0 elif args.command == 'set-get-info': set_info = getSetInfo(args.landb_set_name) if set_info == None: print("ERROR: No set found that matched the provided name") + return 1 else: print(json.dumps(helpers.serialize_object(set_info, dict))) - return + + return 0 try: if args.unprotected_command or setCheckOwnership(args.landb_set_name, args.ownership_string): @@ -281,7 +283,7 @@ def main(): if args.command == 'set-add': if args.domain == "" or args.person_name == "" or args.type == "": print("When using command set-add, you have to provide --landb-set-name, --domain, --person-name and --type") - return + return 1 setInsert(args.landb_set_name) @@ -295,8 +297,8 @@ def main(): elif args.command == 'set-add-address': if args.address == "": print("When using command set-add-address, you have to provide --landb-set-name and --address") - return - + return 1 + setInsertAddress(args.landb_set_name, args.address) print("Address added to set with success") @@ -304,8 +306,8 @@ def main(): elif args.command == 'set-remove-address': if args.address == "": print("When using command set-remove-address, you have to provide --landb-set-name and --address") - return - + return 1 + setDeleteAddress(args.landb_set_name, args.address) print("Address removed from set with success") @@ -313,13 +315,13 @@ def main(): elif args.command == 'set-update': if args.landb_set_name == "" or args.node_list == "": print("When using command set-remove-address, you have to provide --landb-set-name and --node-list") - return - + return 1 + # Fetch nodes in set landb_nodes = getSetAllAddresses(args.landb_set_name) if landb_nodes == None: - print("Set not found on create so setInsert failed silenty") - return + print("Set not found on create so setInsert failed silenty") + return 1 #Fetch Openshift machines and add their names to a list named okd_nodes parsed_names = args.node_list.split(",") @@ -327,7 +329,7 @@ def main(): for name in parsed_names: if name != "": okd_nodes.append((name+".cern.ch").upper()) - + # Find the intersection of landb_nodes and okd_nodes which gives us # nodes that we don't want to touch common_nodes = intersection(landb_nodes, okd_nodes) @@ -345,6 +347,8 @@ def main(): print("Set updated with success") + return 0 + except exceptions.Fault as ex: # Ignore ownership exception on remove operations so we don't endup not being able to # remove the finalizer from the CR, due to the script being always raising exceptions @@ -356,40 +360,45 @@ def main(): # Logic to handle dns- commands, non disruptive commands never check owenership of resources; # disruptive commands have to check ownership of resources unless they are runned with - # unprotected-command flag, exception for commands with -alias- since, those are + # unprotected-command flag, exception for commands with -alias- since, those are # going to be executed from another Ansible task that doesn't have access to ownership information elif args.command.startswith("dns-"): if args.domain == "": print("When using dns commands, you have to at least provide --domain") - return + return 1 elif args.command == 'dns-search': list_of_dns = dnsDelegatedSearch(args.domain) if not list_of_dns: print("ERROR: No delegated domains found that matched the provided name/expression") + return 1 else: print(json.dumps(helpers.serialize_object(list_of_dns, dict))) - return + + return 0 elif args.view == "": print("When using dns commands to modify state, you have to at least provide --domain and --view") - return + return 1 elif args.command == 'dns-delegate-alias-add': if args.alias == "": print("When using command dns-delegate-alias-add, you have to provide --domain, --view, --alias") + return 1 else: dnsDelegatedAliasAdd(args.domain, args.view, args.alias) print("Alias added to existing DNS delegated domain with success") - return + + return 0 elif args.command == 'dns-delegate-alias-remove': if args.alias == "": print("When using command dns-delegate-alias-remove, you have to provide --domain, --view, --alias") - else: + return 1 + else: dnsDelegatedAliasRemove(args.domain, args.view, args.alias) print("Alias removed from existing DNS delegated domain with success") - return + return 0 try: if args.unprotected_command or dnsCheckOwnership(args.domain, args.view, args.ownership_string): @@ -398,8 +407,8 @@ def main(): if args.keyname == "" or args.description == "" or args.ownership_string == "": print("When using command dns-delegate-add, you have to provide --domain, --view, --keyname --owneship-string and --description. \ Ownerhsip string needs to be provided as it will live in the description field that cannot be empty") - return - + return 1 + # Due to lanDB user-description only having space for 56 charcters we have to trim # our description here args.description = args.description[:56] @@ -412,7 +421,9 @@ def main(): dnsDelegatedRemove(args.domain, args.view) print("DNS delegated domain removed with success") - + + return 0 + except exceptions.Fault as ex: # Ignore ownership exception on remove operations so we don't endup not being able to # remove the finalizer from the CR, due to the script being always raising exceptions diff --git a/roles/landbset/defaults/main.yml b/roles/landbset/defaults/main.yml index 019ad5cae4205dc6434808ac727630f02d90bf74..15f42a6602343a7bde7254c8383e29ebf3c2d159 100644 --- a/roles/landbset/defaults/main.yml +++ b/roles/landbset/defaults/main.yml @@ -4,7 +4,7 @@ # when running the finalizer code, this will be set to `absent` cf. watches.yml state: present -# Domain of landb set defaults to "General Purpose Network" +# Domain of landb set defaults to "General Purpose Network" # https://network.cern.ch/sc/html/help/domain.html domain: "GPN" @@ -16,14 +16,20 @@ type: "INTER" landb_user: "{{ lookup('env','LANDB_USER') }}" landb_password: "{{ lookup('env','LANDB_PASSWORD') }}" -# This variable will be used every time we want to add a set to lanDB +# This variable will be used every time we want to add a set to lanDB # Deceided set it as env var as we will likely don't want to have different # sets with different landb responsibles, this values is expected to be an e-grop landb_responsible: "{{ lookup('env','LANDB_RESPONSIBLE') }}" -# This variable will be used to pass to python scrip the list of node names that +# This variable will be used to pass to python script the list of node names that # we want to add to the lanDB set list_names: "" +# Empty values are allowed, but we don't want "undefined variables" errors when user +# does not set these values in the CR +label_selector: "" # filters nodes based on label +loadbalancer_label_selector: "" # filters loadbalancer services based on label +loadbalancer_namespace: "" # filters loadbalancer services based on namespace (empty string includes all namespaces) + # Name of the cluster where the operator is running, this will then be used to build the ownership string -cluster_name: "{{ lookup('env','CLUSTER_NAME') }}" \ No newline at end of file +cluster_name: "{{ lookup('env','CLUSTER_NAME') }}" diff --git a/roles/landbset/tasks/main.yml b/roles/landbset/tasks/main.yml index a1617c0f5e693e7c3241d381c84177c169aeee26..51c6da8d70af8b51075399f679b4ad2df5b59ac0 100644 --- a/roles/landbset/tasks/main.yml +++ b/roles/landbset/tasks/main.yml @@ -6,7 +6,7 @@ # Variable names are transformed from camelcase to underscores # E.g. CR .spec.camelCase transformed into camel_case -# Definition for both variables landb_user, landb_password, landb_responsible and list_names are in the file defaults/main.yml +# Definition for both variables landb_user, landb_password, landb_responsible and list_names are in the file defaults/main.yml # Build ownership string that is going to be used to allow us to manage ownership of LanDB sets # this ownership string will live in the description field of a LanDB set @@ -14,7 +14,7 @@ set_fact: ownership_string: "/managedBy=landb-operator/cluster='{{ cluster_name }}'/namespace='{{ meta.namespace }}'/name='{{ meta.name }}'" -# If are not deleting, then we also want to add the set to lanDB +# Add the set to LanDB # flag --person-first-name is omited as it will not be relevant for our use case where the responsible is an e-group - name: Add set to lanDB script: ../files/main.py --landb-user '{{ landb_user }}' --landb-password '{{ landb_password }}' --command set-add --landb-set-name '{{ set_name }}' --person-name '{{ landb_responsible }}' --domain '{{ domain }}' --type '{{ type }}' --ownership-string '{{ ownership_string }}' @@ -22,7 +22,7 @@ executable: python3 when: state == 'present' -# If are not deleting, set a fact with all the nodes that match the label selector +# Set a fact with all the nodes that match the label selector - name: Gather nodes k8s_info: api_version: "" @@ -32,26 +32,41 @@ register: nodes_list when: state == 'present' -# If are not deleting, create a string of node names separated by , -# to serve as input to Update set we have to create this string -# to allow us to pass information into the script that will update -# the set. +# Create a string of node names separated by `,` +# to serve as input to Update set we have to create this string +# to allow us to pass information into the script that will update the set. +# String has a leading comma, but no trailing comma. - name: Create node name string set_fact: - list_names: '{{ list_names + "," + item.metadata.name }}' + list_names: '{{ list_names + "," + item.metadata.name }}' loop: '{{ nodes_list.resources }}' when: state == 'present' -# If are not deleting, use command set-update that will parse string of names +# Set a fact with all the loadbalancer services that match the label selector +# Ideally we would simply like to use a field selector like `spec.type=LoadBalancer`, +# but that is not supported. Instead, we use some shell magic. +# https://github.com/kubernetes/kubernetes/issues/77662 +# https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/ +- name: Gather LoadBalancer services + script: ../files/loadbalancers.sh '{{ loadbalancer_label_selector }}' '{{ loadbalancer_namespace }}' + register: loadbalancers_list + when: state == 'present' + +# Merge the node list and loadbalancer list +- name: Combine node list and loadbalancer list + set_fact: + list_names: '{{ list_names }},{{ loadbalancers_list.stdout }}' + when: state == 'present' + +# Use command `set-update` that will parse string of names # separated by , and then do the intersection of node names already present -# on landb and the ones we want to add. Will remove the ones that are present -# in landb but not in list_name and we will add the ones that are in list_names but not in landb +# on landb and the ones we want to add. Will remove the ones that are present +# in landb but not in list_name and we will add the ones that are in list_names but not in landb - name: Update set script: ../files/main.py --landb-user '{{ landb_user }}' --landb-password '{{ landb_password }}' --command set-update --landb-set-name '{{ set_name }}' --node-list '{{ list_names }}' --ownership-string '{{ ownership_string }}' args: executable: python3 - when: state == 'present' - + when: state == 'present' and list_names and list_names != ',' # If we are deleting, then we also want to delete the set from lanDB # Note that this command set-remove will delete all nodes from the lanDB set @@ -60,4 +75,4 @@ script: ../files/main.py --landb-user '{{ landb_user }}' --landb-password '{{ landb_password }}' --command set-remove --landb-set-name '{{ set_name }}' --ownership-string '{{ ownership_string }}' args: executable: python3 - when: state == 'absent' \ No newline at end of file + when: state == 'absent'