visualization operator: Add datasource 37/94237/6
authorSrivahni <srivahni.chivukula@intel.com>
Fri, 23 Aug 2019 18:19:26 +0000 (11:19 -0700)
committerMarco Platania <platania@research.att.com>
Fri, 6 Sep 2019 12:44:13 +0000 (12:44 +0000)
Added support to create a grafana datasource dynamically
using GrafanaDataSource CR.

Issue-ID: ONAPARC-393
Signed-off-by: Srivahni <srivahni.chivukula@intel.com>
Change-Id: Iaa645c5c4f303afbcec114c00e35cd6e6ae6c98c

19 files changed:
vnfs/DAaaS/README.md
vnfs/DAaaS/deploy/visualization/charts/grafana/values.yaml
vnfs/DAaaS/microservices/visualization-operator/Makefile [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/deploy/crds/onap_v1alpha1_grafanadatasource_crd.yaml [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/deploy/operator.yaml
vnfs/DAaaS/microservices/visualization-operator/deploy/role.yaml
vnfs/DAaaS/microservices/visualization-operator/examples/grafana/influxdb_grafanadatasource_cr.yaml [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/examples/grafana/prometheus_grafanadatasource_cr.yaml [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/go.mod
vnfs/DAaaS/microservices/visualization-operator/go.sum
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/addtoscheme_onap_v1alpha1.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/group.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/doc.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/grafanadatasource_types.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/register.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/zz_generated.deepcopy.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/zz_generated.openapi.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/controller/add_grafanadatasource.go [new file with mode: 0644]
vnfs/DAaaS/microservices/visualization-operator/pkg/controller/grafanadatasource/grafanadatasource_controller.go [new file with mode: 0644]

index a9c9932..80f0d86 100644 (file)
@@ -90,6 +90,15 @@ cd $DA_WORKING_DIR/../microservices/collectd-operator
 IMAGE_NAME=dcr.cluster.local:32644/collectd-operator:latest
 ./build/build_image.sh $IMAGE_NAME
 ```
+#### visualization-operator
+```bash
+cd $DA_WORKING_DIR/../microservices/visualization-operator
+
+## Note: The image tag and respository in the Visualization-operator helm charts needs to match the IMAGE_NAME
+IMAGE_NAME=dcr.cluster.local:32644/visualization-operator:latest
+./build/build_image.sh $IMAGE_NAME
+```
+
 ### Install the Operator Package
 ```bash
 cd $DA_WORKING_DIR/operator
@@ -183,6 +192,12 @@ kubectl create -f edge1 [PLUGIN_NAME2]_collectdplugin_cr.yaml
 kubectl create -f edge1 [PLUGIN_NAME3]_collectdplugin_cr.yaml
 ...
 ```
+#### Configure Grafana Datasources
+Using the sample [prometheus_grafanadatasource_cr.yaml](microservices/visualization-operator/examples/grafana/prometheus_grafanadatasource_cr.yaml), Configure the GrafanaDataSource CR by running the command below
+```yaml
+kubectl create -f [DATASOURCE_NAME]_grafanadatasource_cr.yaml
+...
+```
 
 ## Install Minio Model repository
 * Prerequisite: Dynamic storage provisioner needs to be enabled. Either rook-ceph ($DA_WORKING_DIR/00-init) or another alternate provisioner needs to be enabled.
index 582c010..d78af1f 100755 (executable)
@@ -156,7 +156,7 @@ persistence:
 
 # Administrator credentials when not using an existing secret (see below)
 adminUser: admin
-# adminPassword: strongpassword
+adminPassword: admin 
 
 # Use an existing secret for the admin user.
 admin:
diff --git a/vnfs/DAaaS/microservices/visualization-operator/Makefile b/vnfs/DAaaS/microservices/visualization-operator/Makefile
new file mode 100644 (file)
index 0000000..4f4b3e0
--- /dev/null
@@ -0,0 +1,56 @@
+# SPDX-license-identifier: Apache-2.0
+##############################################################################
+# Copyright (c) 2019 Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# Common
+VERSION := $(shell git describe --tags)
+BUILD := $(shell git rev-parse --short HEAD)
+PROJECTNAME := $(shell basename "$(pwd)")
+
+ROOTPATH := $(shell realpath "$(PWD)/../../../../../../")
+VOP := ${PWD}/build/_output/bin/visualization-operator
+VOP_LOCAL := ${VOP}-local
+IMAGE_NAME := dcr.cluster.local:32644/visualization-operator:latest
+
+export GO111MODULE=on
+
+.PHONY: clean publish
+
+## build: Generate the k8s and openapi artifacts using operator-sdk
+build: clean 
+       GOOS=linux GOARCH=amd64
+       operator-sdk generate k8s --verbose
+       operator-sdk generate openapi --verbose 
+       @operator-sdk build ${IMAGE_NAME} --verbose
+       @go build -o ${VOP_LOCAL} visualization-operator/cmd/manager
+      
+## clean: clean build artifacts, image, binary
+clean:
+       @echo "Deleting the Visualization-operator binary"
+       @rm -rf ${VOP}
+       @rm -rf ${VOP_LOCAL}
+       @if docker images $(IMAGE_NAME) | awk '{ print $$2 }' | grep -q -F latest; then echo "Deleting the visualization-operator docker image";  docker rmi ${IMAGE_NAME}; fi
+
+## publish: Push docker image to registry
+publish:
+       @docker push ${IMAGE_NAME}
+
+## format: format source code
+format:
+       @go fmt ./...
+
+.PHONY: help
+## help: Print help message
+help: Makefile
+       @echo
+       @echo " Requires Operator SDK v0.8.0+, go1.12.5+"
+       @echo
+       @echo " Choose a command run in "$(PROJECTNAME)":"
+       @echo
+       @sed -n 's/^## //p' $< | column -t -s ':' |  sed -e 's/^/ /'
+       @echo
diff --git a/vnfs/DAaaS/microservices/visualization-operator/deploy/crds/onap_v1alpha1_grafanadatasource_crd.yaml b/vnfs/DAaaS/microservices/visualization-operator/deploy/crds/onap_v1alpha1_grafanadatasource_crd.yaml
new file mode 100644 (file)
index 0000000..39b78d9
--- /dev/null
@@ -0,0 +1,90 @@
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: grafanadatasources.onap.org
+spec:
+  group: onap.org
+  names:
+    kind: GrafanaDataSource
+    listKind: GrafanaDataSourceList
+    plural: grafanadatasources
+    singular: grafanadatasource
+  scope: Namespaced
+  subresources:
+    status: {}
+  validation:
+    openAPIV3Schema:
+      properties:
+        apiVersion:
+          description: 'APIVersion defines the versioned schema of this representation
+            of an object. Servers should convert recognized schemas to the latest
+            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources'
+          type: string
+        kind:
+          description: 'Kind is a string value representing the REST resource this
+            object represents. Servers may infer this from the endpoint the client
+            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
+          type: string
+        metadata:
+          type: object
+        spec:
+          properties:
+            datasources:
+              description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
+                Important: Run "operator-sdk generate k8s" to regenerate code after
+                modifying this file Add custom validation using kubebuilder tags:
+                https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html'
+              items:
+                properties:
+                  access:
+                    type: string
+                  basicAuth:
+                    type: boolean
+                  basicAuthPassword:
+                    type: string
+                  basicAuthUser:
+                    type: string
+                  database:
+                    type: string
+                  isDefault:
+                    type: boolean
+                  jsonData:
+                    additionalProperties:
+                      type: string
+                    type: object
+                  name:
+                    type: string
+                  password:
+                    type: string
+                  readOnly:
+                    type: boolean
+                  type:
+                    type: string
+                  url:
+                    type: string
+                  user:
+                    type: string
+                  withCredentials:
+                    type: boolean
+                required:
+                - name
+                - type
+                - url
+                - access
+                type: object
+              type: array
+            grafana:
+              additionalProperties:
+                type: string
+              type: object
+          required:
+          - datasources
+          - grafana
+          type: object
+        status:
+          type: object
+  version: v1alpha1
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
index 6c37f31..b508b1c 100644 (file)
@@ -16,15 +16,13 @@ spec:
       containers:
         - name: visualization-operator
           # Replace this with the built image name
-          image: REPLACE_IMAGE
+          image: dcr.cluster.local:32644/visualization-operator:latest
           command:
           - visualization-operator
           imagePullPolicy: Always
           env:
             - name: WATCH_NAMESPACE
-              valueFrom:
-                fieldRef:
-                  fieldPath: metadata.namespace
+              value: ""
             - name: POD_NAME
               valueFrom:
                 fieldRef:
index a140ca2..f7e1ad1 100644 (file)
@@ -1,6 +1,7 @@
-kind: Role
 apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
 metadata:
+  creationTimestamp: null
   name: visualization-operator
 rules:
 - apiGroups:
@@ -14,7 +15,7 @@ rules:
   - configmaps
   - secrets
   verbs:
-  - "*"
+  - '*'
 - apiGroups:
   - apps
   resources:
@@ -23,22 +24,22 @@ rules:
   - replicasets
   - statefulsets
   verbs:
-  - "*"
+  - '*'
 - apiGroups:
   - monitoring.coreos.com
   resources:
   - servicemonitors
   verbs:
-  - "get"
-  - "create"
+  - get
+  - create
 - apiGroups:
   - apps
-  resources:
-  - deployments/finalizers
   resourceNames:
   - visualization-operator
+  resources:
+  - deployments/finalizers
   verbs:
-  - "update"
+  - update
 - apiGroups:
   - ""
   resources:
@@ -51,3 +52,9 @@ rules:
   - replicasets
   verbs:
   - get
+- apiGroups:
+  - onap.org
+  resources:
+  - '*'
+  verbs:
+  - '*'
diff --git a/vnfs/DAaaS/microservices/visualization-operator/examples/grafana/influxdb_grafanadatasource_cr.yaml b/vnfs/DAaaS/microservices/visualization-operator/examples/grafana/influxdb_grafanadatasource_cr.yaml
new file mode 100644 (file)
index 0000000..5d9753e
--- /dev/null
@@ -0,0 +1,24 @@
+apiVersion: onap.org/v1alpha1
+kind: GrafanaDataSource
+metadata:
+  name: influxdb
+spec:
+  datasources:
+    - name: InfluxDB
+      type: influxdb
+      url: http://localhost:8086 
+      isDefault: false
+      access: proxy
+      withCredentials: true
+      basicAuth: true
+      basicAuthUser: user
+      basicAuthPassword: password
+      database: collectd
+      user: user
+      password: password
+      jsonData:
+        timeInterval: 15s
+  grafana:
+    url:  http://vis-grafana.default.svc.cluster.local
+    username: admin
+    password: admin
diff --git a/vnfs/DAaaS/microservices/visualization-operator/examples/grafana/prometheus_grafanadatasource_cr.yaml b/vnfs/DAaaS/microservices/visualization-operator/examples/grafana/prometheus_grafanadatasource_cr.yaml
new file mode 100644 (file)
index 0000000..b808636
--- /dev/null
@@ -0,0 +1,23 @@
+apiVersion: onap.org/v1alpha1
+kind: GrafanaDataSource
+metadata:
+  name: prometheus
+spec:
+  datasources:
+    - name: Prometheus
+      type: prometheus
+      url: http://cp-prometheus-prometheus:9090
+      isDefault: true
+      access: proxy
+      withCredentials: true
+      basicAuth: true
+      basicAuthUser: user
+      basicAuthPassword: password
+      jsonData:
+        timeInterval: 10s
+        queryTimeout: 50s
+      readOnly: false
+  grafana:
+    url:  http://vis-grafana.default.svc.cluster.local
+    username: admin
+    password: admin
index 0381329..af334b0 100644 (file)
@@ -4,6 +4,12 @@ require (
        github.com/NYTimes/gziphandler v1.0.1 // indirect
        github.com/operator-framework/operator-sdk v0.9.1-0.20190805223000-66e78cc576ef
        github.com/spf13/pflag v1.0.3
+       golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
+       golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect
+       golang.org/x/net v0.0.0-20190724013045-ca1201d0de80
+       golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect
+       golang.org/x/text v0.3.2 // indirect
+       golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de // indirect
        k8s.io/api v0.0.0-20190612125737-db0771252981
        k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad
        k8s.io/client-go v11.0.0+incompatible
index 547073e..e0690dd 100644 (file)
@@ -91,6 +91,7 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@@ -198,6 +199,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
 github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
@@ -253,9 +255,11 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.4.2-0.20180831124310-ae19f1b56d53/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 github.com/openshift/origin v0.0.0-20160503220234-8f127d736703/go.mod h1:0Rox5r9C8aQn6j1oAOQ0c1uC86mYbUFObzjBRvUKHII=
@@ -282,6 +286,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -334,6 +339,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
 github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245/go.mod h1:O1c8HleITsZqzNZDjSNzirUGsMT0oGu9LhHKoJrqO+A=
@@ -369,12 +375,16 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE=
 golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -394,6 +404,9 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20170412232759-a6bd8cefa181/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -408,6 +421,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -424,10 +439,15 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
 golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M=
+golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -435,6 +455,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZe
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181011152555-a398e557df60/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181207222222-4c874b978acb/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -442,8 +463,12 @@ golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190213015956-f7e1b50d2251/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190408170212-12dd9f86f350/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de h1:VNumCimp/Bwk6fRqgPHkjiUPZ/vzlpi23/kQTuQ4gBA=
+golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
@@ -473,6 +498,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
@@ -481,6 +507,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0
 gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/square/go-jose.v2 v2.3.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -494,6 +521,7 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 k8s.io/api v0.0.0-20190222213804-5cb15d344471 h1:MzQGt8qWQCR+39kbYRd0uQqsvSidpYqJLFeWiJ9l4OE=
 k8s.io/api v0.0.0-20190222213804-5cb15d344471/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
+k8s.io/apiextensions-apiserver v0.0.0-20190228180357-d002e88f6236 h1:JfFtjaElBIgYKCWEtYQkcNrTpW+lMO4GJy8NP6SVQmM=
 k8s.io/apiextensions-apiserver v0.0.0-20190228180357-d002e88f6236/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
 k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628 h1:UYfHH+KEF88OTg+GojQUwFTNxbxwmoktLwutUzR0GPg=
 k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
@@ -529,6 +557,7 @@ sigs.k8s.io/controller-runtime v0.1.12/go.mod h1:HFAYoOh6XMV+jKF1UjFwrknPbowfyHE
 sigs.k8s.io/controller-tools v0.1.11-0.20190411181648-9d55346c2bde/go.mod h1:ATWLRP3WGxuAN9HcT2LaKHReXIH+EZGzRuMHuxjXfhQ=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
 sigs.k8s.io/testing_frameworks v0.1.0/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
+sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs=
 sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
 sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/addtoscheme_onap_v1alpha1.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/addtoscheme_onap_v1alpha1.go
new file mode 100644 (file)
index 0000000..57e6df9
--- /dev/null
@@ -0,0 +1,10 @@
+package apis
+
+import (
+       "visualization-operator/pkg/apis/onap/v1alpha1"
+)
+
+func init() {
+       // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
+       AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme)
+}
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/group.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/group.go
new file mode 100644 (file)
index 0000000..d35634c
--- /dev/null
@@ -0,0 +1,6 @@
+// Package onap contains onap API versions.
+//
+// This file ensures Go source parsers acknowledge the onap package
+// and any child packages. It can be removed if any other Go source files are
+// added to this package.
+package onap
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/doc.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/doc.go
new file mode 100644 (file)
index 0000000..29b3493
--- /dev/null
@@ -0,0 +1,4 @@
+// Package v1alpha1 contains API Schema definitions for the onap v1alpha1 API group
+// +k8s:deepcopy-gen=package,register
+// +groupName=onap.org
+package v1alpha1
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/grafanadatasource_types.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/grafanadatasource_types.go
new file mode 100644 (file)
index 0000000..6082006
--- /dev/null
@@ -0,0 +1,68 @@
+package v1alpha1
+
+import (
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
+// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
+
+// GrafanaDataSourceSpec defines the desired state of GrafanaDataSource
+// +k8s:openapi-gen=true
+type GrafanaDataSourceSpec struct {
+       // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
+       // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
+       // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
+       Datasources []Datasource      `json:"datasources"`
+       Grafana     map[string]string `json:"grafana"`
+}
+
+// GrafanaDataSourceStatus defines the observed state of GrafanaDataSource
+// +k8s:openapi-gen=true
+type GrafanaDataSourceStatus struct {
+}
+
+// Datasource defines the fields in a GrafanaDataSource
+// +k8s:openapi-gen=true
+type Datasource struct {
+       Name              string            `json:"name"`
+       Type              string            `json:"type"`
+       URL               string            `json:"url"`
+       IsDefault         bool              `json:"isDefault,omitempty"`
+       Access            string            `json:"access"`
+       WithCredentials   bool              `json:"withCredentials,omitempty"`
+       BasicAuth         bool              `json:"basicAuth,omitempty"`
+       BasicAuthUser     string            `json:"basicAuthUser,omitempty"`
+       BasicAuthPassword string            `json:"basicAuthPassword,omitempty"`
+       JsonData          map[string]string `json:"jsonData,omitempty"`
+       Database          string            `json:"database,omitempty"`
+       User              string            `json:"user,omitempty"`
+       Password          string            `json:"password,omitempty"`
+       ReadOnly          bool              `json:"readOnly,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// GrafanaDataSource is the Schema for the grafanadatasources API
+// +k8s:openapi-gen=true
+// +kubebuilder:subresource:status
+type GrafanaDataSource struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec   GrafanaDataSourceSpec   `json:"spec,omitempty"`
+       Status GrafanaDataSourceStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// GrafanaDataSourceList contains a list of GrafanaDataSource
+type GrafanaDataSourceList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+       Items           []GrafanaDataSource `json:"items"`
+}
+
+func init() {
+       SchemeBuilder.Register(&GrafanaDataSource{}, &GrafanaDataSourceList{})
+}
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/register.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/register.go
new file mode 100644 (file)
index 0000000..c670eea
--- /dev/null
@@ -0,0 +1,19 @@
+// NOTE: Boilerplate only.  Ignore this file.
+
+// Package v1alpha1 contains API Schema definitions for the onap v1alpha1 API group
+// +k8s:deepcopy-gen=package,register
+// +groupName=onap.org
+package v1alpha1
+
+import (
+       "k8s.io/apimachinery/pkg/runtime/schema"
+       "sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
+)
+
+var (
+       // SchemeGroupVersion is group version used to register these objects
+       SchemeGroupVersion = schema.GroupVersion{Group: "onap.org", Version: "v1alpha1"}
+
+       // SchemeBuilder is used to add go types to the GroupVersionKind scheme
+       SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
+)
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/zz_generated.deepcopy.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/zz_generated.deepcopy.go
new file mode 100644 (file)
index 0000000..2cc830b
--- /dev/null
@@ -0,0 +1,139 @@
+// +build !ignore_autogenerated
+
+// Code generated by operator-sdk. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+       runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Datasource) DeepCopyInto(out *Datasource) {
+       *out = *in
+       if in.JsonData != nil {
+               in, out := &in.JsonData, &out.JsonData
+               *out = make(map[string]string, len(*in))
+               for key, val := range *in {
+                       (*out)[key] = val
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Datasource.
+func (in *Datasource) DeepCopy() *Datasource {
+       if in == nil {
+               return nil
+       }
+       out := new(Datasource)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GrafanaDataSource) DeepCopyInto(out *GrafanaDataSource) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       in.Spec.DeepCopyInto(&out.Spec)
+       out.Status = in.Status
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSource.
+func (in *GrafanaDataSource) DeepCopy() *GrafanaDataSource {
+       if in == nil {
+               return nil
+       }
+       out := new(GrafanaDataSource)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *GrafanaDataSource) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GrafanaDataSourceList) DeepCopyInto(out *GrafanaDataSourceList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       out.ListMeta = in.ListMeta
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]GrafanaDataSource, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceList.
+func (in *GrafanaDataSourceList) DeepCopy() *GrafanaDataSourceList {
+       if in == nil {
+               return nil
+       }
+       out := new(GrafanaDataSourceList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *GrafanaDataSourceList) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GrafanaDataSourceSpec) DeepCopyInto(out *GrafanaDataSourceSpec) {
+       *out = *in
+       if in.Datasources != nil {
+               in, out := &in.Datasources, &out.Datasources
+               *out = make([]Datasource, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+       if in.Grafana != nil {
+               in, out := &in.Grafana, &out.Grafana
+               *out = make(map[string]string, len(*in))
+               for key, val := range *in {
+                       (*out)[key] = val
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceSpec.
+func (in *GrafanaDataSourceSpec) DeepCopy() *GrafanaDataSourceSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(GrafanaDataSourceSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GrafanaDataSourceStatus) DeepCopyInto(out *GrafanaDataSourceStatus) {
+       *out = *in
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceStatus.
+func (in *GrafanaDataSourceStatus) DeepCopy() *GrafanaDataSourceStatus {
+       if in == nil {
+               return nil
+       }
+       out := new(GrafanaDataSourceStatus)
+       in.DeepCopyInto(out)
+       return out
+}
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/zz_generated.openapi.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/apis/onap/v1alpha1/zz_generated.openapi.go
new file mode 100644 (file)
index 0000000..7f74f2f
--- /dev/null
@@ -0,0 +1,220 @@
+// +build !
+
+// This file was autogenerated by openapi-gen. Do not edit it manually!
+
+package v1alpha1
+
+import (
+       spec "github.com/go-openapi/spec"
+       common "k8s.io/kube-openapi/pkg/common"
+)
+
+func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
+       return map[string]common.OpenAPIDefinition{
+               "./pkg/apis/onap/v1alpha1.Datasource":              schema_pkg_apis_onap_v1alpha1_Datasource(ref),
+               "./pkg/apis/onap/v1alpha1.GrafanaDataSource":       schema_pkg_apis_onap_v1alpha1_GrafanaDataSource(ref),
+               "./pkg/apis/onap/v1alpha1.GrafanaDataSourceSpec":   schema_pkg_apis_onap_v1alpha1_GrafanaDataSourceSpec(ref),
+               "./pkg/apis/onap/v1alpha1.GrafanaDataSourceStatus": schema_pkg_apis_onap_v1alpha1_GrafanaDataSourceStatus(ref),
+       }
+}
+
+func schema_pkg_apis_onap_v1alpha1_Datasource(ref common.ReferenceCallback) common.OpenAPIDefinition {
+       return common.OpenAPIDefinition{
+               Schema: spec.Schema{
+                       SchemaProps: spec.SchemaProps{
+                               Description: "Datasource defines the fields in a GrafanaDataSource",
+                               Properties: map[string]spec.Schema{
+                                       "name": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "type": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "url": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "isDefault": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"boolean"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "access": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "withCredentials": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"boolean"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "basicAuth": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"boolean"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "basicAuthUser": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "basicAuthPassword": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "jsonData": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type: []string{"object"},
+                                                       AdditionalProperties: &spec.SchemaOrBool{
+                                                               Schema: &spec.Schema{
+                                                                       SchemaProps: spec.SchemaProps{
+                                                                               Type:   []string{"string"},
+                                                                               Format: "",
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                                       "database": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "user": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "password": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"string"},
+                                                       Format: "",
+                                               },
+                                       },
+                                       "readOnly": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type:   []string{"boolean"},
+                                                       Format: "",
+                                               },
+                                       },
+                               },
+                               Required: []string{"name", "type", "url", "access"},
+                       },
+               },
+               Dependencies: []string{},
+       }
+}
+
+func schema_pkg_apis_onap_v1alpha1_GrafanaDataSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
+       return common.OpenAPIDefinition{
+               Schema: spec.Schema{
+                       SchemaProps: spec.SchemaProps{
+                               Description: "GrafanaDataSource is the Schema for the grafanadatasources API",
+                               Properties: map[string]spec.Schema{
+                                       "kind": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
+                                                       Type:        []string{"string"},
+                                                       Format:      "",
+                                               },
+                                       },
+                                       "apiVersion": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
+                                                       Type:        []string{"string"},
+                                                       Format:      "",
+                                               },
+                                       },
+                                       "metadata": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+                                               },
+                                       },
+                                       "spec": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Ref: ref("./pkg/apis/onap/v1alpha1.GrafanaDataSourceSpec"),
+                                               },
+                                       },
+                                       "status": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Ref: ref("./pkg/apis/onap/v1alpha1.GrafanaDataSourceStatus"),
+                                               },
+                                       },
+                               },
+                       },
+               },
+               Dependencies: []string{
+                       "./pkg/apis/onap/v1alpha1.GrafanaDataSourceSpec", "./pkg/apis/onap/v1alpha1.GrafanaDataSourceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+       }
+}
+
+func schema_pkg_apis_onap_v1alpha1_GrafanaDataSourceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+       return common.OpenAPIDefinition{
+               Schema: spec.Schema{
+                       SchemaProps: spec.SchemaProps{
+                               Description: "GrafanaDataSourceSpec defines the desired state of GrafanaDataSource",
+                               Properties: map[string]spec.Schema{
+                                       "datasources": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Description: "INSERT ADDITIONAL SPEC FIELDS - desired state of cluster Important: Run \"operator-sdk generate k8s\" to regenerate code after modifying this file Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html",
+                                                       Type:        []string{"array"},
+                                                       Items: &spec.SchemaOrArray{
+                                                               Schema: &spec.Schema{
+                                                                       SchemaProps: spec.SchemaProps{
+                                                                               Ref: ref("./pkg/apis/onap/v1alpha1.Datasource"),
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                                       "grafana": {
+                                               SchemaProps: spec.SchemaProps{
+                                                       Type: []string{"object"},
+                                                       AdditionalProperties: &spec.SchemaOrBool{
+                                                               Schema: &spec.Schema{
+                                                                       SchemaProps: spec.SchemaProps{
+                                                                               Type:   []string{"string"},
+                                                                               Format: "",
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                               Required: []string{"datasources", "grafana"},
+                       },
+               },
+               Dependencies: []string{
+                       "./pkg/apis/onap/v1alpha1.Datasource"},
+       }
+}
+
+func schema_pkg_apis_onap_v1alpha1_GrafanaDataSourceStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+       return common.OpenAPIDefinition{
+               Schema: spec.Schema{
+                       SchemaProps: spec.SchemaProps{
+                               Description: "GrafanaDataSourceStatus defines the observed state of GrafanaDataSource",
+                               Properties:  map[string]spec.Schema{},
+                       },
+               },
+               Dependencies: []string{},
+       }
+}
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/controller/add_grafanadatasource.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/controller/add_grafanadatasource.go
new file mode 100644 (file)
index 0000000..350b8a0
--- /dev/null
@@ -0,0 +1,10 @@
+package controller
+
+import (
+       "visualization-operator/pkg/controller/grafanadatasource"
+)
+
+func init() {
+       // AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
+       AddToManagerFuncs = append(AddToManagerFuncs, grafanadatasource.Add)
+}
diff --git a/vnfs/DAaaS/microservices/visualization-operator/pkg/controller/grafanadatasource/grafanadatasource_controller.go b/vnfs/DAaaS/microservices/visualization-operator/pkg/controller/grafanadatasource/grafanadatasource_controller.go
new file mode 100644 (file)
index 0000000..f46cf1b
--- /dev/null
@@ -0,0 +1,167 @@
+package grafanadatasource
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+
+       onapv1alpha1 "visualization-operator/pkg/apis/onap/v1alpha1"
+
+       "k8s.io/apimachinery/pkg/api/errors"
+       "k8s.io/apimachinery/pkg/runtime"
+       "net/http"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+       "sigs.k8s.io/controller-runtime/pkg/controller"
+       "sigs.k8s.io/controller-runtime/pkg/handler"
+       "sigs.k8s.io/controller-runtime/pkg/manager"
+       "sigs.k8s.io/controller-runtime/pkg/reconcile"
+       logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
+       "sigs.k8s.io/controller-runtime/pkg/source"
+)
+
+var log = logf.Log.WithName("controller_grafanadatasource")
+
+// Add creates a new GrafanaDataSource Controller and adds it to the Manager. The Manager will set fields on the Controller
+// and Start it when the Manager is Started.
+func Add(mgr manager.Manager) error {
+       return add(mgr, newReconciler(mgr))
+}
+
+// newReconciler returns a new reconcile.Reconciler
+func newReconciler(mgr manager.Manager) reconcile.Reconciler {
+       return &ReconcileGrafanaDataSource{client: mgr.GetClient(), scheme: mgr.GetScheme()}
+}
+
+// add adds a new Controller to mgr with r as the reconcile.Reconciler
+func add(mgr manager.Manager, r reconcile.Reconciler) error {
+       // Create a new controller
+       c, err := controller.New("grafanadatasource-controller", mgr, controller.Options{Reconciler: r})
+       if err != nil {
+               return err
+       }
+
+       // Watch for changes to primary resource GrafanaDataSource
+       err = c.Watch(&source.Kind{Type: &onapv1alpha1.GrafanaDataSource{}}, &handler.EnqueueRequestForObject{})
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+// blank assignment to verify that ReconcileGrafanaDataSource implements reconcile.Reconciler
+var _ reconcile.Reconciler = &ReconcileGrafanaDataSource{}
+
+// ReconcileGrafanaDataSource reconciles a GrafanaDataSource object
+type ReconcileGrafanaDataSource struct {
+       // This client, initialized using mgr.Client() above, is a split client
+       // that reads objects from the cache and writes to the apiserver
+       client client.Client
+       scheme *runtime.Scheme
+}
+
+// Reconcile reads that state of the cluster for a GrafanaDataSource object and makes changes based on the state read
+// and what is in the GrafanaDataSource.Spec
+// Note:
+// The Controller will requeue the Request to be processed again if the returned error is non-nil or
+// Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
+func (r *ReconcileGrafanaDataSource) Reconcile(request reconcile.Request) (reconcile.Result, error) {
+       reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
+       reqLogger.Info("Reconciling GrafanaDataSource")
+
+       // Fetch the GrafanaDataSource instance
+       instance := &onapv1alpha1.GrafanaDataSource{}
+       err := r.client.Get(context.TODO(), request.NamespacedName, instance)
+       if err != nil {
+               if errors.IsNotFound(err) {
+                       // Request object not found, could have been deleted after reconcile request.
+                       // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
+                       // Return and don't requeue
+                       return reconcile.Result{}, nil
+               }
+               // Error reading the object - requeue the request.
+
+               return reconcile.Result{}, err
+       }
+
+       datasources := instance.Spec.Datasources
+       grafana := instance.Spec.Grafana
+
+       reqLogger.V(1).Info(" Datasource Name ", "datasources", datasources)
+
+       //loop through all datasources in the spec
+       for _, datasource := range datasources {
+
+               //check if datasource exists
+               grafanaURL := grafana["url"] + "/api/datasources/name/" + datasource.Name
+               grafanaUsername := grafana["username"]
+               grafanaPassword := grafana["password"]
+
+               client := &http.Client{}
+               req, err := http.NewRequest("GET", grafanaURL, nil)
+               if err != nil {
+                       reqLogger.Error(err, "GET REQUEST error")
+                       return reconcile.Result{}, err
+               }
+               req.SetBasicAuth(grafanaUsername, grafanaPassword)
+               getResp, err := client.Do(req)
+               if err != nil {
+                       reqLogger.Error(err, "GET RESPONSE error")
+                       return reconcile.Result{}, err
+               }
+
+               defer getResp.Body.Close()
+
+               //add datasource if datasource does not exist already
+               if getResp.StatusCode == http.StatusNotFound {
+                       reqLogger.Info("Datasource does not exist, creating one...")
+                       // create datasource
+                       if err := createDataSource(grafana, datasource); err != nil {
+                               return reconcile.Result{}, err
+                       }
+               } else if getResp.StatusCode == http.StatusOK {
+                       //if datasource already exists
+                       reqLogger.V(1).Info("datasource already exists", "datasource", datasource.Name)
+               } else {
+                       reqLogger.Error(err, "unknown error", datasource.Name)
+               }
+
+       }
+       return reconcile.Result{}, nil
+}
+
+func createDataSource(grafana map[string]string, datasource onapv1alpha1.Datasource) error {
+       reqLogger := log.WithValues("Datasource name", datasource.Name, "Datasource URL", datasource.URL)
+       reqLogger.Info("creating datasource")
+
+       grafanaURL := grafana["url"] + "/api/datasources"
+       grafanaUsername := grafana["username"]
+       grafanaPassword := grafana["password"]
+
+       client := &http.Client{}
+       postBody, err := json.Marshal(datasource)
+       if err != nil {
+               reqLogger.Error(err, "JSON Marshalling error")
+               return err
+       }
+
+       req, err := http.NewRequest("POST", grafanaURL, bytes.NewBuffer(postBody))
+       if err != nil {
+               reqLogger.Error(err, "POST REQUEST error")
+               return err
+       }
+       req.Header.Set("Content-Type", "application/json")
+       req.SetBasicAuth(grafanaUsername, grafanaPassword)
+       postResp, err := client.Do(req)
+       if err != nil {
+               reqLogger.Error(err, "POST RESPONSE error")
+               return err
+       }
+       defer req.Body.Close()
+
+       if postResp.StatusCode == http.StatusOK {
+               reqLogger.Info("Datasource created")
+               return nil
+       }
+       return err
+}