├── triggerfile ├── OWNERS ├── common ├── config │ ├── .hadolint.yml │ ├── mdl.rb │ ├── tslint.json │ ├── .yamllint.yml │ └── sass-lint.yml ├── manifest.yaml ├── scripts │ ├── .githooks │ │ ├── make_lint-all.sh │ │ └── pre-commit │ ├── lint_go.sh │ ├── lint_copyright_banner.sh │ ├── install-operator-sdk.sh │ ├── config_docker.sh │ ├── gobuild.sh │ ├── delete-csv.sh │ ├── push-csv.sh │ └── csv-protect.py └── Makefile.common.mk ├── deploy ├── olm-catalog │ └── ibm-monitoring-grafana-operator │ │ ├── ibm-monitoring-grafana-operator.package.yaml │ │ ├── 1.8.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.8.1 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.9.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.9.1 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.9.2 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.10.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.10.1 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.10.2 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.10.3 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.10.4 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.11.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.11.1 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.12.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.13.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.14.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.15.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.16.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.17.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.18.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.19.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.20.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.21.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.22.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.23.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.24.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.25.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.26.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.0 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.1 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.10 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.11 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.12 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.13 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.2 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.3 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.4 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.5 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.6 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.7 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ ├── 1.27.8 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml │ │ └── 1.27.9 │ │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml ├── service_account.yaml ├── crds │ ├── operator.ibm.com_v1alpha1_grafana_cr.yaml │ └── monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml ├── role_binding.yaml ├── operator.yaml └── role.yaml ├── .osdk-scorecard.yaml ├── hack └── boilerplate.go.txt ├── version └── version.go ├── pkg ├── controller │ ├── artifacts │ │ ├── ocp_appm_config.go │ │ ├── router_entry.go │ │ ├── grafanaDBConfig.go │ │ ├── grafana_crd_entry.go │ │ ├── grafana_ds_proxy_config.go │ │ ├── entrypoint.go │ │ ├── grafanaConfig.go │ │ ├── init.go │ │ └── router_config.go │ ├── add_grafana.go │ ├── controller.go │ ├── model │ │ ├── cert.go │ │ ├── ds_proxy_config.go │ │ ├── ds_proxy_container.go │ │ ├── cleanup_csmonitoring.go │ │ ├── constants.go │ │ ├── grafana_ingress.go │ │ ├── grafana_router.go │ │ ├── grafana_dashboard.go │ │ ├── grafana_service.go │ │ ├── utils.go │ │ └── volume_source.go │ ├── config │ │ └── controller_config.go │ └── dashboards │ │ └── init.go └── apis │ ├── operator │ ├── v1alpha1 │ │ ├── doc.go │ │ ├── zz_generated.openapi.go │ │ └── register.go │ └── group.go │ ├── addtoscheme_operator_v1alpha1.go │ └── apis.go ├── tools.go ├── .gitignore ├── base_images.json ├── README.md └── go.mod /triggerfile: -------------------------------------------------------------------------------- 1 | Trigger rebuild 20220317-1012 2 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - dongwangdw 3 | - dongyingbo 4 | - Tirumalavasa 5 | - pgodowski 6 | 7 | reviewers: 8 | - dongwangdw 9 | - dongyingbo 10 | - Tirumalavasa 11 | - pgodowski 12 | - PRTamilanban 13 | -------------------------------------------------------------------------------- /common/config/.hadolint.yml: -------------------------------------------------------------------------------- 1 | ignored: 2 | - FAKE_DL3003 3 | - DL3006 4 | 5 | trustedRegistries: 6 | - gcr.io 7 | - docker.io 8 | - quay.io 9 | - registry.access.redhat.com 10 | - docker-na-public.artifactory.swg-devops.com/hyc-cloud-private-edge-docker-local 11 | - icr.io 12 | -------------------------------------------------------------------------------- /common/config/mdl.rb: -------------------------------------------------------------------------------- 1 | all 2 | rule 'MD002', :level => 1 3 | rule 'MD007', :indent => 4 4 | rule 'MD013', :line_length => 160, :code_blocks => false, :tables => false 5 | rule 'MD026', :punctuation => ".,;:!" 6 | exclude_rule 'MD013' 7 | exclude_rule 'MD014' 8 | exclude_rule 'MD030' 9 | exclude_rule 'MD032' 10 | exclude_rule 'MD033' 11 | exclude_rule 'MD041' 12 | exclude_rule 'MD046' -------------------------------------------------------------------------------- /deploy/olm-catalog/ibm-monitoring-grafana-operator/ibm-monitoring-grafana-operator.package.yaml: -------------------------------------------------------------------------------- 1 | channels: 2 | - currentCSV: ibm-monitoring-grafana-operator.v1.10.2 3 | name: stable-v1 4 | - currentCSV: ibm-monitoring-grafana-operator.v1.11.1 5 | name: beta 6 | - currentCSV: ibm-monitoring-grafana-operator.v1.27.13 7 | name: dev 8 | - currentCSV: ibm-monitoring-grafana-operator.v1.22.0 9 | name: v3 10 | defaultChannel: stable-v1 11 | packageName: ibm-monitoring-grafana-operator-app 12 | -------------------------------------------------------------------------------- /common/manifest.yaml: -------------------------------------------------------------------------------- 1 | image: __IMAGE_REPO__/__IMAGE_NAME__:__RELEASE_TAG__ 2 | manifests: 3 | - image: __IMAGE_REPO__/__IMAGE_NAME__-amd64:__RELEASE_TAG__ 4 | platform: 5 | architecture: amd64 6 | os: linux 7 | - image: __IMAGE_REPO__/__IMAGE_NAME__-ppc64le:__RELEASE_TAG__ 8 | platform: 9 | architecture: ppc64le 10 | os: linux 11 | - image: __IMAGE_REPO__/__IMAGE_NAME__-s390x:__RELEASE_TAG__ 12 | platform: 13 | architecture: s390x 14 | os: linux 15 | -------------------------------------------------------------------------------- /deploy/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: ibm-monitoring-grafana-operator 9 | --- 10 | apiVersion: v1 11 | kind: ServiceAccount 12 | metadata: 13 | labels: 14 | app.kubernetes.io/name: ibm-monitoring 15 | app.kubernetes.io/instance: common-monitoring 16 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 17 | name: ibm-monitoring-grafana 18 | -------------------------------------------------------------------------------- /.osdk-scorecard.yaml: -------------------------------------------------------------------------------- 1 | scorecard: 2 | # Setting a global scorecard option 3 | output: json 4 | bundle: deploy/olm-catalog/ibm-monitoring-grafana-operator 5 | plugins: 6 | - basic: 7 | cr-manifest: 8 | - "deploy/crds/operator.ibm.com_v1alpha1_grafana_cr.yaml" 9 | namespace: "ibm-common-services" 10 | crds-dir: "deploy/crds" 11 | - olm: 12 | cr-manifest: 13 | - "deploy/crds/operator.ibm.com_v1alpha1_grafana_cr.yaml" 14 | csv-path: "deploy/olm-catalog/ibm-monitoring-grafana-operator/1.8.0/ibm-monitoring-grafana-operator.v1.8.0.clusterserviceversion.yaml" -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | -------------------------------------------------------------------------------- /common/scripts/.githooks/make_lint-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2020 IBM Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | make lint-all 18 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2022 IBM Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package version 15 | 16 | var ( 17 | Version = "1.27.13" 18 | ) 19 | -------------------------------------------------------------------------------- /common/scripts/lint_go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2020 IBM Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | GOGC=25 golangci-lint run -c ./common/config/.golangci.yml 19 | -------------------------------------------------------------------------------- /common/config/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "rules": { 7 | "max-line-length": { 8 | "options": [160] 9 | }, 10 | "arrow-parens": false, 11 | "new-parens": true, 12 | "no-arg": true, 13 | "no-bitwise": true, 14 | "no-conditional-assignment": true, 15 | "no-consecutive-blank-lines": true, 16 | "no-console": { 17 | "severity": "warning", 18 | "options": ["debug", "info", "log", "time", "timeEnd", "trace"] 19 | }, 20 | "no-shadowed-variable": false, 21 | "eofline": false 22 | }, 23 | "jsRules": {}, 24 | "rulesDirectory": [] 25 | } -------------------------------------------------------------------------------- /pkg/controller/artifacts/ocp_appm_config.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | const DefaultOCPAppMonitorConfig = `enableUserWorkload: true 19 | ` 20 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // +build tools 17 | 18 | // Place any runtime dependencies as imports in this file. 19 | // Go modules will be forced to download and install them. 20 | package tools 21 | -------------------------------------------------------------------------------- /pkg/controller/artifacts/router_entry.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | const routerEntry = `#!/bin/sh 19 | 20 | exec nginx -c /opt/ibm/router/nginx/conf/nginx.conf.monitoring -g 'daemon off;' 21 | ` 22 | -------------------------------------------------------------------------------- /common/config/.yamllint.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | braces: disable 3 | brackets: disable 4 | colons: {max-spaces-before: 0, max-spaces-after: 1} 5 | commas: disable 6 | comments: disable 7 | comments-indentation: disable 8 | document-end: disable 9 | document-start: disable 10 | empty-lines: disable 11 | empty-values: {forbid-in-block-mappings: true, forbid-in-flow-mappings: true} 12 | hyphens: {max-spaces-after: 1} 13 | indentation: disable 14 | key-duplicates: enable 15 | key-ordering: disable 16 | line-length: disable 17 | new-line-at-end-of-file: disable 18 | new-lines: {type: unix} 19 | quoted-strings: disable 20 | trailing-spaces: disable 21 | octal-values: enable 22 | truthy: disable 23 | ignore: 24 | deploy/olm-catalog/ibm-monitoring-grafana-operator/1.9.2/ibm-monitoring-grafana-operator.v1.9.2.clusterserviceversion.yaml -------------------------------------------------------------------------------- /deploy/olm-catalog/ibm-monitoring-grafana-operator/1.8.0/monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: monitoringdashboards.monitoringcontroller.cloud.ibm.com 9 | spec: 10 | group: monitoringcontroller.cloud.ibm.com 11 | version: v1 12 | names: 13 | kind: MonitoringDashboard 14 | plural: monitoringdashboards 15 | scope: Namespaced 16 | validation: {} 17 | additionalPrinterColumns: 18 | - name: Enabled 19 | type: boolean 20 | JSONPath: .spec.enabled 21 | - name: Age 22 | type: date 23 | JSONPath: .metadata.creationTimestamp 24 | -------------------------------------------------------------------------------- /deploy/olm-catalog/ibm-monitoring-grafana-operator/1.8.1/monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: monitoringdashboards.monitoringcontroller.cloud.ibm.com 9 | spec: 10 | group: monitoringcontroller.cloud.ibm.com 11 | version: v1 12 | names: 13 | kind: MonitoringDashboard 14 | plural: monitoringdashboards 15 | scope: Namespaced 16 | validation: {} 17 | additionalPrinterColumns: 18 | - name: Enabled 19 | type: boolean 20 | JSONPath: .spec.enabled 21 | - name: Age 22 | type: date 23 | JSONPath: .metadata.creationTimestamp 24 | -------------------------------------------------------------------------------- /deploy/olm-catalog/ibm-monitoring-grafana-operator/1.9.0/monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: monitoringdashboards.monitoringcontroller.cloud.ibm.com 9 | spec: 10 | group: monitoringcontroller.cloud.ibm.com 11 | version: v1 12 | names: 13 | kind: MonitoringDashboard 14 | plural: monitoringdashboards 15 | scope: Namespaced 16 | validation: {} 17 | additionalPrinterColumns: 18 | - name: Enabled 19 | type: boolean 20 | JSONPath: .spec.enabled 21 | - name: Age 22 | type: date 23 | JSONPath: .metadata.creationTimestamp 24 | -------------------------------------------------------------------------------- /deploy/olm-catalog/ibm-monitoring-grafana-operator/1.9.1/monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: monitoringdashboards.monitoringcontroller.cloud.ibm.com 9 | spec: 10 | group: monitoringcontroller.cloud.ibm.com 11 | version: v1 12 | names: 13 | kind: MonitoringDashboard 14 | plural: monitoringdashboards 15 | scope: Namespaced 16 | validation: {} 17 | additionalPrinterColumns: 18 | - name: Enabled 19 | type: boolean 20 | JSONPath: .spec.enabled 21 | - name: Age 22 | type: date 23 | JSONPath: .metadata.creationTimestamp 24 | -------------------------------------------------------------------------------- /deploy/olm-catalog/ibm-monitoring-grafana-operator/1.9.2/monitoringcontroller.cloud.ibm.com_monitoringdashboards_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: monitoringdashboards.monitoringcontroller.cloud.ibm.com 9 | spec: 10 | group: monitoringcontroller.cloud.ibm.com 11 | version: v1 12 | names: 13 | kind: MonitoringDashboard 14 | plural: monitoringdashboards 15 | scope: Namespaced 16 | validation: {} 17 | additionalPrinterColumns: 18 | - name: Enabled 19 | type: boolean 20 | JSONPath: .spec.enabled 21 | - name: Age 22 | type: date 23 | JSONPath: .metadata.creationTimestamp 24 | -------------------------------------------------------------------------------- /common/scripts/.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2020 IBM Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | remote="$1" 18 | url="$2" 19 | 20 | python3 common/scripts/csv-protect.py 21 | if [ $? != 0 ];then 22 | exit 1 23 | fi 24 | 25 | .git/hooks/make_lint-all.sh 26 | 27 | exit $? 28 | -------------------------------------------------------------------------------- /pkg/apis/operator/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // Package v1alpha1 contains API Schema definitions for the operator v1alpha1 API group 17 | // +k8s:deepcopy-gen=package,register 18 | // +groupName=operator.ibm.com 19 | package v1alpha1 20 | -------------------------------------------------------------------------------- /pkg/apis/operator/group.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // Package operator contains operator API versions. 17 | // 18 | // This file ensures Go source parsers acknowledge the operator package 19 | // and any child packages. It can be removed if any other Go source files are 20 | // added to this package. 21 | package operator 22 | -------------------------------------------------------------------------------- /pkg/controller/add_grafana.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package controller 17 | 18 | import ( 19 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/controller/grafana" 20 | ) 21 | 22 | func init() { 23 | // AddToManagerFuncs is a list of functions to create controllers and add them to a manager. 24 | AddToManagerFuncs = append(AddToManagerFuncs, grafana.Add) 25 | } 26 | -------------------------------------------------------------------------------- /common/scripts/lint_copyright_banner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2020 IBM Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | set -e 19 | 20 | ec=0 21 | for fn in "$@"; do 22 | if ! grep -L -q -e "Apache License, Version 2" "${fn}"; then 23 | echo "Missing license: ${fn}" 24 | ec=1 25 | fi 26 | 27 | if ! grep -L -q -e "Copyright" "${fn}"; then 28 | echo "Missing copyright: ${fn}" 29 | ec=1 30 | fi 31 | done 32 | 33 | exit $ec 34 | -------------------------------------------------------------------------------- /pkg/apis/addtoscheme_operator_v1alpha1.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package apis 17 | 18 | import ( 19 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 20 | ) 21 | 22 | func init() { 23 | // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back 24 | AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/apis/apis.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package apis 17 | 18 | import ( 19 | "k8s.io/apimachinery/pkg/runtime" 20 | ) 21 | 22 | // AddToSchemes may be used to add all resources defined in the project to a Scheme 23 | var AddToSchemes runtime.SchemeBuilder 24 | 25 | // AddToScheme adds all Resources to the Scheme 26 | func AddToScheme(s *runtime.Scheme) error { 27 | return AddToSchemes.AddToScheme(s) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/controller/artifacts/grafanaDBConfig.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | const grafanaDBConfig = ` 19 | 20 | apiVersion: 1 21 | providers: 22 | - name: 'default' 23 | orgId: 1 24 | folder: '' 25 | type: file 26 | disableDeletion: false 27 | updateIntervalSeconds: 30 #how often Grafana will scan for changed dashboards 28 | options: 29 | path: /etc/grafana/dashboards/` 30 | -------------------------------------------------------------------------------- /pkg/controller/artifacts/grafana_crd_entry.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | // With parameter clusterPort 19 | const crdEntry = `#!/bin/bash 20 | FLAG=false 21 | while [[ $FLAG == false ]]; do 22 | curl -k --connect-timeout 10 https://127.0.0.1:{{ .ClusterPort }}/api 23 | if [[ $? == 0 ]]; then 24 | FLAG=true 25 | echo "Grafana process started" 26 | fi 27 | done 28 | 29 | /grafana-dashboard-crd 30 | ` 31 | -------------------------------------------------------------------------------- /pkg/controller/artifacts/grafana_ds_proxy_config.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | // This is the configuration file of proxy between grafana container and OCP thanos-quirier service 19 | const grafanaDSProxyConfig = ` 20 | type: ibm-cs-iam 21 | paras: 22 | uidURL: https://platform-identity-provider.{{ .Namespace }}.svc:4300 23 | userInfoURL: https://platform-identity-management.{{ .Namespace }}.svc:4500 24 | ` 25 | -------------------------------------------------------------------------------- /pkg/apis/operator/v1alpha1/zz_generated.openapi.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | // 4 | // Copyright 2020 IBM Corporation 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | // 18 | 19 | // This file was autogenerated by openapi-gen. Do not edit it manually! 20 | 21 | package v1alpha1 22 | 23 | import ( 24 | common "k8s.io/kube-openapi/pkg/common" 25 | ) 26 | 27 | func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { 28 | return map[string]common.OpenAPIDefinition{} 29 | } 30 | -------------------------------------------------------------------------------- /pkg/controller/controller.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package controller 17 | 18 | import ( 19 | "sigs.k8s.io/controller-runtime/pkg/manager" 20 | ) 21 | 22 | // AddToManagerFuncs is a list of functions to add all Controllers to the Manager 23 | var AddToManagerFuncs []func(manager.Manager) error 24 | 25 | // AddToManager adds all Controllers to the Manager 26 | func AddToManager(m manager.Manager) error { 27 | for _, f := range AddToManagerFuncs { 28 | if err := f(m); err != nil { 29 | return err 30 | } 31 | } 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /deploy/crds/operator.ibm.com_v1alpha1_grafana_cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.ibm.com/v1alpha1 2 | kind: Grafana 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: ibm-monitoring 6 | app.kubernetes.io/instance: common-monitoring 7 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 8 | name: ibm-monitoring 9 | spec: 10 | service: 11 | ports: 12 | - name: ibm-monitoring-grafana 13 | protocol: TCP 14 | port: 3000 15 | grafanaConfig: 16 | resources: 17 | requests: 18 | cpu: 300m 19 | memory: 512Mi 20 | limits: 21 | cpu: 600m 22 | memory: 1024Mi 23 | dashboardConfig: 24 | resources: 25 | requests: 26 | cpu: 50m 27 | memory: 64Mi 28 | limits: 29 | cpu: 100m 30 | memory: 128Mi 31 | ipVersion: "IPv4" 32 | routerConfig: 33 | resources: 34 | requests: 35 | cpu: 50m 36 | memory: 64Mi 37 | limits: 38 | cpu: 100m 39 | memory: 128Mi 40 | isHub: false 41 | tlsSecretName: ibm-monitoring-certs 42 | tlsClientSecretName: ibm-monitoring-certs 43 | # datasourceConfig: 44 | # type: "openshift" 45 | -------------------------------------------------------------------------------- /common/scripts/install-operator-sdk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2020 IBM Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | echo ">>> Installing Operator SDK" 19 | 20 | # Use version 0.15.1 21 | RELEASE_VERSION=v0.18.0 22 | # Download binary 23 | curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu 24 | # Install binary 25 | chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu && mkdir -p /usr/local/bin/ && cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk && rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu 26 | -------------------------------------------------------------------------------- /pkg/controller/artifacts/entrypoint.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020-2021 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | const entrypoint = `#!/bin/sh 19 | 20 | export CA=$(sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' /opt/ibm/monitoring/ca-certs/ca.crt) 21 | export CERT=$(sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' /opt/ibm/monitoring/certs/tls.crt) 22 | export KEY=$(sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' /opt/ibm/monitoring/certs/tls.key) 23 | 24 | cat >> /etc/grafana/provisioning/datasources/datasource.yaml <**Important:** Do not install this operator directly. Only install this operator using the IBM Common Services Operator. For more information about installing this operator and other Common Services operators, see [Installer documentation](http://ibm.biz/cpcs_opinstall). If you are using this operator as part of an IBM Cloud Pak, see the documentation for that IBM Cloud Pak to learn more about how to install and use the operator service. For more information about IBM Cloud Paks, see [IBM Cloud Paks that use Common Services](http://ibm.biz/cpcs_cloudpaks). 4 | 5 | - The ibm-monitoring-grafana-operator installs the Grafana service. Use the Grafana service to present metrics dashboards that you can use for monitoring. You can also create your own metrics dashboards. 6 | 7 | ## Supported platforms 8 | 9 | Red Hat OpenShift Container Platform 4.x or newer installed on one of the following platforms: 10 | 11 | - Linux x86_64 12 | - Linux on Power (ppc64le) 13 | - Linux on IBM Z and LinuxONE 14 | 15 | ## Operator versions 16 | 17 | - 1.8.0 18 | - 1.8.1 19 | - 1.9.0 20 | 21 | ## Prerequisites 22 | 23 | Before you install this operator, you need to first install the operator dependencies and prerequisites: 24 | 25 | - For the list of operator dependencies, see the IBM Knowledge Center [Common Services dependencies documentation](http://ibm.biz/cpcs_opdependencies). 26 | 27 | - For the list of prerequisites for installing the grafana operator, see the IBM Knowledge Center [Preparing to install services documentation](http://ibm.biz/cpcs_opinstprereq). 28 | 29 | ## Documentation 30 | 31 | To install the operator with the IBM Common Services Operator follow the installation and configuration instructions within the IBM Knowledge Center. 32 | 33 | - If you are using the operator as part of an IBM Cloud Pak, see the documentation for that IBM Cloud Pak. For a list of IBM Cloud Paks, see [IBM Cloud Paks that use Common Services](http://ibm.biz/cpcs_cloudpaks). 34 | - If you are using the operator with an IBM Containerized Software, see the IBM Cloud Platform Common Services Knowledge Center [Installer documentation](http://ibm.biz/cpcs_opinstall). 35 | 36 | ## SecurityContextConstraints Requirements 37 | 38 | The ibm-monitoring-grafana-operator and Grafana operands run under OpenShift Container Platform default restricted security context constraints. 39 | 40 | For more information about the OpenShift Container Platform Security Context Constraints, see [Managing Security Context Constraints](https://docs.openshift.com/container-platform/4.3/authentication/managing-security-context-constraints.html). 41 | 42 | ## Developer guide 43 | 44 | As a developer, if you want to build and test this operator to try out and learn more about the operator and its capabilities, you can use the following developer guide. The guide provides commands for a quick installation and initial validation for running the operator. 45 | 46 | > **Important:** The following developer guide is provided as-is and only for trial and education purposes. IBM and IBM Support does not provide any support for the usage of the operator with this developer guide. For the official supported installation and usage guide for the operator, see the IBM Knowledge Center documentation for your IBM Cloud Pak or for IBM Cloud Platform Common Services. 47 | 48 | ### End-to-End testing 49 | 50 | For more instructions on how to run end-to-end testing with Operand Deployment Lifecycle Manager, see [ODLM guide](https://github.com/IBM/operand-deployment-lifecycle-manager/blob/master/docs/dev/e2e.md). 51 | -------------------------------------------------------------------------------- /pkg/controller/model/constants.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020-2021 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | "time" 20 | ) 21 | 22 | const ( 23 | DefaultThanosURL = "https://thanos-querier.openshift-monitoring.svc:9091" 24 | GrafanaConfigName = "grafana-config" 25 | GrafanaLogVolumes = "grafana-log" 26 | GrafanaDataVolumes = "grafana-storage" 27 | GrafanaDatasourceName = "datasource-config" 28 | GrafanaHealthEndpoint = "/api/health" 29 | DefaultRouterPort = 8080 30 | DefaultClusterPort int32 = 8443 31 | GrafanaAdminSecretName = "grafana-secret" 32 | GrafanaInitMounts = "grafana-init-mount" 33 | GrafanaPlugins = "grafana-plugins" 34 | GrafanaConfigMapsDir = "/etc/grafana-configmaps/" 35 | GrafanaServiceAccountName = "ibm-monitoring-grafana" 36 | GrafanaDeploymentName = "ibm-monitoring-grafana" 37 | GrafanaServiceName = "ibm-monitoring-grafana" 38 | GrafanaHTTPPortName = "web" 39 | RequeueDelay = time.Second * 10 40 | DefaultGrafanaPort int32 = 3000 41 | GrafanaRouteName = "ibm-monitoring-grafana" 42 | GrafanaAdminUserEnvVar = "username" 43 | GrafanaAdminPasswordEnvVar = "password" 44 | ClusterDomain = "cluster.local" 45 | InitContainerName = "init-container" 46 | DefaultInitImage = "quay.io/opencloudio/icp-initcontainer" 47 | DefaultInitImageTag = "1.0.0-build.3" 48 | DefaultDashboardControllerImage = "quay.io/opencloudio/dashboard-controller" 49 | DefaultDashboardControllerImageTag = "v1.2.0-build.3" 50 | DefaultBaseImage = "quay.io/opencloudio/grafana" 51 | DefaultBaseImageTag = "v6.5.2-build.2" 52 | DefaultRouterImage = "quay.io/opencloudio/icp-management-ingress" 53 | DefaultRouterImageTag = "2.5.1" 54 | DSProxyConfigSecName = "grafana-ds-proxy-config" 55 | 56 | grafanaImageEnv = "GRAFANA_IMAGE" 57 | routerImageEnv = "ICP_MANAGEMENT_INGRESS_IMAGE" 58 | dsProxyImageEnv = "GRAFANA_OCPTHANOS_PROXY_IMAGE" 59 | dashboardCtlImageEnv = "DASHBOARD_CONTROLLER_IMAGE" 60 | imageDigestKey = `sha256:` 61 | 62 | //CS Monitoring resources to be cleanedup 63 | CollectdDeploymentName = "ibm-monitoring-collectd" 64 | KubestateDeploymentName = "ibm-monitoring-kube-state" 65 | McmCtlDeploymentName = "ibm-monitoring-mcm-ctl" 66 | NodeExporterDaemonSetName = "ibm-monitoring-nodeexporter" 67 | PrometheusOperatorDeploymentName = "ibm-monitoring-prometheus-operator" 68 | PrometheusStatefulSetName = "prometheus-ibm-monitoring-prometheus" 69 | AlertManagerStatefulsetName = "alertmanager-ibm-monitoring-alertmanager" 70 | ) 71 | -------------------------------------------------------------------------------- /pkg/controller/model/grafana_ingress.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | ingressv1 "k8s.io/api/networking/v1" 20 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "sigs.k8s.io/controller-runtime/pkg/client" 22 | 23 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 24 | ) 25 | 26 | var GrafanaIngressName string = "grafana-ingress" 27 | 28 | func GetIngressLabels(cr *v1alpha1.Grafana) map[string]string { 29 | 30 | labels := map[string]string{ 31 | "app": "grafana", 32 | "component": "grafana", 33 | } 34 | labels = appendCommonLabels(labels) 35 | if cr.Spec.Service != nil && cr.Spec.Service.Labels != nil { 36 | mergeMaps(labels, cr.Spec.Service.Labels) 37 | } 38 | return labels 39 | } 40 | 41 | func GetIngressAnnotations(cr *v1alpha1.Grafana) map[string]string { 42 | annotations := map[string]string{ 43 | "kubernetes.io/ingress.class": "ibm-icp-management", 44 | "icp.management.ibm.com/authz-type": "rbac", 45 | "icp.management.ibm.com/secure-backends": "true", 46 | "icp.management.ibm.com/secure-client-ca-secret": cr.Spec.TLSClientSecretName, 47 | "icp.management.ibm.com/rewrite-target": "/", 48 | } 49 | 50 | if cr.Spec.Service.Annotations != nil && len(cr.Spec.Service.Annotations) != 0 { 51 | mergeMaps(annotations, cr.Spec.Service.Annotations) 52 | } 53 | return annotations 54 | } 55 | 56 | func getIngressSpec() ingressv1.IngressSpec { 57 | pathType := ingressv1.PathType("ImplementationSpecific") 58 | return ingressv1.IngressSpec{ 59 | Rules: []ingressv1.IngressRule{ 60 | { 61 | IngressRuleValue: ingressv1.IngressRuleValue{ 62 | HTTP: &ingressv1.HTTPIngressRuleValue{ 63 | Paths: []ingressv1.HTTPIngressPath{ 64 | { 65 | Path: "/grafana", 66 | PathType: &pathType, 67 | Backend: ingressv1.IngressBackend{ 68 | Service: &ingressv1.IngressServiceBackend{ 69 | Name: GrafanaServiceName, 70 | Port: ingressv1.ServiceBackendPort{ 71 | Number: DefaultGrafanaPort, 72 | }, 73 | }, 74 | }, 75 | }, 76 | }, 77 | }, 78 | }, 79 | }, 80 | }, 81 | } 82 | } 83 | 84 | func GrafanaIngress(cr *v1alpha1.Grafana) *ingressv1.Ingress { 85 | return &ingressv1.Ingress{ 86 | ObjectMeta: v1.ObjectMeta{ 87 | Name: GrafanaIngressName, 88 | Namespace: cr.Namespace, 89 | Labels: GetIngressLabels(cr), 90 | Annotations: GetIngressAnnotations(cr), 91 | }, 92 | Spec: getIngressSpec(), 93 | } 94 | } 95 | 96 | func ReconciledGrafanaIngress(cr *v1alpha1.Grafana, current *ingressv1.Ingress) *ingressv1.Ingress { 97 | 98 | reconciled := current.DeepCopy() 99 | spec := getIngressSpec() 100 | reconciled.Spec = spec 101 | reconciled.Labels = GetIngressLabels(cr) 102 | reconciled.Annotations = GetIngressAnnotations(cr) 103 | return reconciled 104 | } 105 | 106 | func GrafanaIngressSelector(cr *v1alpha1.Grafana) client.ObjectKey { 107 | return client.ObjectKey{ 108 | Namespace: cr.Namespace, 109 | Name: GrafanaIngressName, 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /pkg/controller/model/grafana_router.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020-2021 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | "os" 20 | 21 | corev1 "k8s.io/api/core/v1" 22 | 23 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 24 | conf "github.com/IBM/ibm-monitoring-grafana-operator/pkg/controller/config" 25 | ) 26 | 27 | func getVolumeMountsForRouter() []corev1.VolumeMount { 28 | return []corev1.VolumeMount{ 29 | { 30 | Name: routerConfig, 31 | MountPath: "/opt/ibm/router/nginx/conf/nginx.conf.monitoring", 32 | SubPath: "nginx.conf.monitoring", 33 | }, 34 | { 35 | Name: routerEntry, 36 | MountPath: "/opt/ibm/router/entry", 37 | }, 38 | { 39 | Name: "grafana-storage", 40 | MountPath: "/test", 41 | ReadOnly: true, 42 | }, 43 | { 44 | Name: "ibm-monitoring-ca-certs", 45 | MountPath: "/opt/ibm/router/ca-certs", 46 | }, 47 | { 48 | Name: "ibm-monitoring-certs", 49 | MountPath: "/opt/ibm/router/certs", 50 | }, 51 | { 52 | Name: grafanaLua, 53 | MountPath: "/opt/ibm/router/nginx/conf/grafana.lua", 54 | SubPath: "grafana.lua", 55 | }, 56 | { 57 | Name: utilLua, 58 | MountPath: "/opt/ibm/router/nginx/conf/monitoring-util.lua", 59 | SubPath: "monitoring-util.lua", 60 | }, 61 | } 62 | } 63 | 64 | func getRouterProbe(delay, period, timeout, failureThreshold int, iamNamespace string) *corev1.Probe { 65 | config := conf.GetControllerConfig() 66 | iamServicePort := config.GetConfigString(conf.IAMServicePortName, "") 67 | wget := "wget --spider --no-check-certificate -S 'https://platform-identity-provider" 68 | checkURL := wget + "." + iamNamespace + ".svc." + ClusterDomain + ":" + iamServicePort + "/v1/info'" 69 | checkCMD := []string{"sh", "-c", checkURL} 70 | 71 | handler := corev1.Handler{} 72 | handler.Exec = &corev1.ExecAction{} 73 | handler.Exec.Command = checkCMD 74 | return &corev1.Probe{ 75 | Handler: corev1.Handler{ 76 | Exec: &corev1.ExecAction{ 77 | Command: checkCMD, 78 | }, 79 | }, 80 | InitialDelaySeconds: int32(delay), 81 | PeriodSeconds: int32(period), 82 | TimeoutSeconds: int32(timeout), 83 | FailureThreshold: int32(failureThreshold), 84 | } 85 | } 86 | 87 | func createRouterContainer(cr *v1alpha1.Grafana) corev1.Container { 88 | 89 | var resources corev1.ResourceRequirements 90 | if cr.Spec.RouterConfig != nil && cr.Spec.RouterConfig.Resources != nil { 91 | resources = *cr.Spec.RouterConfig.Resources 92 | } else { 93 | resources = getContainerResource(cr, "Router") 94 | } 95 | 96 | image := imageName(os.Getenv(routerImageEnv), cr.Spec.RouterImage) 97 | 98 | return corev1.Container{ 99 | Name: "router", 100 | Image: image, 101 | Command: []string{"/opt/ibm/router/entry/entrypoint.sh"}, 102 | Ports: []corev1.ContainerPort{ 103 | { 104 | Name: "router", 105 | ContainerPort: DefaultRouterPort, 106 | Protocol: "TCP", 107 | }, 108 | }, 109 | Resources: resources, 110 | LivenessProbe: getRouterProbe(30, 30, 30, 10, cr.Namespace), 111 | ReadinessProbe: getRouterProbe(32, 20, 30, 10, cr.Namespace), 112 | VolumeMounts: getVolumeMountsForRouter(), 113 | Env: setupAdminEnv("GF_SECURITY_ADMIN_USER", "GF_SECURITY_ADMIN_PASSWORD"), 114 | TerminationMessagePath: "/dev/termination-log", 115 | TerminationMessagePolicy: "File", 116 | ImagePullPolicy: "IfNotPresent", 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /deploy/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: ibm-monitoring 7 | app.kubernetes.io/instance: common-monitoring 8 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 9 | creationTimestamp: null 10 | name: ibm-monitoring-grafana-dashboard 11 | rules: 12 | - apiGroups: 13 | - "" 14 | resources: 15 | - namespaces 16 | verbs: 17 | - get 18 | --- 19 | apiVersion: rbac.authorization.k8s.io/v1 20 | kind: ClusterRole 21 | metadata: 22 | labels: 23 | app.kubernetes.io/name: ibm-monitoring 24 | app.kubernetes.io/instance: common-monitoring 25 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 26 | creationTimestamp: null 27 | name: ibm-monitoring-grafana-operator 28 | rules: 29 | - apiGroups: 30 | - "" 31 | resources: 32 | - configmaps 33 | resourceNames: 34 | - cluster-monitoring-config 35 | verbs: 36 | - get 37 | --- 38 | apiVersion: rbac.authorization.k8s.io/v1 39 | kind: Role 40 | metadata: 41 | labels: 42 | app.kubernetes.io/name: ibm-monitoring 43 | app.kubernetes.io/instance: common-monitoring 44 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 45 | creationTimestamp: null 46 | name: ibm-monitoring-grafana-dashboard 47 | rules: 48 | - apiGroups: 49 | - monitoringcontroller.cloud.ibm.com 50 | resources: 51 | - monitoringdashboards 52 | verbs: 53 | - get 54 | - list 55 | - watch 56 | - create 57 | - update 58 | - patch 59 | - delete 60 | --- 61 | apiVersion: rbac.authorization.k8s.io/v1 62 | kind: Role 63 | metadata: 64 | labels: 65 | app.kubernetes.io/name: ibm-monitoring 66 | app.kubernetes.io/instance: common-monitoring 67 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 68 | creationTimestamp: null 69 | name: ibm-monitoring-grafana-operator 70 | rules: 71 | - apiGroups: 72 | - "" 73 | resources: 74 | - pods 75 | - services 76 | - endpoints 77 | - persistentvolumeclaims 78 | - events 79 | - configmaps 80 | - secrets 81 | verbs: 82 | - get 83 | - list 84 | - watch 85 | - create 86 | - update 87 | - patch 88 | - delete 89 | - apiGroups: 90 | - apps 91 | resources: 92 | - deployments 93 | - statefulsets 94 | - replicasets 95 | verbs: 96 | - get 97 | - list 98 | - watch 99 | - create 100 | - update 101 | - patch 102 | - delete 103 | - apiGroups: 104 | - apps 105 | resources: 106 | - daemonsets 107 | verbs: 108 | - delete 109 | - apiGroups: 110 | - certmanager.k8s.io 111 | resources: 112 | - certificates 113 | verbs: 114 | - get 115 | - list 116 | - watch 117 | - create 118 | - update 119 | - patch 120 | - delete 121 | - apiGroups: 122 | - operator.ibm.com 123 | resources: 124 | - grafanas 125 | - grafanas/finalizers 126 | - grafanas/status 127 | verbs: 128 | - get 129 | - list 130 | - watch 131 | - create 132 | - update 133 | - patch 134 | - delete 135 | - apiGroups: 136 | - extensions 137 | resources: 138 | - ingresses 139 | verbs: 140 | - get 141 | - list 142 | - watch 143 | - create 144 | - update 145 | - patch 146 | - delete 147 | - apiGroups: 148 | - networking.k8s.io 149 | resources: 150 | - ingresses 151 | verbs: 152 | - get 153 | - list 154 | - watch 155 | - create 156 | - update 157 | - patch 158 | - delete 159 | - apiGroups: 160 | - monitoringcontroller.cloud.ibm.com 161 | resources: 162 | - monitoringdashboards 163 | verbs: 164 | - get 165 | - list 166 | - watch 167 | - create 168 | - update 169 | - patch 170 | - delete 171 | --- 172 | apiVersion: rbac.authorization.k8s.io/v1 173 | kind: Role 174 | metadata: 175 | labels: 176 | app.kubernetes.io/name: ibm-monitoring 177 | app.kubernetes.io/instance: common-monitoring 178 | app.kubernetes.io/managed-by: ibm-monitoring-grafana-operator 179 | creationTimestamp: null 180 | name: ibm-monitoring-grafana 181 | rules: 182 | - apiGroups: 183 | - "" 184 | resources: 185 | - services 186 | - endpoints 187 | - pods 188 | - configmaps 189 | verbs: 190 | - get 191 | - list 192 | - watch -------------------------------------------------------------------------------- /pkg/controller/model/grafana_dashboard.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020-2021 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | "os" 20 | "strconv" 21 | 22 | corev1 "k8s.io/api/core/v1" 23 | 24 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 25 | ) 26 | 27 | func setVolumeMountsForDashboard() []corev1.VolumeMount { 28 | var mounts []corev1.VolumeMount 29 | 30 | mounts = append(mounts, corev1.VolumeMount{ 31 | Name: grafanaCRD, 32 | MountPath: "/grafana/entry", 33 | }, corev1.VolumeMount{ 34 | Name: "ibm-monitoring-client-certs", 35 | MountPath: "/opt/ibm/monitoring/certs", 36 | }, corev1.VolumeMount{ 37 | Name: "ibm-monitoring-ca-certs", 38 | MountPath: "/opt/ibm/monitoring/ca-certs", 39 | }, corev1.VolumeMount{ 40 | Name: grafanaDefaultDashboard, 41 | MountPath: "/opt/dashboards", 42 | }) 43 | return mounts 44 | 45 | } 46 | 47 | func setupDashboardEnv(cr *v1alpha1.Grafana) []corev1.EnvVar { 48 | 49 | var isHub bool 50 | var version, prometheusHost, loopback string 51 | var clusterPort, prometheusPort int32 52 | 53 | if cr.Spec.ClusterPort != 0 { 54 | clusterPort = cr.Spec.ClusterPort 55 | } else { 56 | clusterPort = DefaultClusterPort 57 | } 58 | 59 | prometheusHost, prometheusPort = prometheusInfo(cr) 60 | 61 | envs := []corev1.EnvVar{} 62 | envs = append(envs, setupAdminEnv("USER", "PASSWORD")...) 63 | if cr.Spec.IsHub { 64 | isHub = true 65 | } else { 66 | isHub = false 67 | } 68 | 69 | if cr.Spec.IPVersion != "" { 70 | version = cr.Spec.IPVersion 71 | } else if cr.Spec.DashboardsConfig != nil && cr.Spec.DashboardsConfig.IPVersion != "" { 72 | version = cr.Spec.DashboardsConfig.IPVersion 73 | } else { 74 | version = "IPv4" 75 | } 76 | 77 | if version == "IPv6" { 78 | loopback = "[::1]" 79 | } else { 80 | loopback = "127.0.0.1" 81 | } 82 | 83 | envs = append(envs, corev1.EnvVar{ 84 | Name: "PROMETHEUS_HOST", 85 | Value: prometheusHost, 86 | }, corev1.EnvVar{ 87 | Name: "PROMETHEUS_PORT", 88 | Value: strconv.FormatInt(int64(prometheusPort), 10), 89 | }, corev1.EnvVar{ 90 | Name: "PORT", 91 | Value: strconv.FormatInt(int64(clusterPort), 10), 92 | }, corev1.EnvVar{ 93 | Name: "IS_HUB_CLUSTER", 94 | Value: strconv.FormatBool(isHub), 95 | }, corev1.EnvVar{ 96 | Name: "LOOPBACK", 97 | Value: loopback, 98 | }, corev1.EnvVar{ 99 | Name: "NAMESPACE", 100 | Value: cr.Namespace, 101 | }, corev1.EnvVar{ 102 | Name: "DASH_NAMESPACES", 103 | Value: getDashNamespaces(cr), 104 | }) 105 | 106 | return envs 107 | } 108 | 109 | func createDashboardContainer(cr *v1alpha1.Grafana) corev1.Container { 110 | 111 | var resources corev1.ResourceRequirements 112 | image := imageName(os.Getenv(dashboardCtlImageEnv), cr.Spec.DashboardControllerImage) 113 | if cr.Spec.DashboardsConfig != nil && cr.Spec.DashboardsConfig.Resources != nil { 114 | resources = *cr.Spec.DashboardsConfig.Resources 115 | } else { 116 | resources = getContainerResource(cr, "Dashboard") 117 | } 118 | return corev1.Container{ 119 | Name: "dashboard-controller", 120 | Image: image, 121 | ImagePullPolicy: "IfNotPresent", 122 | Resources: resources, 123 | LivenessProbe: getProbe(40, 30, 10), 124 | ReadinessProbe: getProbe(30, 30, 10), 125 | Command: []string{"/grafana/entry/run.sh"}, 126 | Env: setupDashboardEnv(cr), 127 | VolumeMounts: setVolumeMountsForDashboard(), 128 | TerminationMessagePath: "/dev/termination-log", 129 | TerminationMessagePolicy: "File", 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /pkg/controller/dashboards/init.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package dashboards 17 | 18 | import ( 19 | "fmt" 20 | "io/ioutil" 21 | "path/filepath" 22 | "strings" 23 | 24 | dbv1 "github.ibm.com/IBMPrivateCloud/grafana-dashboard-crd/pkg/apis/monitoringcontroller/v1" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | logf "sigs.k8s.io/controller-runtime/pkg/log" 27 | 28 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 29 | ) 30 | 31 | // DefaultDashboards store default dashboards 32 | var DefaultDashboards map[string]string 33 | var dashboardsData map[string]string 34 | var log = logf.Log.WithName("dashboard") 35 | 36 | // DefaultDBsStatus store the status of dashboards, the initial statuses 37 | // are all enabled. 38 | var DefaultDBsStatus map[string]bool 39 | 40 | func appendCommonLabels(labels map[string]string) map[string]string { 41 | labels["app.kubernetes.io/name"] = "ibm-monitoring" 42 | labels["app.kubernetes.io/instance"] = "common-monitoring" 43 | labels["app.kubernetes.io/managed-by"] = "ibm-monitoring-exporters-operator" 44 | return labels 45 | } 46 | 47 | func CreateDashboard(namespace, name string, status bool) *dbv1.MonitoringDashboard { 48 | 49 | labels := map[string]string{"app": "ibm-monitoring-grafana", "component": "grafana"} 50 | labels = appendCommonLabels(labels) 51 | dashboardJSON := dashboardsData[name] 52 | return &dbv1.MonitoringDashboard{ 53 | TypeMeta: metav1.TypeMeta{APIVersion: dbv1.SchemeGroupVersion.String()}, 54 | ObjectMeta: metav1.ObjectMeta{ 55 | Name: name, 56 | Namespace: namespace, 57 | Labels: labels, 58 | }, 59 | Spec: dbv1.MonitoringDashboardSpec{ 60 | Data: dashboardJSON, 61 | Enabled: status, 62 | }, 63 | } 64 | } 65 | 66 | func ReconcileDashboardsStatus(cr *v1alpha1.Grafana) { 67 | var newStatus map[string]bool 68 | if cr.Spec.DashboardsConfig != nil { 69 | if cr.Spec.DashboardsConfig.DashboardsStatus != nil { 70 | newStatus = cr.Spec.DashboardsConfig.DashboardsStatus 71 | } 72 | } 73 | 74 | if cr.Spec.IsHub { 75 | DefaultDBsStatus["mcm-clusters-monitoring"] = true 76 | } 77 | 78 | for dbName, status := range newStatus { 79 | if _, ok := DefaultDBsStatus[dbName]; ok { 80 | DefaultDBsStatus[dbName] = status 81 | } 82 | } 83 | 84 | } 85 | 86 | // Initialize DefaultDashboards, dashboardsData, DefaultDBsStatus 87 | func init() { 88 | DefaultDashboards = map[string]string{} 89 | dashboardsData = map[string]string{} 90 | DefaultDBsStatus = map[string]bool{} 91 | 92 | dashboardDir := "/dashboards/" 93 | files, err := ioutil.ReadDir(dashboardDir) 94 | if err != nil { 95 | log.Error(err, "Fail to read dashboard file") 96 | panic(err) 97 | } 98 | for _, file := range files { 99 | fileName := file.Name() 100 | filePath := dashboardDir + fileName 101 | jsData, err := ioutil.ReadFile(filePath) 102 | if err != nil { 103 | log.Error(err, fmt.Sprintf("Fail to marshal json file %s", fileName)) 104 | panic(err) 105 | } 106 | name := strings.TrimSuffix(fileName, filepath.Ext(fileName)) 107 | dashboardsData[name] = string(jsData) 108 | DefaultDBsStatus[name] = true 109 | } 110 | // Set default dashboards status 111 | DefaultDBsStatus["mcm-clusters-monitoring"] = false 112 | DefaultDBsStatus["cs-calico-monitoring"] = false 113 | DefaultDBsStatus["cs-glusterfs-monitoring"] = false 114 | DefaultDBsStatus["cs-minio-monitoring"] = false 115 | DefaultDBsStatus["etcd-monitoring"] = false 116 | DefaultDBsStatus["cs-rook-ceph-monitoring"] = false 117 | 118 | DefaultDashboards["mcm-clusters-monitoring.json"] = dashboardsData["mcm-clusters-monitoring"] 119 | DefaultDashboards["kubernetes-pod-overview.json"] = dashboardsData["kubernetes-pod-overview"] 120 | } 121 | -------------------------------------------------------------------------------- /pkg/controller/artifacts/router_config.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package artifacts 17 | 18 | // With parameters: ClusterPort and Environment 19 | const routerConfig = ` 20 | error_log stderr notice; 21 | 22 | events { 23 | worker_connections 1024; 24 | } 25 | 26 | http { 27 | access_log off; 28 | 29 | include /opt/ibm/router/nginx/conf/mime.types; 30 | default_type application/octet-stream; 31 | sendfile on; 32 | keepalive_timeout 65; 33 | server_tokens off; 34 | more_set_headers "Server: "; 35 | 36 | # Without this, cosocket-based code in worker 37 | # initialization cannot resolve localhost. 38 | 39 | upstream grafana { 40 | server 127.0.0.1:{{ .ClusterPort }}; 41 | } 42 | 43 | proxy_cache_path /tmp/nginx-mesos-cache levels=1:2 keys_zone=mesos:1m inactive=10m; 44 | 45 | lua_package_path '$prefix/conf/?.lua;;'; 46 | lua_shared_dict mesos_state_cache 100m; 47 | lua_shared_dict shmlocks 1m; 48 | 49 | init_by_lua ' 50 | grafana = require "grafana" 51 | '; 52 | {{- if eq .Environment "openshift" -}} 53 | resolver local=on; 54 | {{- else -}} 55 | resolver kube-dns; 56 | {{- end -}} 57 | 58 | server { 59 | listen 8445 ssl default_server; 60 | ssl_certificate /opt/ibm/router/certs/tls.crt; 61 | ssl_certificate_key /opt/ibm/router/certs/tls.key; 62 | ssl_client_certificate /opt/ibm/router/ca-certs/ca.crt; 63 | ssl_verify_client on; 64 | ssl_protocols TLSv1.2; 65 | # Ref: https://github.com/cloudflare/sslconfig/blob/master/conf 66 | # Modulo ChaCha20 cipher. 67 | ssl_ciphers EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!EECDH+3DES:!RSA+3DES:!MD5; 68 | ssl_prefer_server_ciphers on; 69 | 70 | server_name dcos.*; 71 | root /opt/ibm/router/nginx/html; 72 | 73 | location /check_stale_users { 74 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 75 | proxy_set_header Host $http_host; 76 | rewrite_by_lua 'grafana.check_stale_users()'; 77 | } 78 | 79 | location /public { 80 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 81 | proxy_set_header Host $http_host; 82 | proxy_pass https://grafana/public; 83 | proxy_ssl_certificate /opt/ibm/router/certs/tls.crt; 84 | proxy_ssl_certificate_key /opt/ibm/router/certs/tls.key; 85 | header_filter_by_lua_block { 86 | ngx.header.Authorization = "Basic {{ .GrafanaCredential }}" 87 | ngx.header["Cache-control"] = "no-cache, no-store, must-revalidate" 88 | ngx.header["Pragma"] = "no-cache" 89 | ngx.header["Access-Control-Allow-Credentials"] = "false" 90 | } 91 | } 92 | 93 | location / { 94 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 95 | proxy_set_header Host $http_host; 96 | header_filter_by_lua_block { 97 | ngx.header["Cache-control"] = "no-cache, no-store, must-revalidate" 98 | ngx.header["Pragma"] = "no-cache" 99 | ngx.header["Access-Control-Allow-Credentials"] = "false" 100 | } 101 | rewrite_by_lua 'grafana.rewrite_grafana_header()'; 102 | proxy_pass https://grafana/; 103 | proxy_ssl_certificate /opt/ibm/router/certs/tls.crt; 104 | proxy_ssl_certificate_key /opt/ibm/router/certs/tls.key; 105 | } 106 | 107 | location /index.html { 108 | return 404; 109 | } 110 | } 111 | } 112 | ` 113 | -------------------------------------------------------------------------------- /pkg/controller/model/grafana_service.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | corev1 "k8s.io/api/core/v1" 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/util/intstr" 22 | "sigs.k8s.io/controller-runtime/pkg/client" 23 | 24 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 25 | ) 26 | 27 | func getServiceLabels(cr *v1alpha1.Grafana) map[string]string { 28 | labels := map[string]string{ 29 | "app": "grafana", 30 | "component": "grafana", 31 | } 32 | labels = appendCommonLabels(labels) 33 | 34 | if cr.Spec.Service != nil && cr.Spec.Service.Labels != nil { 35 | mergeMaps(labels, cr.Spec.Service.Labels) 36 | } 37 | 38 | return labels 39 | } 40 | 41 | func getServiceAnnotations(cr *v1alpha1.Grafana) map[string]string { 42 | if cr.Spec.Service == nil { 43 | return nil 44 | } 45 | 46 | return cr.Spec.Service.Annotations 47 | } 48 | 49 | func getServiceType(cr *v1alpha1.Grafana) corev1.ServiceType { 50 | if cr.Spec.Service == nil { 51 | return corev1.ServiceTypeClusterIP 52 | } 53 | if cr.Spec.Service.Type == "" { 54 | return corev1.ServiceTypeClusterIP 55 | } 56 | return cr.Spec.Service.Type 57 | } 58 | 59 | func getServicePorts(cr *v1alpha1.Grafana, currentState *corev1.Service) []corev1.ServicePort { 60 | intPort := DefaultGrafanaPort 61 | 62 | defaultPorts := []corev1.ServicePort{ 63 | { 64 | Name: GrafanaHTTPPortName, 65 | Protocol: "TCP", 66 | Port: intPort, 67 | TargetPort: intstr.IntOrString{ 68 | Type: intstr.Int, 69 | IntVal: 8445, 70 | }, 71 | }, 72 | } 73 | 74 | if cr.Spec.Service == nil { 75 | return defaultPorts 76 | } 77 | 78 | // Re-assign existing node port 79 | if cr.Spec.Service != nil && 80 | currentState != nil && 81 | cr.Spec.Service.Type == corev1.ServiceTypeNodePort { 82 | for _, port := range currentState.Spec.Ports { 83 | if port.Name == GrafanaHTTPPortName { 84 | defaultPorts[0].NodePort = port.NodePort 85 | } 86 | } 87 | } 88 | 89 | if cr.Spec.Service.Ports == nil { 90 | return defaultPorts 91 | } 92 | 93 | // Don't allow overriding the default port but allow adding 94 | // additional ports 95 | for _, port := range cr.Spec.Service.Ports { 96 | if port.Name == GrafanaHTTPPortName || port.Port == intPort { 97 | continue 98 | } 99 | defaultPorts = append(defaultPorts, port) 100 | } 101 | 102 | return defaultPorts 103 | } 104 | 105 | func getGrafanaSelectors(cr *v1alpha1.Grafana) map[string]string { 106 | selectors := map[string]string{ 107 | "app": "grafana", 108 | "component": "grafana", 109 | } 110 | 111 | if cr.Spec.Service != nil && cr.Spec.Service.Selector != nil { 112 | mergeMaps(selectors, cr.Spec.Service.Selector) 113 | } 114 | 115 | return selectors 116 | } 117 | 118 | func GrafanaService(cr *v1alpha1.Grafana) *corev1.Service { 119 | return &corev1.Service{ 120 | ObjectMeta: metav1.ObjectMeta{ 121 | Name: GrafanaServiceName, 122 | Namespace: cr.Namespace, 123 | Labels: getServiceLabels(cr), 124 | Annotations: getServiceAnnotations(cr), 125 | }, 126 | Spec: corev1.ServiceSpec{ 127 | Ports: getServicePorts(cr, nil), 128 | Selector: getGrafanaSelectors(cr), 129 | ClusterIP: "", 130 | Type: getServiceType(cr), 131 | }, 132 | } 133 | } 134 | 135 | func ReconciledGrafanaService(cr *v1alpha1.Grafana, current *corev1.Service) *corev1.Service { 136 | reconciled := current.DeepCopy() 137 | reconciled.Labels = getServiceLabels(cr) 138 | reconciled.Annotations = getServiceAnnotations(cr) 139 | reconciled.Spec.Ports = getServicePorts(cr, current) 140 | reconciled.Spec.Type = getServiceType(cr) 141 | reconciled.Spec.Selector = getGrafanaSelectors(cr) 142 | return reconciled 143 | } 144 | 145 | func GrafanaServiceSelector(cr *v1alpha1.Grafana) client.ObjectKey { 146 | return client.ObjectKey{ 147 | Namespace: cr.Namespace, 148 | Name: GrafanaServiceName, 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /common/Makefile.common.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 IBM Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | ############################################################ 18 | # install git hooks 19 | ############################################################ 20 | INSTALL_HOOKS := $(shell find .git/hooks -type l -exec rm {} \; && \ 21 | find common/scripts/.githooks -type f -exec ln -sf ../../{} .git/hooks/ \; ) 22 | 23 | ############################################################ 24 | # GKE section 25 | ############################################################ 26 | PROJECT ?= oceanic-guard-191815 27 | ZONE ?= us-east5-c 28 | CLUSTER ?= bedrock-prow 29 | tt3=$(shell which 2to3) 30 | 31 | activate-serviceaccount: 32 | ifdef GOOGLE_APPLICATION_CREDENTIALS 33 | @gcloud auth activate-service-account --key-file="$(GOOGLE_APPLICATION_CREDENTIALS)" 34 | endif 35 | 36 | get-cluster-credentials: activate-serviceaccount 37 | mkdir -p ~/.kube; cp -v /etc/kubeconfig/config ~/.kube; kubectl config use-context default; kubectl get nodes; echo going forward retiring google cloud 38 | ifdef GOOGLE_APPLICATION_CREDENTIALS 39 | @gcloud container clusters get-credentials "$(CLUSTER)" --project="$(PROJECT)" --zone="$(ZONE)" 40 | endif 41 | 42 | config-docker: get-cluster-credentials 43 | @common/scripts/config_docker.sh 44 | 45 | ############################################################ 46 | # lint section 47 | ############################################################ 48 | 49 | FINDFILES=find . \( -path ./.git -o -path ./.github \) -prune -o -type f 50 | XARGS = xargs -0 ${XARGS_FLAGS} 51 | CLEANXARGS = xargs ${XARGS_FLAGS} 52 | 53 | lint-dockerfiles: 54 | @${FINDFILES} -name 'Dockerfile*' -print0 | ${XARGS} hadolint -c ./common/config/.hadolint.yml 55 | 56 | lint-scripts: 57 | @${FINDFILES} -name '*.sh' -print0 | ${XARGS} shellcheck 58 | 59 | lint-yaml: 60 | @${FINDFILES} \( -name '*.yml' -o -name '*.yaml' \) -print0 | ${XARGS} grep -L -e "{{" | ${CLEANXARGS} yamllint -c ./common/config/.yamllint.yml 61 | 62 | lint-helm: 63 | @${FINDFILES} -name 'Chart.yaml' -print0 | ${XARGS} -L 1 dirname | ${CLEANXARGS} helm lint 64 | 65 | lint-copyright-banner: 66 | @${FINDFILES} \( -name '*.go' -o -name '*.cc' -o -name '*.h' -o -name '*.proto' -o -name '*.py' -o -name '*.sh' \) \( ! \( -name '*.gen.go' -o -name '*.pb.go' -o -name '*_pb2.py' \) \) -print0 |\ 67 | ${XARGS} common/scripts/lint_copyright_banner.sh 68 | 69 | lint-go: 70 | @${FINDFILES} -name '*.go' \( ! \( -name '*.gen.go' -o -name '*.pb.go' \) \) -print0 | ${XARGS} common/scripts/lint_go.sh 71 | 72 | lint-python: 73 | ifeq (${tt3},) 74 | @apt update 75 | @apt install -y 2to3 76 | endif 77 | @${FINDFILES} -name '*.py' \( ! \( -name '*_pb2.py' \) \) -print0 | ${XARGS} autopep8 --max-line-length 160 --exit-code -d 78 | 79 | lint-markdown: 80 | @${FINDFILES} -name '*.md' -print0 | ${XARGS} mdl --ignore-front-matter --style common/config/mdl.rb 81 | ifdef MARKDOWN_LINT_WHITELIST 82 | @${FINDFILES} -name '*.md' -print0 | ${XARGS} awesome_bot --skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect --white-list ${MARKDOWN_LINT_WHITELIST} 83 | else 84 | @${FINDFILES} -name '*.md' -print0 | ${XARGS} awesome_bot --skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect 85 | endif 86 | 87 | lint-sass: 88 | @${FINDFILES} -name '*.scss' -print0 | ${XARGS} sass-lint -c common/config/sass-lint.yml --verbose 89 | 90 | lint-typescript: 91 | @${FINDFILES} -name '*.ts' -print0 | ${XARGS} tslint -c common/config/tslint.json 92 | 93 | lint-protos: 94 | @$(FINDFILES) -name '*.proto' -print0 | $(XARGS) -L 1 prototool lint --protoc-bin-path=/usr/bin/protoc 95 | 96 | lint-all: lint-dockerfiles lint-scripts lint-yaml lint-helm lint-copyright-banner lint-go lint-python lint-markdown lint-sass lint-typescript lint-protos 97 | 98 | format-go: 99 | @${FINDFILES} -name '*.go' \( ! \( -name '*.gen.go' -o -name '*.pb.go' \) \) -print0 | ${XARGS} goimports -w -local "github.com/IBM" 100 | 101 | format-python: 102 | @${FINDFILES} -name '*.py' -print0 | ${XARGS} autopep8 --max-line-length 160 --aggressive --aggressive -i 103 | 104 | format-protos: 105 | @$(FINDFILES) -name '*.proto' -print0 | $(XARGS) -L 1 prototool format -w 106 | 107 | .PHONY: lint-dockerfiles lint-scripts lint-yaml lint-copyright-banner lint-go lint-python lint-helm lint-markdown lint-sass lint-typescript lint-protos lint-all format-go format-python format-protos config-docker 108 | -------------------------------------------------------------------------------- /common/scripts/csv-protect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # Copyright 2020 IBM Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | import os 19 | import fnmatch 20 | import yaml 21 | import pathlib 22 | import subprocess 23 | import json 24 | 25 | try: 26 | from yaml import CLoader as Loader, CDumper as Dumper 27 | except ImportError: 28 | from yaml import Loader, Dumper 29 | 30 | 31 | def packagePathes(): 32 | projectDir = pathlib.Path(os.path.abspath(__file__)).parent.parent.parent 33 | packageFilePattern = "*.package.yaml" 34 | packageFile = "" 35 | catalogDir = "" 36 | for currentFile in pathlib.Path(pathlib.Path.joinpath(projectDir, "deploy", "olm-catalog")).rglob(packageFilePattern): 37 | packageFile = currentFile 38 | catalogDir = pathlib.Path(packageFile).parent 39 | break 40 | return str(projectDir), str(catalogDir), str(packageFile) 41 | 42 | 43 | def modifiedFiles(projectDir): 44 | process = subprocess.Popen(['git', 'diff', "--name-only"], 45 | stdout=subprocess.PIPE, 46 | universal_newlines=True, 47 | cwd=str(projectDir)) 48 | unstagedFiles = process.stdout.readlines() 49 | 50 | process = subprocess.Popen(['git', 'diff', "--name-only", "--cached"], 51 | stdout=subprocess.PIPE, 52 | universal_newlines=True, 53 | cwd=str(projectDir)) 54 | 55 | stagedFiles = process.stdout.readlines() 56 | 57 | changedFiles = unstagedFiles + stagedFiles 58 | for i in range(len(changedFiles)): 59 | changedFiles[i] = str(pathlib.Path( 60 | changedFiles[i].rstrip('\n')).absolute()) 61 | return changedFiles 62 | 63 | 64 | def devCSV(packageFile, catalogDir): 65 | devCSV = "" 66 | devCSVPath = "" 67 | isNew = True 68 | stream = open(packageFile, 'r') 69 | packageContent = yaml.load(stream, Loader=Loader) 70 | for channel in packageContent["channels"]: 71 | if channel["name"] == "dev": 72 | devCSV = channel["currentCSV"] 73 | for channel in packageContent["channels"]: 74 | if channel["name"] != "dev" and channel["currentCSV"] == devCSV: 75 | isNew = False 76 | 77 | csvFilePattern = "*.clusterserviceversion.yaml" 78 | for csv in pathlib.Path(str(catalogDir)).rglob(csvFilePattern): 79 | if devCSV in str(csv): 80 | devCSVPath = str(csv) 81 | 82 | return devCSV, devCSVPath, isNew 83 | 84 | 85 | def allCSVs(catalogDir): 86 | csvFilePattern = "*.clusterserviceversion.yaml" 87 | csvNames = [] 88 | for csv in pathlib.Path(catalogDir).rglob(csvFilePattern): 89 | csvNames.append(str(csv)) 90 | return csvNames 91 | 92 | 93 | def validateExampleCR(csv, catalogDir): 94 | print(("valiate CR examples defined in csv: {0}".format( 95 | str(pathlib.Path(csv).relative_to(catalogDir))))) 96 | stream = open(csv, 'r') 97 | csvContent = yaml.load(stream, Loader=Loader) 98 | crs = csvContent["metadata"]["annotations"]["alm-examples"] 99 | json.loads(crs) 100 | print("CR examples are validated") 101 | return True 102 | 103 | 104 | def main(): 105 | print("start to check csv files") 106 | projectDir, catalogDir, packageFile = packagePathes() 107 | print(("project dir: {0}".format(projectDir))) 108 | changedFiles = modifiedFiles(projectDir) 109 | devCSVName, devCSVPath, devCSVIsNew = devCSV(packageFile, catalogDir) 110 | print(("find dev csv: {0}".format(devCSVName))) 111 | 112 | if devCSVName == "": 113 | print("ERROR: dev channel is not defined") 114 | exit(1) 115 | csvs = allCSVs(catalogDir) 116 | for csv in csvs: 117 | for changeFile in changedFiles: 118 | if csv == changeFile: 119 | if csv == devCSVName and (not devCSVIsNew): 120 | print(("ERROR: modifing csv: {0}".format(csv))) 121 | exit(1) 122 | if csv != devCSVPath: 123 | print(("ERROR: modifing csv: {0}".format(csv))) 124 | exit(1) 125 | if not validateExampleCR(devCSVPath, catalogDir): 126 | print(( 127 | "ERROR: failed to validate csv: {0}".format(devCSVPath))) 128 | exit(1) 129 | print("csv check passed") 130 | 131 | 132 | if __name__ == "__main__": 133 | main() 134 | -------------------------------------------------------------------------------- /pkg/controller/model/utils.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020-2021 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | "os" 20 | "reflect" 21 | "strconv" 22 | "strings" 23 | 24 | corev1 "k8s.io/api/core/v1" 25 | "k8s.io/apimachinery/pkg/api/resource" 26 | 27 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 28 | ) 29 | 30 | var memoryRequest int = 256 31 | var cpuRequest int = 200 32 | var memoryLimit int = 512 33 | var cpuLimit int = 500 34 | var dashNamespaces string 35 | 36 | func getDashNamespaces(cr *v1alpha1.Grafana) string { 37 | namespaces := strings.Split(dashNamespaces, ",") 38 | for _, ns := range namespaces { 39 | if ns == cr.Namespace { 40 | return dashNamespaces 41 | } 42 | } 43 | return dashNamespaces + "," + cr.Namespace 44 | 45 | } 46 | func prometheusInfo(cr *v1alpha1.Grafana) (host string, port int32) { 47 | // return OCP prometheus host and ports 48 | host = "localhost" 49 | port = 9096 50 | 51 | return host, port 52 | } 53 | func IssuerName(cr *v1alpha1.Grafana) string { 54 | issuer := "cs-ca-issuer" 55 | if cr.Spec.Issuer != "" { 56 | issuer = cr.Spec.Issuer 57 | 58 | } 59 | return issuer 60 | } 61 | func IssuerType(cr *v1alpha1.Grafana) string { 62 | t := "Issuer" 63 | if cr.Spec.IssuerType != "" { 64 | t = cr.Spec.IssuerType 65 | 66 | } 67 | return t 68 | } 69 | func ThanosURL(cr *v1alpha1.Grafana) string { 70 | thanosURL := DefaultThanosURL 71 | if cr.Spec.DataSourceConfig != nil && 72 | cr.Spec.DataSourceConfig.OCPDSConfig != nil && 73 | cr.Spec.DataSourceConfig.OCPDSConfig.URL != "" { 74 | thanosURL = cr.Spec.DataSourceConfig.OCPDSConfig.URL 75 | } 76 | return thanosURL 77 | 78 | } 79 | 80 | func mergeMaps(to, from map[string]string) { 81 | for key, val := range from { 82 | to[key] = val 83 | } 84 | } 85 | func imageName(defaultV string, overwrite string) string { 86 | if strings.Contains(overwrite, imageDigestKey) { 87 | return overwrite 88 | } 89 | 90 | return defaultV 91 | 92 | } 93 | 94 | func getContainerResource(cr *v1alpha1.Grafana, name string) corev1.ResourceRequirements { 95 | 96 | var resources *v1alpha1.GrafanaResources 97 | var times int 98 | if cr.Spec.Resources != nil { 99 | resources = cr.Spec.Resources 100 | } else { 101 | times = 1 102 | } 103 | 104 | if resources != nil { 105 | r := reflect.ValueOf(resources) 106 | value := reflect.Indirect(r).FieldByName(name) 107 | times = int(value.Int()) 108 | } 109 | 110 | return getResource(times) 111 | } 112 | 113 | func getResource(times int) corev1.ResourceRequirements { 114 | 115 | MR := strconv.Itoa(memoryRequest*times) + "Mi" 116 | CR := strconv.Itoa(cpuRequest*times) + "m" 117 | ML := strconv.Itoa(memoryLimit*times) + "Mi" 118 | CL := strconv.Itoa(cpuLimit*times) + "m" 119 | return corev1.ResourceRequirements{ 120 | Requests: corev1.ResourceList{ 121 | corev1.ResourceMemory: resource.MustParse(MR), 122 | corev1.ResourceCPU: resource.MustParse(CR), 123 | }, 124 | Limits: corev1.ResourceList{ 125 | corev1.ResourceMemory: resource.MustParse(ML), 126 | corev1.ResourceCPU: resource.MustParse(CL), 127 | }, 128 | } 129 | 130 | } 131 | 132 | func createVolumeFromCM(name string) corev1.Volume { 133 | 134 | var stringMode string 135 | 136 | stringMode = "0664" 137 | if strings.Contains(name, "entry") { 138 | stringMode = "0777" 139 | } 140 | 141 | mode, _ := strconv.ParseInt(stringMode, 8, 32) 142 | defaultMode := int32(mode) 143 | 144 | return corev1.Volume{ 145 | Name: name, 146 | VolumeSource: corev1.VolumeSource{ 147 | ConfigMap: &corev1.ConfigMapVolumeSource{ 148 | LocalObjectReference: corev1.LocalObjectReference{ 149 | Name: name, 150 | }, 151 | DefaultMode: &defaultMode, 152 | }, 153 | }, 154 | } 155 | } 156 | 157 | func createVolumeFromSecret(secretName, volumeName string) corev1.Volume { 158 | return corev1.Volume{ 159 | Name: volumeName, 160 | VolumeSource: corev1.VolumeSource{ 161 | Secret: &corev1.SecretVolumeSource{ 162 | SecretName: secretName, 163 | }, 164 | }, 165 | } 166 | } 167 | 168 | func setupAdminEnv(username, password string) []corev1.EnvVar { 169 | return []corev1.EnvVar{ 170 | { 171 | Name: username, 172 | ValueFrom: &corev1.EnvVarSource{ 173 | SecretKeyRef: &corev1.SecretKeySelector{ 174 | LocalObjectReference: corev1.LocalObjectReference{ 175 | Name: GrafanaAdminSecretName, 176 | }, 177 | Key: GrafanaAdminUserEnvVar, 178 | }, 179 | }, 180 | }, 181 | { 182 | Name: password, 183 | ValueFrom: &corev1.EnvVarSource{ 184 | SecretKeyRef: &corev1.SecretKeySelector{ 185 | LocalObjectReference: corev1.LocalObjectReference{ 186 | Name: GrafanaAdminSecretName, 187 | }, 188 | Key: GrafanaAdminPasswordEnvVar, 189 | }, 190 | }, 191 | }, 192 | } 193 | } 194 | 195 | func appendCommonLabels(labels map[string]string) map[string]string { 196 | labels["app.kubernetes.io/name"] = "ibm-monitoring" 197 | labels["app.kubernetes.io/instance"] = "common-monitoring" 198 | labels["app.kubernetes.io/managed-by"] = "ibm-monitoring-grafana-operator" 199 | return labels 200 | } 201 | 202 | func init() { 203 | dashNamespaces = os.Getenv("DASH_NAMESPACES") 204 | } 205 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/IBM/ibm-monitoring-grafana-operator 2 | 3 | go 1.18 4 | 5 | require ( 6 | //github.com/jetstack/cert-manager v0.13.0 7 | github.com/ibm/ibm-cert-manager-operator v0.0.0-20220602233809-3a62073266c7 8 | github.com/operator-framework/operator-sdk v0.18.0 9 | sigs.k8s.io/controller-runtime v0.10.0 10 | ) 11 | 12 | // Pinned to kubernetes-0.21.2 13 | replace ( 14 | k8s.io/api => k8s.io/api v0.22.0 15 | k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.2 16 | k8s.io/apimachinery => k8s.io/apimachinery v0.22.0 17 | k8s.io/apiserver => k8s.io/apiserver v0.21.2 18 | k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.2 19 | k8s.io/client-go => k8s.io/client-go v0.22.0 20 | k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.2 21 | k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.2 22 | k8s.io/code-generator => k8s.io/code-generator v0.21.2 23 | k8s.io/component-base => k8s.io/component-base v0.21.2 24 | k8s.io/cri-api => k8s.io/cri-api v0.21.2 25 | k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.2 26 | k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.2 27 | k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.2 28 | k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.2 29 | k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.2 30 | k8s.io/kubectl => k8s.io/kubectl v0.21.2 31 | k8s.io/kubelet => k8s.io/kubelet v0.21.2 32 | k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.2 33 | k8s.io/metrics => k8s.io/metrics v0.21.2 34 | k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.2 35 | ) 36 | 37 | replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 38 | 39 | replace github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.11.1 40 | 41 | replace github.com/docker/docker => github.com/moby/moby v17.10.0-ce+incompatible // Required by Helm 42 | 43 | replace golang.org/x/crypto => golang.org/x/crypto v0.18.0 44 | 45 | replace golang.org/x/net => golang.org/x/net v0.23.0 46 | 47 | replace golang.org/x/sys => golang.org/x/sys v0.6.0 48 | 49 | replace golang.org/x/text => golang.org/x/text v0.8.0 50 | 51 | // pinned to cert manager v0.10 52 | replace github.com/Azure/go-autorest => github.com/Azure/go-autorest v14.2.0+incompatible 53 | 54 | require ( 55 | github.com/spf13/pflag v1.0.5 56 | github.ibm.com/IBMPrivateCloud/grafana-dashboard-crd v1.2.0 57 | k8s.io/api v0.22.1 58 | k8s.io/apimachinery v0.22.1 59 | k8s.io/client-go v12.0.0+incompatible 60 | k8s.io/kube-openapi v0.0.0-20210527164424-3c818078ee3d 61 | sigs.k8s.io/yaml v1.2.0 62 | ) 63 | 64 | require ( 65 | cloud.google.com/go v0.56.0 // indirect 66 | github.com/Azure/go-autorest v14.2.0+incompatible // indirect 67 | github.com/Azure/go-autorest/autorest v0.11.18 // indirect 68 | github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect 69 | github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect 70 | github.com/Azure/go-autorest/logger v0.2.1 // indirect 71 | github.com/Azure/go-autorest/tracing v0.6.0 // indirect 72 | github.com/PuerkitoBio/purell v1.1.1 // indirect 73 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 74 | github.com/beorn7/perks v1.0.1 // indirect 75 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 76 | github.com/coreos/prometheus-operator v0.38.1-0.20200424145508-7e176fda06cc // indirect 77 | github.com/davecgh/go-spew v1.1.1 // indirect 78 | github.com/emicklei/go-restful v2.9.5+incompatible // indirect 79 | github.com/emicklei/go-restful/v3 v3.10.2 // indirect 80 | github.com/evanphx/json-patch v4.11.0+incompatible // indirect 81 | github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect 82 | github.com/fsnotify/fsnotify v1.4.9 // indirect 83 | github.com/go-logr/logr v0.4.0 // indirect 84 | github.com/go-logr/zapr v0.4.0 // indirect 85 | github.com/go-openapi/jsonpointer v0.19.3 // indirect 86 | github.com/go-openapi/jsonreference v0.19.3 // indirect 87 | github.com/go-openapi/swag v0.19.9 // indirect 88 | github.com/gogo/protobuf v1.3.2 // indirect 89 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 90 | github.com/golang/protobuf v1.5.2 // indirect 91 | github.com/google/go-cmp v0.5.5 // indirect 92 | github.com/google/gofuzz v1.1.0 // indirect 93 | github.com/google/uuid v1.1.2 // indirect 94 | github.com/googleapis/gnostic v0.5.5 // indirect 95 | github.com/imdario/mergo v0.3.12 // indirect 96 | github.com/json-iterator/go v1.1.11 // indirect 97 | github.com/mailru/easyjson v0.7.1 // indirect 98 | github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect 99 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 100 | github.com/modern-go/reflect2 v1.0.1 // indirect 101 | github.com/pkg/errors v0.9.1 // indirect 102 | github.com/prometheus/client_golang v1.11.0 // indirect 103 | github.com/prometheus/client_model v0.2.0 // indirect 104 | github.com/prometheus/common v0.26.0 // indirect 105 | github.com/prometheus/procfs v0.6.0 // indirect 106 | go.uber.org/atomic v1.7.0 // indirect 107 | go.uber.org/multierr v1.6.0 // indirect 108 | go.uber.org/zap v1.19.0 // indirect 109 | golang.org/x/crypto v0.21.0 // indirect 110 | golang.org/x/net v0.10.0 // indirect 111 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect 112 | golang.org/x/sys v0.18.0 // indirect 113 | golang.org/x/term v0.18.0 // indirect 114 | golang.org/x/text v0.14.0 // indirect 115 | golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect 116 | gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect 117 | google.golang.org/appengine v1.6.7 // indirect 118 | google.golang.org/protobuf v1.26.0 // indirect 119 | gopkg.in/inf.v0 v0.9.1 // indirect 120 | gopkg.in/yaml.v2 v2.4.0 // indirect 121 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 122 | k8s.io/apiextensions-apiserver v0.22.1 // indirect 123 | k8s.io/component-base v0.22.1 // indirect 124 | k8s.io/klog v1.0.0 // indirect 125 | k8s.io/klog/v2 v2.9.0 // indirect 126 | k8s.io/kube-state-metrics v1.7.2 // indirect 127 | k8s.io/utils v0.0.0-20210802155522-efc7438f0176 // indirect 128 | sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect 129 | ) 130 | 131 | replace github.com/emicklei/go-restful => github.com/emicklei/go-restful/v3 v3.10.0 132 | 133 | replace github.com/coreos/prometheus-operator => github.com/coreos/prometheus-operator v0.41.1 134 | 135 | replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.0-20220521103104-8f96da9f5d5e 136 | 137 | replace google.golang.org/protobuf => google.golang.org/protobuf v1.33.0 138 | -------------------------------------------------------------------------------- /pkg/controller/model/volume_source.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020-2021 IBM Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | package model 17 | 18 | import ( 19 | "bytes" 20 | "text/template" 21 | 22 | corev1 "k8s.io/api/core/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | "sigs.k8s.io/controller-runtime/pkg/client" 25 | 26 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/apis/operator/v1alpha1" 27 | tpls "github.com/IBM/ibm-monitoring-grafana-operator/pkg/controller/artifacts" 28 | "github.com/IBM/ibm-monitoring-grafana-operator/pkg/controller/dashboards" 29 | ) 30 | 31 | // These vars are used to recontile all the configmaps. 32 | var ( 33 | environment string = "openshift" 34 | //configmap names 35 | grafanaLua string = "grafana-lua-script-config" 36 | utilLua string = "grafana-util-lua-script-config" 37 | grafanaDBConfig string = "grafana-dashboard-config" 38 | routerConfig string = "grafana-router-config" 39 | routerEntry string = "grafana-router-entry" 40 | grafanaDefaultDashboard string = "grafana-default-dashboards" 41 | grafanaCRD string = "grafana-crd-entry" 42 | dsConfig string = "grafana-ds-entry-config" 43 | grafanaConfig string = "grafana-config" 44 | grafanaCredentialStr string = "YWRtaW46YWRtaW4=" 45 | ) 46 | 47 | type fileKeys map[string]map[string]*template.Template 48 | 49 | // To store all the tempate data. 50 | type templateData struct { 51 | Namespace string 52 | Environment string 53 | ClusterDomain string 54 | GrafanaFullName string 55 | PrometheusFullName string 56 | GrafanaCredential string 57 | ClusterPort int32 58 | PrometheusPort int32 59 | GrafanaPort int32 60 | } 61 | 62 | // FileKeys stores the configmap name and file key 63 | var FileKeys fileKeys 64 | 65 | func init() { 66 | FileKeys = make(fileKeys) 67 | FileKeys[grafanaLua] = map[string]*template.Template{"grafana.lua": tpls.GrafanaLuaScript} 68 | FileKeys[utilLua] = map[string]*template.Template{"monitoring-util.lua": tpls.UtilLuaScript} 69 | FileKeys[routerConfig] = map[string]*template.Template{"nginx.conf.monitoring": tpls.RouterConfig} 70 | FileKeys[routerEntry] = map[string]*template.Template{"entrypoint.sh": tpls.RouterEntry} 71 | FileKeys[grafanaCRD] = map[string]*template.Template{"run.sh": tpls.GrafanaCRDEntry} 72 | FileKeys[dsConfig] = map[string]*template.Template{"entrypoint.sh": tpls.Entrypoint} 73 | FileKeys[grafanaConfig] = map[string]*template.Template{"grafana.ini": tpls.GrafanaConfig} 74 | FileKeys[grafanaDBConfig] = map[string]*template.Template{"dashboards.yaml": tpls.GrafanaDBConfig} 75 | } 76 | 77 | func createConfigmap(namespace, name string, data map[string]string) *corev1.ConfigMap { 78 | labels := map[string]string{"app": "grafana"} 79 | labels = appendCommonLabels(labels) 80 | 81 | configmap := corev1.ConfigMap{ 82 | ObjectMeta: metav1.ObjectMeta{ 83 | Name: name, 84 | Namespace: namespace, 85 | Labels: labels, 86 | }, 87 | Data: data, 88 | } 89 | return &configmap 90 | } 91 | 92 | func createDefaultDashboard(namespace string) *corev1.ConfigMap { 93 | configData := map[string]string{} 94 | 95 | for file, data := range dashboards.DefaultDashboards { 96 | configData[file] = data 97 | } 98 | 99 | labels := map[string]string{"app": "ibm-monitoring-grafana", "component": "grafana"} 100 | labels = appendCommonLabels(labels) 101 | return &corev1.ConfigMap{ 102 | ObjectMeta: metav1.ObjectMeta{ 103 | Name: grafanaDefaultDashboard, 104 | Namespace: namespace, 105 | Labels: labels, 106 | }, 107 | Data: configData, 108 | } 109 | } 110 | 111 | // ReconcileConfigMaps will reconcile all the confimaps for the grafana. 112 | // There is not selector to retrieve all the configmaps. Just update them 113 | // with a switch of IsConfigMapsDone variable. 114 | func ReconcileConfigMaps(cr *v1alpha1.Grafana) []*corev1.ConfigMap { 115 | configmaps := []*corev1.ConfigMap{} 116 | namespace := cr.Namespace 117 | var prometheusPort, httpPort int32 118 | var prometheusFullName string 119 | 120 | if cr.Spec.ClusterPort != 0 { 121 | httpPort = cr.Spec.ClusterPort 122 | } else { 123 | httpPort = DefaultClusterPort 124 | } 125 | prometheusFullName, prometheusPort = prometheusInfo(cr) 126 | grafanaPort := DefaultGrafanaPort 127 | grafanaFullName := GrafanaServiceName 128 | 129 | tplData := templateData{ 130 | Namespace: namespace, 131 | ClusterPort: httpPort, 132 | Environment: environment, 133 | ClusterDomain: ClusterDomain, 134 | PrometheusFullName: prometheusFullName, 135 | PrometheusPort: prometheusPort, 136 | GrafanaFullName: grafanaFullName, 137 | GrafanaPort: grafanaPort, 138 | GrafanaCredential: grafanaCredentialStr, 139 | } 140 | 141 | for file, dValue := range FileKeys { 142 | data := map[string]string{} 143 | var buff bytes.Buffer 144 | for name, tpl := range dValue { 145 | err := tpl.Execute(&buff, tplData) 146 | if err != nil { 147 | panic(err) 148 | } 149 | data[name] = buff.String() 150 | } 151 | configmaps = append(configmaps, createConfigmap(cr.Namespace, file, data)) 152 | } 153 | 154 | configmaps = append(configmaps, createDefaultDashboard(cr.Namespace)) 155 | return configmaps 156 | } 157 | 158 | // CreateGrafanaSecret create a secret from the user/passwd from config file 159 | func CreateGrafanaSecret(cr *v1alpha1.Grafana) *corev1.Secret { 160 | 161 | var password, user string = "admin", "admin" 162 | data := map[string][]byte{"username": []byte(user), "password": []byte(password)} 163 | 164 | labels := map[string]string{"app": "grafana", "component": "grafana"} 165 | labels = appendCommonLabels(labels) 166 | return &corev1.Secret{ 167 | ObjectMeta: metav1.ObjectMeta{ 168 | Name: GrafanaAdminSecretName, 169 | Namespace: cr.Namespace, 170 | Labels: labels, 171 | }, 172 | Type: "Opaque", 173 | Data: data, 174 | } 175 | } 176 | 177 | // GrafanaSecretSelector to retrieve the secret 178 | func GrafanaSecretSelector(cr *v1alpha1.Grafana) client.ObjectKey { 179 | return client.ObjectKey{ 180 | Name: GrafanaAdminSecretName, 181 | Namespace: cr.Namespace, 182 | } 183 | } 184 | --------------------------------------------------------------------------------