summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--deployments/kubernetes/monitor-deploy.yaml11
-rw-r--r--deployments/kubernetes/onap4k8s.yaml72
-rwxr-xr-xkud/tests/plugin_fw.sh6
-rw-r--r--src/dcm/api/logicalCloudHandler.go18
-rw-r--r--src/dcm/config.json12
-rw-r--r--src/dcm/go.sum1
-rw-r--r--src/dcm/pkg/module/apply.go8
-rw-r--r--src/dcm/pkg/module/logicalcloud.go6
-rw-r--r--src/k8splugin/api/instancehandler_test.go85
-rw-r--r--src/k8splugin/go.mod28
-rw-r--r--src/k8splugin/internal/app/client.go181
-rw-r--r--src/k8splugin/internal/app/instance.go81
-rw-r--r--src/k8splugin/internal/app/instance_test.go122
-rw-r--r--src/k8splugin/internal/plugin/helpers.go4
-rw-r--r--src/monitor/deploy/crds/k8splugin_v1alpha1_resourcebundlestate_crd.yaml5
15 files changed, 305 insertions, 335 deletions
diff --git a/deployments/kubernetes/monitor-deploy.yaml b/deployments/kubernetes/monitor-deploy.yaml
index 29bb1eb6..ef8e5ec3 100644
--- a/deployments/kubernetes/monitor-deploy.yaml
+++ b/deployments/kubernetes/monitor-deploy.yaml
@@ -77,6 +77,10 @@ spec:
items:
type: object
type: array
+ csrStatuses:
+ items:
+ type: object
+ type: array
required:
- ready
- resourceCount
@@ -89,6 +93,7 @@ spec:
- ingressStatuses
- jobStatuses
- statefulSetStatuses
+ - csrStatuses
type: object
version: v1alpha1
versions:
@@ -169,6 +174,12 @@ rules:
- '*'
verbs:
- '*'
+- apiGroups:
+ - certificates.k8s.io
+ resources:
+ - '*'
+ verbs:
+ - '*'
---
apiVersion: rbac.authorization.k8s.io/v1
diff --git a/deployments/kubernetes/onap4k8s.yaml b/deployments/kubernetes/onap4k8s.yaml
index 6e404873..1d0c55f7 100644
--- a/deployments/kubernetes/onap4k8s.yaml
+++ b/deployments/kubernetes/onap4k8s.yaml
@@ -361,3 +361,75 @@ spec:
- key: config.json
path: config.json
+---
+# DCM Config Map
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: dcm
+ labels:
+ app: dcm
+data:
+ config.json: |
+ {
+ "database-type": "mongo",
+ "database-ip": "mongo",
+ "etcd-ip": "etcd",
+ "service-port": "9077"
+ }
+
+---
+# DCM Service
+apiVersion: v1
+kind: Service
+metadata:
+ name: dcm
+ labels:
+ app: dcm
+spec:
+ selector:
+ app: dcm
+ type: NodePort
+ ports:
+ - name: http
+ port: 9077
+ nodePort: 31877
+ protocol: TCP
+ targetPort: 9077
+
+---
+# DCM Deployment
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: dcm
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: dcm
+ template:
+ metadata:
+ labels:
+ app: dcm
+ spec:
+ containers:
+ - name: dcm
+ image: emcov2/emco:stable
+ imagePullPolicy: Always
+ command: ["/opt/emco/entrypoint", "dcm"]
+ workingDir: /opt/emco
+ ports:
+ - containerPort: 9077
+ volumeMounts:
+ - name: config
+ mountPath: /opt/emco/config.json
+ subPath: config.json
+ volumes:
+ - name: config
+ configMap:
+ name: dcm
+ items:
+ - key: config.json
+ path: config.json
+
diff --git a/kud/tests/plugin_fw.sh b/kud/tests/plugin_fw.sh
index 28df372c..a503d661 100755
--- a/kud/tests/plugin_fw.sh
+++ b/kud/tests/plugin_fw.sh
@@ -2,6 +2,7 @@
# SPDX-license-identifier: Apache-2.0
##############################################################################
# Copyright (c) 2018
+# Copyright © 2020 Samsung Electronics
# 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
@@ -116,6 +117,9 @@ print_msg "Not waiting for vFW to fully install as no further checks are impleme
#sleep 8m
print_msg "[END] Basic checks for instantiated resource"
+print_msg "Retrieving VNF status (this will result with long output)"
+call_api "${base_url}/instance/${vnf_id}/status"
+
print_msg "Retrieving VNF details"
response="$(call_api "${base_url}/instance/${vnf_id}")"
echo "$response"
@@ -136,3 +140,5 @@ delete_resource "${base_url}/rb/definition/${rb_name}/${rb_version}"
print_msg "Deleting ${cloud_region_id} cloud region connection"
delete_resource "${base_url}/connectivity-info/${cloud_region_id}"
+
+print_msg "Test finished successfully"
diff --git a/src/dcm/api/logicalCloudHandler.go b/src/dcm/api/logicalCloudHandler.go
index fb0f0c63..b5161efa 100644
--- a/src/dcm/api/logicalCloudHandler.go
+++ b/src/dcm/api/logicalCloudHandler.go
@@ -25,6 +25,7 @@ import (
"github.com/gorilla/mux"
"github.com/onap/multicloud-k8s/src/dcm/pkg/module"
+ orch "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
pkgerrors "github.com/pkg/errors"
)
@@ -59,6 +60,15 @@ func (h logicalCloudHandler) createHandler(w http.ResponseWriter, r *http.Reques
return
}
+ // Validate that the specified Project exists
+ // before associating a Logical Cloud with it
+ p := orch.NewProjectClient()
+ _, err = p.GetProject(project)
+ if err != nil {
+ http.Error(w, "The specified project does not exist.", http.StatusNotFound)
+ return
+ }
+
ret, err := h.client.Create(project, v)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -186,7 +196,7 @@ func (h logicalCloudHandler) applyHandler(w http.ResponseWriter, r *http.Request
return
}
- _, ctxVal, err := h.client.GetLogicalCloudContext(name)
+ _, ctxVal, err := h.client.GetLogicalCloudContext(project, name)
if ctxVal != "" {
err = pkgerrors.New("Logical Cloud already applied")
http.Error(w, err.Error(), http.StatusConflict)
@@ -212,7 +222,7 @@ func (h logicalCloudHandler) applyHandler(w http.ResponseWriter, r *http.Request
return
}
- err = module.CreateEtcdContext(lc, clusters, quotas)
+ err = module.CreateEtcdContext(project, lc, clusters, quotas)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -237,7 +247,7 @@ func (h logicalCloudHandler) terminateHandler(w http.ResponseWriter, r *http.Req
return
}
- _, ctxVal, err := h.client.GetLogicalCloudContext(name)
+ _, ctxVal, err := h.client.GetLogicalCloudContext(project, name)
if ctxVal == "" {
err = pkgerrors.New("Logical Cloud hasn't been applied yet")
http.Error(w, err.Error(), http.StatusConflict)
@@ -259,7 +269,7 @@ func (h logicalCloudHandler) terminateHandler(w http.ResponseWriter, r *http.Req
return
}
- err = module.DestroyEtcdContext(lc, clusters, quotas)
+ err = module.DestroyEtcdContext(project, lc, clusters, quotas)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
diff --git a/src/dcm/config.json b/src/dcm/config.json
index 65a18acb..7e1f579c 100644
--- a/src/dcm/config.json
+++ b/src/dcm/config.json
@@ -1,14 +1,6 @@
{
- "database-ip": "172.18.0.2",
"database-type": "mongo",
- "plugin-dir": "plugins",
- "service-port": "9077",
- "ca-file": "ca.cert",
- "server-cert": "server.cert",
- "server-key": "server.key",
- "password": "",
+ "database-ip": "172.18.0.2",
"etcd-ip": "172.18.0.3",
- "etcd-cert": "",
- "etcd-key": "",
- "etcd-ca-file": ""
+ "service-port": "9077"
}
diff --git a/src/dcm/go.sum b/src/dcm/go.sum
index ad36ad8d..d1b1e30f 100644
--- a/src/dcm/go.sum
+++ b/src/dcm/go.sum
@@ -807,6 +807,7 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
+github.com/onap/multicloud-k8s v0.0.0-20200928235143-603a68284970 h1:yWZDIjZBhwtbV7+fa8QB/WhPlHCR4qBhY2OG7K83wGs=
github.com/onap/multicloud-k8s/src/ncm v0.0.0-20200515060444-c77850a75eee/go.mod h1:q6s8c45A2NN2V4lxciJ7OmCZFaS1uQSWaGxGG3UM3kM=
github.com/onap/multicloud-k8s/src/rsync v0.0.0-20200630152613-7c20f73e7c5d h1:0aXmwqPN8MjyqjKK5L1IhhP/hpP5nGj6xMgo6AOzCPI=
github.com/onap/multicloud-k8s/src/rsync v0.0.0-20200630152613-7c20f73e7c5d/go.mod h1:pVhhvg5N0Qy8QDJkYRnWCQbxLDV5GYLmPyzlndbGx7w=
diff --git a/src/dcm/pkg/module/apply.go b/src/dcm/pkg/module/apply.go
index a866934a..0b370f4a 100644
--- a/src/dcm/pkg/module/apply.go
+++ b/src/dcm/pkg/module/apply.go
@@ -305,12 +305,11 @@ func callRsyncUninstall(contextid interface{}) error {
return nil
}
-func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
+func CreateEtcdContext(project string, logicalcloud LogicalCloud, clusterList []Cluster,
quotaList []Quota) error {
APP := "logical-cloud"
logicalCloudName := logicalcloud.MetaData.LogicalCloudName
- project := "test-project" // FIXME(igordc): temporary, need to do some rework in the LC structs
//Resource Names
namespaceName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+namespace"}, "")
@@ -599,13 +598,12 @@ func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
// TODO: rename these methods
// DestroyEtcdContext remove from rsync then delete appcontext and all resources
-func DestroyEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
+func DestroyEtcdContext(project string, logicalcloud LogicalCloud, clusterList []Cluster,
quotaList []Quota) error {
logicalCloudName := logicalcloud.MetaData.LogicalCloudName
- // project := "test-project" // FIXME(igordc): temporary, need to do some rework in the LC structs
- _, ctxVal, err := NewLogicalCloudClient().GetLogicalCloudContext(logicalCloudName)
+ _, ctxVal, err := NewLogicalCloudClient().GetLogicalCloudContext(project, logicalCloudName)
if err != nil {
return pkgerrors.Wrapf(err, "Error finding AppContext for Logical Cloud: %v", logicalCloudName)
}
diff --git a/src/dcm/pkg/module/logicalcloud.go b/src/dcm/pkg/module/logicalcloud.go
index 83ff153f..3ecb6288 100644
--- a/src/dcm/pkg/module/logicalcloud.go
+++ b/src/dcm/pkg/module/logicalcloud.go
@@ -73,7 +73,7 @@ type LogicalCloudManager interface {
GetAll(project string) ([]LogicalCloud, error)
Delete(project, name string) error
Update(project, name string, c LogicalCloud) (LogicalCloud, error)
- GetLogicalCloudContext(name string) (appcontext.AppContext, string, error)
+ GetLogicalCloudContext(project string, name string) (appcontext.AppContext, string, error)
}
// Interface facilitates unit testing by mocking functions
@@ -237,11 +237,11 @@ func (v *LogicalCloudClient) Update(project, logicalCloudName string, c LogicalC
}
// GetClusterContext returns the AppContext for corresponding provider and name
-func (v *LogicalCloudClient) GetLogicalCloudContext(name string) (appcontext.AppContext, string, error) {
+func (v *LogicalCloudClient) GetLogicalCloudContext(project string, name string) (appcontext.AppContext, string, error) {
//Construct key and tag to select the entry
key := LogicalCloudKey{
LogicalCloudName: name,
- Project: "test-project", // FIXME(igordc): temporary, need to do some rework in the LC structs
+ Project: project,
}
value, err := db.DBconn.Find(v.storeName, key, v.tagContext)
diff --git a/src/k8splugin/api/instancehandler_test.go b/src/k8splugin/api/instancehandler_test.go
index 7b6594cf..c0690fb2 100644
--- a/src/k8splugin/api/instancehandler_test.go
+++ b/src/k8splugin/api/instancehandler_test.go
@@ -316,91 +316,6 @@ func TestInstanceGetHandler(t *testing.T) {
}
}
-func TestStatusHandler(t *testing.T) {
- testCases := []struct {
- label string
- input string
- expectedCode int
- expectedResponse *app.InstanceStatus
- instClient *mockInstanceClient
- }{
- {
- label: "Fail to Get Status",
- input: "HaKpys8e",
- expectedCode: http.StatusInternalServerError,
- instClient: &mockInstanceClient{
- err: pkgerrors.New("Internal error"),
- },
- },
- {
- label: "Succesful GET Status",
- input: "HaKpys8e",
- expectedCode: http.StatusOK,
- expectedResponse: &app.InstanceStatus{
- Request: app.InstanceRequest{
- RBName: "test-rbdef",
- RBVersion: "v1",
- ProfileName: "profile1",
- CloudRegion: "region1",
- },
- Ready: true,
- ResourceCount: 2,
- PodStatuses: []app.PodStatus{
- {
- Name: "test-pod1",
- Namespace: "default",
- Ready: true,
- IPAddresses: []string{"192.168.1.1", "192.168.2.1"},
- },
- {
- Name: "test-pod2",
- Namespace: "default",
- Ready: true,
- IPAddresses: []string{"192.168.3.1", "192.168.5.1"},
- },
- },
- },
- instClient: &mockInstanceClient{
- statusItem: app.InstanceStatus{
- Request: app.InstanceRequest{
- RBName: "test-rbdef",
- RBVersion: "v1",
- ProfileName: "profile1",
- CloudRegion: "region1",
- },
- Ready: true,
- ResourceCount: 2,
- PodStatuses: []app.PodStatus{
- {
- Name: "test-pod1",
- Namespace: "default",
- Ready: true,
- IPAddresses: []string{"192.168.1.1", "192.168.2.1"},
- },
- {
- Name: "test-pod2",
- Namespace: "default",
- Ready: true,
- IPAddresses: []string{"192.168.3.1", "192.168.5.1"},
- },
- },
- },
- },
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.label, func(t *testing.T) {
- request := httptest.NewRequest("GET", "/v1/instance/"+testCase.input+"/status", nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil))
-
- if testCase.expectedCode != resp.StatusCode {
- t.Fatalf("Request method returned: %v and it was expected: %v", resp.StatusCode, testCase.expectedCode)
- }
- })
- }
-}
-
func TestInstanceListHandler(t *testing.T) {
testCases := []struct {
label string
diff --git a/src/k8splugin/go.mod b/src/k8splugin/go.mod
index 57b03266..75cb7c7e 100644
--- a/src/k8splugin/go.mod
+++ b/src/k8splugin/go.mod
@@ -1,8 +1,6 @@
module github.com/onap/multicloud-k8s/src/k8splugin
require (
- cloud.google.com/go v0.38.0 // indirect
- github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/DATA-DOG/go-sqlmock v1.3.3 // indirect
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect
github.com/Masterminds/semver v1.4.2 // indirect
@@ -10,35 +8,26 @@ require (
github.com/aokoli/goutils v1.1.0 // indirect
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 // indirect
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
- github.com/coreos/bbolt v1.3.3 // indirect
- github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
- github.com/cyphar/filepath-securejoin v0.2.2 // indirect
- github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/docker/docker v0.7.3-0.20190912223608-ad718029b705 // indirect
github.com/docker/engine v0.0.0-20190620014054-c513a4c6c298
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 // indirect
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
- github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
- github.com/fatih/camelcase v1.0.0 // indirect
github.com/fvbommel/util v0.0.2
github.com/ghodss/yaml v1.0.0
github.com/go-openapi/spec v0.19.3 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/gobuffalo/packr v1.30.1 // indirect
- github.com/gobwas/glob v0.2.3 // indirect
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/googleapis/gnostic v0.2.0 // indirect
- github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/handlers v1.3.0
github.com/gorilla/mux v1.7.0
github.com/gorilla/websocket v1.4.1 // indirect
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect
- github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.11.1 // indirect
github.com/hashicorp/consul v1.4.0
github.com/hashicorp/go-msgpack v0.5.5 // indirect
@@ -46,20 +35,11 @@ require (
github.com/hashicorp/memberlist v0.1.5 // indirect
github.com/hashicorp/serf v0.8.1 // indirect
github.com/huandu/xstrings v1.2.0 // indirect
- github.com/imdario/mergo v0.3.5 // indirect
github.com/jmoiron/sqlx v1.2.0 // indirect
- github.com/jonboulle/clockwork v0.1.0 // indirect
- github.com/json-iterator/go v1.1.7 // indirect
github.com/lib/pq v1.2.0 // indirect
- github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
- github.com/mitchellh/go-wordwrap v1.0.0 // indirect
- github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
- github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
- github.com/pborman/uuid v1.2.0 // indirect
- github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.8.1
github.com/rubenv/sql-migrate v0.0.0-20190902133344-8926f37f0bc1 // indirect
github.com/sirupsen/logrus v1.4.2
@@ -71,18 +51,11 @@ require (
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
github.com/xdg/stringprep v1.0.0 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
- github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // indirect
github.com/ziutek/mymysql v1.5.4 // indirect
- go.etcd.io/bbolt v1.3.3 // indirect
go.etcd.io/etcd v3.3.12+incompatible
go.mongodb.org/mongo-driver v1.0.0
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
- golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
- google.golang.org/appengine v1.5.0 // indirect
gopkg.in/gorp.v1 v1.7.2 // indirect
- gopkg.in/inf.v0 v0.9.1 // indirect
- gopkg.in/square/go-jose.v2 v2.2.2 // indirect
- gotest.tools v2.2.0+incompatible // indirect
k8s.io/api v0.18.2
k8s.io/apiextensions-apiserver v0.18.2
k8s.io/apimachinery v0.18.2
@@ -90,7 +63,6 @@ require (
k8s.io/client-go v12.0.0+incompatible
k8s.io/cloud-provider v0.18.2
k8s.io/helm v2.16.12+incompatible
- k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf // indirect
k8s.io/kubernetes v1.16.9
k8s.io/utils v0.0.0-20190907131718-3d4f5b7dea0b // indirect
sigs.k8s.io/kustomize v2.0.3+incompatible
diff --git a/src/k8splugin/internal/app/client.go b/src/k8splugin/internal/app/client.go
index ed606444..6762d1bc 100644
--- a/src/k8splugin/internal/app/client.go
+++ b/src/k8splugin/internal/app/client.go
@@ -1,5 +1,7 @@
/*
Copyright 2018 Intel Corporation.
+Copyright © 2020 Samsung Electronics
+
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -18,6 +20,7 @@ import (
"strings"
"time"
+ "github.com/onap/multicloud-k8s/src/k8splugin/internal/config"
"github.com/onap/multicloud-k8s/src/k8splugin/internal/connection"
"github.com/onap/multicloud-k8s/src/k8splugin/internal/helm"
log "github.com/onap/multicloud-k8s/src/k8splugin/internal/logutils"
@@ -25,6 +28,9 @@ import (
pkgerrors "github.com/pkg/errors"
"k8s.io/apimachinery/pkg/api/meta"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+ "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery/cached/disk"
"k8s.io/client-go/dynamic"
@@ -43,6 +49,79 @@ type KubernetesClient struct {
instanceID string
}
+// ResourceStatus holds Resource Runtime Data
+type ResourceStatus struct {
+ Name string `json:"name"`
+ GVK schema.GroupVersionKind `json:"GVK"`
+ Status unstructured.Unstructured `json:"status"`
+}
+
+// getPodsByLabel yields status of all pods under given instance ID
+func (k *KubernetesClient) getPodsByLabel(namespace string) ([]ResourceStatus, error) {
+ client := k.GetStandardClient().CoreV1().Pods(namespace)
+ listOpts := metav1.ListOptions{
+ LabelSelector: config.GetConfiguration().KubernetesLabelName + "=" + k.instanceID,
+ }
+ podList, err := client.List(listOpts)
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "Retrieving PodList from cluster")
+ }
+ resp := make([]ResourceStatus, 0, len(podList.Items))
+ cumulatedErrorMsg := make([]string, 0)
+ for _, pod := range podList.Items {
+ podContent, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&pod)
+ if err != nil {
+ cumulatedErrorMsg = append(cumulatedErrorMsg, err.Error())
+ continue
+ }
+ var unstrPod unstructured.Unstructured
+ unstrPod.SetUnstructuredContent(podContent)
+ podStatus := ResourceStatus{
+ Name: unstrPod.GetName(),
+ GVK: schema.FromAPIVersionAndKind("v1", "Pod"),
+ Status: unstrPod,
+ }
+ resp = append(resp, podStatus)
+ }
+ if len(cumulatedErrorMsg) != 0 {
+ return resp, pkgerrors.New("Converting podContent to unstruct error:\n" +
+ strings.Join(cumulatedErrorMsg, "\n"))
+ }
+ return resp, nil
+}
+
+// getResourcesStatus yields status of given generic resource
+func (k *KubernetesClient) getResourceStatus(res helm.KubernetesResource, namespace string) (ResourceStatus, error) {
+ dynClient := k.GetDynamicClient()
+ mapper := k.GetMapper()
+ mapping, err := mapper.RESTMapping(schema.GroupKind{
+ Group: res.GVK.Group,
+ Kind: res.GVK.Kind,
+ }, res.GVK.Version)
+ if err != nil {
+ return ResourceStatus{},
+ pkgerrors.Wrap(err, "Preparing mapper based on GVK")
+ }
+
+ gvr := mapping.Resource
+ opts := metav1.GetOptions{}
+ var unstruct *unstructured.Unstructured
+ switch mapping.Scope.Name() {
+ case meta.RESTScopeNameNamespace:
+ unstruct, err = dynClient.Resource(gvr).Namespace(namespace).Get(res.Name, opts)
+ case meta.RESTScopeNameRoot:
+ unstruct, err = dynClient.Resource(gvr).Get(res.Name, opts)
+ default:
+ return ResourceStatus{}, pkgerrors.New("Got an unknown RESTSCopeName for mapping: " + res.GVK.String())
+ }
+
+ if err != nil {
+ return ResourceStatus{}, pkgerrors.Wrap(err, "Getting object status")
+ }
+
+ return ResourceStatus{unstruct.GetName(), res.GVK, *unstruct}, nil
+}
+
// getKubeConfig uses the connectivity client to get the kubeconfig based on the name
// of the cloudregion. This is written out to a file.
func (k *KubernetesClient) getKubeConfig(cloudregion string) (string, error) {
@@ -182,40 +261,40 @@ func (k *KubernetesClient) createKind(resTempl helm.KubernetesResourceTemplate,
}
func (k *KubernetesClient) updateKind(resTempl helm.KubernetesResourceTemplate,
- namespace string) (helm.KubernetesResource, error) {
-
- if _, err := os.Stat(resTempl.FilePath); os.IsNotExist(err) {
- return helm.KubernetesResource{}, pkgerrors.New("File " + resTempl.FilePath + "does not exists")
- }
-
- log.Info("Processing Kubernetes Resource", log.Fields{
- "filepath": resTempl.FilePath,
- })
-
- pluginImpl, err := plugin.GetPluginByKind(resTempl.GVK.Kind)
- if err != nil {
- return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error loading plugin")
- }
-
- updatedResourceName, err := pluginImpl.Update(resTempl.FilePath, namespace, k)
- if err != nil {
- log.Error("Error Updating Resource", log.Fields{
- "error": err,
- "gvk": resTempl.GVK,
- "filepath": resTempl.FilePath,
- })
- return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error in plugin "+resTempl.GVK.Kind+" plugin")
- }
-
- log.Info("Updated Kubernetes Resource", log.Fields{
- "resource": updatedResourceName,
- "gvk": resTempl.GVK,
- })
-
- return helm.KubernetesResource{
- GVK: resTempl.GVK,
- Name: updatedResourceName,
- }, nil
+ namespace string) (helm.KubernetesResource, error) {
+
+ if _, err := os.Stat(resTempl.FilePath); os.IsNotExist(err) {
+ return helm.KubernetesResource{}, pkgerrors.New("File " + resTempl.FilePath + "does not exists")
+ }
+
+ log.Info("Processing Kubernetes Resource", log.Fields{
+ "filepath": resTempl.FilePath,
+ })
+
+ pluginImpl, err := plugin.GetPluginByKind(resTempl.GVK.Kind)
+ if err != nil {
+ return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error loading plugin")
+ }
+
+ updatedResourceName, err := pluginImpl.Update(resTempl.FilePath, namespace, k)
+ if err != nil {
+ log.Error("Error Updating Resource", log.Fields{
+ "error": err,
+ "gvk": resTempl.GVK,
+ "filepath": resTempl.FilePath,
+ })
+ return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error in plugin "+resTempl.GVK.Kind+" plugin")
+ }
+
+ log.Info("Updated Kubernetes Resource", log.Fields{
+ "resource": updatedResourceName,
+ "gvk": resTempl.GVK,
+ })
+
+ return helm.KubernetesResource{
+ GVK: resTempl.GVK,
+ Name: updatedResourceName,
+ }, nil
}
func (k *KubernetesClient) createResources(sortedTemplates []helm.KubernetesResourceTemplate,
@@ -239,23 +318,23 @@ func (k *KubernetesClient) createResources(sortedTemplates []helm.KubernetesReso
}
func (k *KubernetesClient) updateResources(sortedTemplates []helm.KubernetesResourceTemplate,
- namespace string) ([]helm.KubernetesResource, error) {
-
- err := k.ensureNamespace(namespace)
- if err != nil {
- return nil, pkgerrors.Wrap(err, "Creating Namespace")
- }
-
- var updatedResources []helm.KubernetesResource
- for _, resTempl := range sortedTemplates {
- resUpdated, err := k.updateKind(resTempl, namespace)
- if err != nil {
- return nil, pkgerrors.Wrapf(err, "Error updating kind: %+v", resTempl.GVK)
- }
- updatedResources = append(updatedResources, resUpdated)
- }
-
- return updatedResources, nil
+ namespace string) ([]helm.KubernetesResource, error) {
+
+ err := k.ensureNamespace(namespace)
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "Creating Namespace")
+ }
+
+ var updatedResources []helm.KubernetesResource
+ for _, resTempl := range sortedTemplates {
+ resUpdated, err := k.updateKind(resTempl, namespace)
+ if err != nil {
+ return nil, pkgerrors.Wrapf(err, "Error updating kind: %+v", resTempl.GVK)
+ }
+ updatedResources = append(updatedResources, resUpdated)
+ }
+
+ return updatedResources, nil
}
func (k *KubernetesClient) deleteKind(resource helm.KubernetesResource, namespace string) error {
diff --git a/src/k8splugin/internal/app/instance.go b/src/k8splugin/internal/app/instance.go
index 220c82da..a6e213c1 100644
--- a/src/k8splugin/internal/app/instance.go
+++ b/src/k8splugin/internal/app/instance.go
@@ -1,5 +1,6 @@
/*
* Copyright 2018 Intel Corporation, Inc
+ * Copyright © 2020 Samsung Electronics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +20,7 @@ package app
import (
"encoding/json"
"log"
+ "strings"
"github.com/onap/multicloud-k8s/src/k8splugin/internal/db"
"github.com/onap/multicloud-k8s/src/k8splugin/internal/helm"
@@ -26,7 +28,6 @@ import (
"github.com/onap/multicloud-k8s/src/k8splugin/internal/rb"
pkgerrors "github.com/pkg/errors"
- corev1 "k8s.io/api/core/v1"
)
// InstanceRequest contains the parameters needed for instantiation
@@ -60,22 +61,12 @@ type InstanceMiniResponse struct {
Namespace string `json:"namespace"`
}
-// PodStatus defines the observed state of ResourceBundleState
-type PodStatus struct {
- Name string `json:"name"`
- Namespace string `json:"namespace"`
- Ready bool `json:"ready"`
- Status corev1.PodStatus `json:"status,omitempty"`
- IPAddresses []string `json:"ipaddresses"`
-}
-
// InstanceStatus is what is returned when status is queried for an instance
type InstanceStatus struct {
Request InstanceRequest `json:"request"`
Ready bool `json:"ready"`
ResourceCount int32 `json:"resourceCount"`
- PodStatuses []PodStatus `json:"podStatuses"`
- ServiceStatuses []corev1.Service `json:"serviceStatuses"`
+ ResourcesStatus []ResourceStatus `json:"resourcesStatus"`
}
// InstanceManager is an interface exposes the instantiation functionality
@@ -107,18 +98,16 @@ func (dk InstanceKey) String() string {
// InstanceClient implements the InstanceManager interface
// It will also be used to maintain some localized state
type InstanceClient struct {
- storeName string
- tagInst string
- tagInstStatus string
+ storeName string
+ tagInst string
}
// NewInstanceClient returns an instance of the InstanceClient
// which implements the InstanceManager
func NewInstanceClient() *InstanceClient {
return &InstanceClient{
- storeName: "rbdef",
- tagInst: "instance",
- tagInstStatus: "instanceStatus",
+ storeName: "rbdef",
+ tagInst: "instance",
}
}
@@ -217,22 +206,64 @@ func (v *InstanceClient) Status(id string) (InstanceStatus, error) {
ID: id,
}
- value, err := db.DBconn.Read(v.storeName, key, v.tagInstStatus)
+ value, err := db.DBconn.Read(v.storeName, key, v.tagInst)
if err != nil {
return InstanceStatus{}, pkgerrors.Wrap(err, "Get Instance")
}
//value is a byte array
- if value != nil {
- resp := InstanceStatus{}
- err = db.DBconn.Unmarshal(value, &resp)
+ if value == nil {
+ return InstanceStatus{}, pkgerrors.New("Status is not available")
+ }
+
+ resResp := InstanceResponse{}
+ err = db.DBconn.Unmarshal(value, &resResp)
+ if err != nil {
+ return InstanceStatus{}, pkgerrors.Wrap(err, "Unmarshaling Instance Value")
+ }
+
+ k8sClient := KubernetesClient{}
+ err = k8sClient.init(resResp.Request.CloudRegion, id)
+ if err != nil {
+ return InstanceStatus{}, pkgerrors.Wrap(err, "Getting CloudRegion Information")
+ }
+
+ cumulatedErrorMsg := make([]string, 0)
+ podsStatus, err := k8sClient.getPodsByLabel(resResp.Namespace)
+ if err != nil {
+ cumulatedErrorMsg = append(cumulatedErrorMsg, err.Error())
+ }
+
+ generalStatus := make([]ResourceStatus, 0, len(resResp.Resources))
+Main:
+ for _, resource := range resResp.Resources {
+ for _, pod := range podsStatus {
+ if resource.GVK == pod.GVK && resource.Name == pod.Name {
+ continue Main //Don't double check pods if someone decided to define pod explicitly in helm chart
+ }
+ }
+ status, err := k8sClient.getResourceStatus(resource, resResp.Namespace)
if err != nil {
- return InstanceStatus{}, pkgerrors.Wrap(err, "Unmarshaling Instance Value")
+ cumulatedErrorMsg = append(cumulatedErrorMsg, err.Error())
+ } else {
+ generalStatus = append(generalStatus, status)
}
- return resp, nil
+ }
+ resp := InstanceStatus{
+ Request: resResp.Request,
+ ResourceCount: int32(len(generalStatus) + len(podsStatus)),
+ Ready: false, //FIXME To determine readiness, some parsing of status fields is necessary
+ ResourcesStatus: append(generalStatus, podsStatus...),
}
- return InstanceStatus{}, pkgerrors.New("Status is not available")
+ if len(cumulatedErrorMsg) != 0 {
+ err = pkgerrors.New("Getting Resources Status:\n" +
+ strings.Join(cumulatedErrorMsg, "\n"))
+ return resp, err
+ }
+ //TODO Filter response content by requested verbosity (brief, ...)?
+
+ return resp, nil
}
// List returns the instance for corresponding ID
diff --git a/src/k8splugin/internal/app/instance_test.go b/src/k8splugin/internal/app/instance_test.go
index 1b84b449..b79cf388 100644
--- a/src/k8splugin/internal/app/instance_test.go
+++ b/src/k8splugin/internal/app/instance_test.go
@@ -318,128 +318,6 @@ func TestInstanceGet(t *testing.T) {
})
}
-func TestInstanceStatus(t *testing.T) {
- oldkrdPluginData := utils.LoadedPlugins
-
- defer func() {
- utils.LoadedPlugins = oldkrdPluginData
- }()
-
- err := LoadMockPlugins(utils.LoadedPlugins)
- if err != nil {
- t.Fatalf("LoadMockPlugins returned an error (%s)", err)
- }
-
- t.Run("Successfully Get Instance Status", func(t *testing.T) {
- db.DBconn = &db.MockDB{
- Items: map[string]map[string][]byte{
- InstanceKey{ID: "HaKpys8e"}.String(): {
- "instanceStatus": []byte(
- `{
- "request": {
- "profile-name":"profile1",
- "rb-name":"test-rbdef",
- "rb-version":"v1",
- "cloud-region":"region1"
- },
- "ready": true,
- "resourceCount": 2,
- "podStatuses": [
- {
- "name": "test-pod1",
- "namespace": "default",
- "ready": true,
- "ipaddresses": ["192.168.1.1", "192.168.2.1"]
- },
- {
- "name": "test-pod2",
- "namespace": "default",
- "ready": true,
- "ipaddresses": ["192.168.4.1", "192.168.5.1"]
- }
- ]
- }`),
- },
- },
- }
-
- expected := InstanceStatus{
- Request: InstanceRequest{
- RBName: "test-rbdef",
- RBVersion: "v1",
- ProfileName: "profile1",
- CloudRegion: "region1",
- },
- Ready: true,
- ResourceCount: 2,
- PodStatuses: []PodStatus{
- {
- Name: "test-pod1",
- Namespace: "default",
- Ready: true,
- IPAddresses: []string{"192.168.1.1", "192.168.2.1"},
- },
- {
- Name: "test-pod2",
- Namespace: "default",
- Ready: true,
- IPAddresses: []string{"192.168.4.1", "192.168.5.1"},
- },
- },
- }
- ic := NewInstanceClient()
- id := "HaKpys8e"
- data, err := ic.Status(id)
- if err != nil {
- t.Fatalf("TestInstanceStatus returned an error (%s)", err)
- }
- if !reflect.DeepEqual(expected, data) {
- t.Fatalf("TestInstanceStatus returned:\n result=%v\n expected=%v",
- data, expected)
- }
- })
-
- t.Run("Get non-existing Instance", func(t *testing.T) {
- db.DBconn = &db.MockDB{
- Items: map[string]map[string][]byte{
- InstanceKey{ID: "HaKpys8e"}.String(): {
- "instanceStatus": []byte(
- `{
- "request": {
- "profile-name":"profile1",
- "rb-name":"test-rbdef",
- "rb-version":"v1",
- "cloud-region":"region1"
- },
- "ready": true,
- "resourceCount": 2,
- "podStatuses": [
- {
- "name": "test-pod1",
- "namespace": "default",
- "ready": true,
- "ipaddresses": ["192.168.1.1", "192.168.2.1"]
- },
- {
- "name": "test-pod2",
- "namespace": "default",
- "ready": true,
- "ipaddresses": ["192.168.4.1", "192.168.5.1"]
- }
- ]
- }`),
- },
- },
- }
-
- ic := NewInstanceClient()
- _, err := ic.Get("non-existing")
- if err == nil {
- t.Fatal("Expected error, got pass", err)
- }
- })
-}
-
func TestInstanceFind(t *testing.T) {
oldkrdPluginData := utils.LoadedPlugins
diff --git a/src/k8splugin/internal/plugin/helpers.go b/src/k8splugin/internal/plugin/helpers.go
index 19ff03ab..7078b813 100644
--- a/src/k8splugin/internal/plugin/helpers.go
+++ b/src/k8splugin/internal/plugin/helpers.go
@@ -69,8 +69,8 @@ type Reference interface {
//Delete a kubernetes resource described in the provided namespace
Delete(resource helm.KubernetesResource, namespace string, client KubernetesConnector) error
- //Update kubernetes resource based on the groupVersionKind and resourceName provided in resource
- Update(yamlFilePath string, namespace string, client KubernetesConnector) (string, error)
+ //Update kubernetes resource based on the groupVersionKind and resourceName provided in resource
+ Update(yamlFilePath string, namespace string, client KubernetesConnector) (string, error)
}
// GetPluginByKind returns a plugin by the kind name
diff --git a/src/monitor/deploy/crds/k8splugin_v1alpha1_resourcebundlestate_crd.yaml b/src/monitor/deploy/crds/k8splugin_v1alpha1_resourcebundlestate_crd.yaml
index 9ca95a32..25197f05 100644
--- a/src/monitor/deploy/crds/k8splugin_v1alpha1_resourcebundlestate_crd.yaml
+++ b/src/monitor/deploy/crds/k8splugin_v1alpha1_resourcebundlestate_crd.yaml
@@ -77,6 +77,10 @@ spec:
items:
type: object
type: array
+ csrStatuses:
+ items:
+ type: object
+ type: array
required:
- ready
- resourceCount
@@ -89,6 +93,7 @@ spec:
- ingressStatuses
- jobStatuses
- statefulSetStatuses
+ - csrStatuses
type: object
version: v1alpha1
versions: