aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INFO.yaml95
-rw-r--r--README.md20
-rw-r--r--deployments/Dockerfile8
-rwxr-xr-xdeployments/start.sh1
-rw-r--r--kud/deployment_infra/playbooks/kud-vars.yml2
-rw-r--r--kud/hosting_providers/vagrant/Vagrantfile2
-rwxr-xr-xkud/hosting_providers/vagrant/installer.sh6
-rwxr-xr-xkud/tests/_functions.sh2
-rwxr-xr-xkud/tests/multus.sh10
-rwxr-xr-xkud/tests/ovn4nfv.sh7
-rw-r--r--src/k8splugin/api/api.go3
-rw-r--r--src/k8splugin/api/healthcheckhandler.go35
-rw-r--r--src/k8splugin/api/healthcheckhandler_test.go58
-rw-r--r--src/k8splugin/cmd/main.go3
-rw-r--r--src/k8splugin/go.sum78
-rw-r--r--src/k8splugin/internal/app/client.go30
-rw-r--r--src/k8splugin/internal/app/client_test.go26
-rw-r--r--src/k8splugin/internal/app/instance.go5
-rw-r--r--src/k8splugin/internal/app/instance_test.go33
-rw-r--r--src/k8splugin/internal/config/config.go2
-rw-r--r--src/k8splugin/internal/connection/connection.go50
-rw-r--r--src/k8splugin/internal/connection/connectionhandler.go42
-rw-r--r--src/k8splugin/internal/db/testing.go4
-rw-r--r--src/k8splugin/internal/utils.go2
-rw-r--r--src/k8splugin/plugins/deployment/plugin.go115
-rw-r--r--src/k8splugin/plugins/deployment/plugin_test.go266
-rw-r--r--src/k8splugin/plugins/generic/plugin.go12
27 files changed, 355 insertions, 562 deletions
diff --git a/INFO.yaml b/INFO.yaml
index 2bd41fdb..d808cb30 100644
--- a/INFO.yaml
+++ b/INFO.yaml
@@ -21,12 +21,12 @@ mailing_list:
realtime_discussion: ''
meetings:
- type: 'zoom'
- agenda: 'https://wiki.onap.org/pages/viewpage.action?pageId=6591499'
- url: 'https://wiki.onap.org/pages/viewpage.action?pageId=6591499'
- server: 'n/a'
- channel: 'n/a'
- repeats: 'weekly'
- time: '13:00 UTC'
+ agenda: 'https://wiki.onap.org/pages/viewpage.action?pageId=6591499'
+ url: 'https://wiki.onap.org/pages/viewpage.action?pageId=6591499'
+ server: 'n/a'
+ channel: 'n/a'
+ repeats: 'weekly'
+ time: '13:00 UTC'
repositories:
- 'multicloud-framework'
- 'multicloud-openstack'
@@ -38,51 +38,62 @@ repositories:
committers:
- <<: *onap_multicloud_ptl
- name: 'Anbing Zhang'
- email: 'zhanganbing@chinamobile.com'
- company: 'China Mobile'
- id: 'zhangab'
- timezone: ''
+ email: 'zhanganbing@chinamobile.com'
+ company: 'China Mobile'
+ id: 'zhangab'
+ timezone: 'Asia/Shanghai'
- name: 'Xinhui Li'
- email: 'lxinhui@vmware.com'
- id: 'xinhuili'
- company: 'VMware'
- timezone: 'China/Beijing'
+ email: 'lxinhui@vmware.com'
+ id: 'xinhuili'
+ company: 'VMware'
+ timezone: 'Asia/Shanghai'
- name: 'Bin Hu'
- email: 'bh526r@att.com'
- company: 'ATT'
- id: 'bh526r'
- timezone: 'America/Palo Alto'
+ email: 'bh526r@att.com'
+ company: 'ATT'
+ id: 'bh526r'
+ timezone: 'America/Los_Angeles'
- name: 'Victor Morales'
- email: 'victor.morales@intel.com'
- company: 'Intel'
- id: 'electrocucaracha'
- timezone: ''
+ email: 'victor.morales@intel.com'
+ company: 'Intel'
+ id: 'electrocucaracha'
+ timezone: 'America/Los_Angeles'
- name: 'Ethan Lynn'
- email: 'ethanlynnl@vmware.com'
- company: 'VMWare'
- id: 'ethanlynnl'
- timezone: ''
+ email: 'ethanlynnl@vmware.com'
+ company: 'VMWare'
+ id: 'ethanlynnl'
+ timezone: 'Asia/Shanghai'
- name: 'Huang Haibin'
- email: 'haibin.huang@intel.com'
- company: 'Intel'
- id: 'haibin'
- timezone: ''
+ email: 'haibin.huang@intel.com'
+ company: 'Intel'
+ id: 'haibin'
+ timezone: 'Asia/Shanghai'
- name: 'Sudhakar Reddy'
- email: 'Sudhakar.Reddy@amdocs.com'
- company: 'Amdocs'
- id: 'SudhakarReddy'
- timezone: ''
+ email: 'Sudhakar.Reddy@amdocs.com'
+ company: 'Amdocs'
+ id: 'SudhakarReddy'
+ timezone: 'Asia/Kolkata'
+ - name: 'Xiaohua Zhang'
+ email: 'Xiaohua.Zhang@windriver.com'
+ company: 'Wind River'
+ id: 'Xiaohua626'
+ timezone: 'Asia/Shanghai'
tsc:
approval: 'https://lists.onap.org/pipermail/onap-tsc'
changes:
- type: 'Addition'
- name: 'yun huang'
- name: 'Victor Morales'
- name: 'Ethan Lynn'
- name: 'Huang Haibin'
- name: 'Sudhakar Reddy'
+ name:
+ - 'yun huang'
+ - 'Victor Morales'
+ - 'Ethan Lynn'
+ - 'Huang Haibin'
+ - 'Sudhakar Reddy'
link: 'http://ircbot.wl.linuxfoundation.org/meetings/onap-meeting/2018/onap-meeting.2018-08-16-13.45.html'
- type: 'Remove'
- name: 'yun huang'
- name: 'Ke Liang'
- name: 'Andrew Philip'
+ name:
+ - 'yun huang'
+ - 'Ke Liang'
+ - 'Andrew Philip'
+ link: 'https://lists.onap.org/g/onap-tsc/message/4635'
+ - type: 'Addition'
+ name: 'Xiaohua Zhang'
+ link: 'https://lists.onap.org/g/onap-tsc/message/4772'
diff --git a/README.md b/README.md
index c3de0b55..fb94b4ca 100644
--- a/README.md
+++ b/README.md
@@ -16,18 +16,24 @@ MultiCloud Kubernetes plugin for ONAP multicloud.
# Installation
Requirements:
-* Go 1.11
+* Go 1.12.4
Steps:
-* Clone repo in GOPATH src:
- * `cd $GOPATH/src && git clone https://git.onap.org/multicloud/k8s`
+* Clone repo:
+ * `git clone https://git.onap.org/multicloud/k8s`
-* Run unit tests:
- * `make build`
+* Build everything:
+ * `cd k8s/src/k8splugin && make all`
-* Compile to build Binary:
- * `make deploy`
+* Run Tests:
+ * `cd k8s/src/k8splugin && make test`
+
+* Generate Coverage Report:
+ * `cd k8s/src/k8splugin && make cover`
+
+* Run the plugin:
+ * `cd k8s/deployments && ./start.sh`
# Architecture
diff --git a/deployments/Dockerfile b/deployments/Dockerfile
index c37c7989..dfe16cb1 100644
--- a/deployments/Dockerfile
+++ b/deployments/Dockerfile
@@ -16,13 +16,7 @@ ENV http_proxy $HTTP_PROXY
ENV https_proxy $HTTPS_PROXY
ENV no_proxy $NO_PROXY
-ENV CSAR_DIR "/opt/csar"
-ENV KUBE_CONFIG_DIR "/opt/kubeconfig"
-ENV DATABASE_TYPE "consul"
-ENV DATABASE_IP "127.0.0.1"
-ENV OVN_CENTRAL_ADDRESS "127.0.0.1:6641"
-
-EXPOSE 8081
+EXPOSE 9015
RUN groupadd -r onap && useradd -r -g onap onap
RUN apt-get update && apt-get install -y -qq apt-transport-https curl \
diff --git a/deployments/start.sh b/deployments/start.sh
index f8dc8e7f..a57a6377 100755
--- a/deployments/start.sh
+++ b/deployments/start.sh
@@ -31,6 +31,7 @@ cat << EOF > k8sconfig.json
"database-address": "$DATABASE_IP",
"database-type": "mongo",
"plugin-dir": "$(pwd)/plugins",
+ "service-port": "9015",
"kube-config-dir": "$(pwd)/kubeconfigs"
}
EOF
diff --git a/kud/deployment_infra/playbooks/kud-vars.yml b/kud/deployment_infra/playbooks/kud-vars.yml
index d49c3b73..8e4f3c4f 100644
--- a/kud/deployment_infra/playbooks/kud-vars.yml
+++ b/kud/deployment_infra/playbooks/kud-vars.yml
@@ -57,7 +57,7 @@ ovn4nfv_source_type: "source"
ovn4nfv_version: aa14577f6bc672bc8622edada8a487825fdebce1
ovn4nfv_url: "https://git.opnfv.org/ovn4nfv-k8s-plugin/"
-go_version: '1.11'
+go_version: '1.12.4'
kubespray_version: 2.8.2
kubectl_version: 1.12.2
helm_client_version: 2.9.1
diff --git a/kud/hosting_providers/vagrant/Vagrantfile b/kud/hosting_providers/vagrant/Vagrantfile
index 83ac68c2..d068b84a 100644
--- a/kud/hosting_providers/vagrant/Vagrantfile
+++ b/kud/hosting_providers/vagrant/Vagrantfile
@@ -120,7 +120,7 @@ Vagrant.configure("2") do |config|
installer.vm.network :private_network, :ip => "10.10.10.2", :type => :static
installer.vm.synced_folder '../../../', '/home/vagrant/multicloud-k8s/', type: sync_type
installer.vm.provision 'shell', privileged: false do |sh|
- sh.env = {'KUD_PLUGIN_ENABLED': 'true'}
+ sh.env = {'KUD_PLUGIN_ENABLED': 'false'}
sh.inline = <<-SHELL
cp /vagrant/insecure_keys/key.pub /home/vagrant/.ssh/id_rsa.pub
cp /vagrant/insecure_keys/key /home/vagrant/.ssh/id_rsa
diff --git a/kud/hosting_providers/vagrant/installer.sh b/kud/hosting_providers/vagrant/installer.sh
index dd27e05f..c17f89e8 100755
--- a/kud/hosting_providers/vagrant/installer.sh
+++ b/kud/hosting_providers/vagrant/installer.sh
@@ -31,10 +31,10 @@ function _install_go {
# _install_pip() - Install Python Package Manager
function _install_pip {
if $(pip --version &>/dev/null); then
+ sudo -E pip install --upgrade pip
+ else
sudo apt-get install -y python-dev
curl -sL https://bootstrap.pypa.io/get-pip.py | sudo python
- else
- sudo -E pip install --upgrade pip
fi
}
@@ -234,7 +234,7 @@ fi
sudo apt-get update
install_k8s
install_addons
-if [[ "${KUD_PLUGIN_ENABLED:-false}" ]]; then
+if ${KUD_PLUGIN_ENABLED:-false}; then
install_plugin
fi
_print_kubernetes_info
diff --git a/kud/tests/_functions.sh b/kud/tests/_functions.sh
index c25d1f2f..5efb56fe 100755
--- a/kud/tests/_functions.sh
+++ b/kud/tests/_functions.sh
@@ -12,6 +12,8 @@ set -o errexit
set -o nounset
set -o pipefail
+source /etc/environment
+
function print_msg {
local msg=$1
local RED='\033[0;31m'
diff --git a/kud/tests/multus.sh b/kud/tests/multus.sh
index 859fa3bb..2cff84bd 100755
--- a/kud/tests/multus.sh
+++ b/kud/tests/multus.sh
@@ -29,12 +29,14 @@ setup $multus_deployment_name
deployment_pod=$(kubectl get pods | grep $multus_deployment_name | awk '{print $1}')
echo "===== $deployment_pod details ====="
kubectl exec -it $deployment_pod -- ip a
-multus_nic=$(kubectl exec -it $deployment_pod -- ifconfig | grep "eth1")
-if [ -z "$multus_nic" ]; then
- echo "The $deployment_pod pod doesn't contain the eth1 nic"
+multus_nic=$(kubectl exec -it $deployment_pod -- ip a)
+if [[ $multus_nic != *"net1"* ]]; then
+ echo "The $deployment_pod pod doesn't contain the net1 nic"
exit 1
+else
+ echo "Test Completed!"
fi
-popd
# Teardown
teardown $multus_deployment_name
+popd
diff --git a/kud/tests/ovn4nfv.sh b/kud/tests/ovn4nfv.sh
index 37fddfd8..de8631f4 100755
--- a/kud/tests/ovn4nfv.sh
+++ b/kud/tests/ovn4nfv.sh
@@ -33,10 +33,13 @@ setup $ovn4nfv_deployment_name
deployment_pod=$(kubectl get pods | grep $ovn4nfv_deployment_name | awk '{print $1}')
echo "===== $deployment_pod details ====="
kubectl exec -it $deployment_pod -- ip a
-multus_nic=$(kubectl exec -it $deployment_pod -- ifconfig | grep "net1")
-if [ -z "$multus_nic" ]; then
+
+ovn_nic=$(kubectl exec -it $deployment_pod -- ip a )
+if [[ $ovn_nic != *"net1"* ]]; then
echo "The $deployment_pod pod doesn't contain the net1 nic"
exit 1
+else
+ echo "Test Completed!"
fi
# Teardown
diff --git a/src/k8splugin/api/api.go b/src/k8splugin/api/api.go
index 741c0639..5fed28a0 100644
--- a/src/k8splugin/api/api.go
+++ b/src/k8splugin/api/api.go
@@ -101,5 +101,8 @@ func NewRouter(defClient rb.DefinitionManager,
resRouter.HandleFunc("/definition/{rbname}/{rbversion}/profile/{prname}/config/rollback", configHandler.rollbackHandler).Methods("POST")
resRouter.HandleFunc("/definition/{rbname}/{rbversion}/profile/{prname}/config/tagit", configHandler.tagitHandler).Methods("POST")
+ // Add healthcheck path
+ instRouter.HandleFunc("/healthcheck", healthCheckHandler).Methods("GET")
+
return router
}
diff --git a/src/k8splugin/api/healthcheckhandler.go b/src/k8splugin/api/healthcheckhandler.go
new file mode 100644
index 00000000..79b7b7ef
--- /dev/null
+++ b/src/k8splugin/api/healthcheckhandler.go
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018 Intel Corporation, Inc
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package api
+
+import (
+ "net/http"
+
+ "k8splugin/internal/db"
+)
+
+// healthCheckHandler executes a db read to return health of k8splugin
+// and its backing database
+func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
+ err := db.DBconn.HealthCheck()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+}
diff --git a/src/k8splugin/api/healthcheckhandler_test.go b/src/k8splugin/api/healthcheckhandler_test.go
new file mode 100644
index 00000000..c2e1888e
--- /dev/null
+++ b/src/k8splugin/api/healthcheckhandler_test.go
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 Intel Corporation, Inc
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package api
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "k8splugin/internal/db"
+
+ pkgerrors "github.com/pkg/errors"
+)
+
+// healthCheckHandler executes a db read to return health of k8splugin
+// and its backing database
+func TestHealthCheckHandler(t *testing.T) {
+
+ t.Run("OK HealthCheck", func(t *testing.T) {
+ db.DBconn = &db.MockDB{
+ Err: nil,
+ }
+ request := httptest.NewRequest("GET", "/v1/healthcheck", nil)
+ resp := executeRequest(request, NewRouter(nil, nil, nil, nil, nil))
+
+ //Check returned code
+ if resp.StatusCode != http.StatusOK {
+ t.Fatalf("Expected %d; Got: %d", http.StatusOK, resp.StatusCode)
+ }
+ })
+
+ t.Run("FAILED HealthCheck", func(t *testing.T) {
+ db.DBconn = &db.MockDB{
+ Err: pkgerrors.New("Runtime Error in DB"),
+ }
+ request := httptest.NewRequest("GET", "/v1/healthcheck", nil)
+ resp := executeRequest(request, NewRouter(nil, nil, nil, nil, nil))
+
+ //Check returned code
+ if resp.StatusCode != http.StatusInternalServerError {
+ t.Fatalf("Expected %d; Got: %d", http.StatusInternalServerError, resp.StatusCode)
+ }
+ })
+}
diff --git a/src/k8splugin/cmd/main.go b/src/k8splugin/cmd/main.go
index 607e3fe1..d6d9d75a 100644
--- a/src/k8splugin/cmd/main.go
+++ b/src/k8splugin/cmd/main.go
@@ -25,6 +25,7 @@ import (
"k8splugin/api"
utils "k8splugin/internal"
"k8splugin/internal/auth"
+ "k8splugin/internal/config"
"github.com/gorilla/handlers"
)
@@ -44,7 +45,7 @@ func main() {
httpServer := &http.Server{
Handler: loggedRouter,
- Addr: ":8081", // Remove hardcoded port number
+ Addr: ":" + config.GetConfiguration().ServicePort,
}
connectionsClose := make(chan struct{})
diff --git a/src/k8splugin/go.sum b/src/k8splugin/go.sum
index 401999b8..cf605d2f 100644
--- a/src/k8splugin/go.sum
+++ b/src/k8splugin/go.sum
@@ -1,5 +1,4 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -20,7 +19,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U=
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/coreos/etcd v3.3.12+incompatible h1:5k8nkcBSvltjOO5RLflnXevOJXndlKIMbvVnMTX+cUU=
+github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ=
github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
@@ -28,10 +27,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU=
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v0.7.3-0.20190312165151-258edd715d46 h1:6ulO/mTQ7hN75egZfHioZVG2srV1c7CBXCQsXJmSOQU=
+github.com/docker/docker v0.7.3-0.20190312165151-258edd715d46 h1:nxT2VWYpy5So0xPokgtf+AMyNaU2Cvb1JU1A2anxNww=
github.com/docker/docker v0.7.3-0.20190312165151-258edd715d46/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v1.13.1 h1:5VBhsO6ckUxB0A8CE5LlUJdXzik9cbEbBTQ/ggeml7M=
-github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
@@ -46,8 +43,6 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwC
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
-github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7iEV1zPCGQldM2atlJZ3TdvVM=
-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/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
@@ -75,7 +70,6 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pO
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
@@ -83,7 +77,6 @@ github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s=
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
-github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.3.0 h1:tsg9qP3mjt1h4Roxp+M1paRjrVBfPSOpBuVclh6YluI=
github.com/gorilla/handlers v1.3.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@@ -97,34 +90,27 @@ github.com/hashicorp/consul v1.4.0 h1:PQTW4xCuAExEiSbhrsFsikzbW5gVBoi74BjUvYFyKH
github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:9HVkPxOpo+yO93Ah4yrO67d/qh0fbLLWbKqhYjyHq9A=
+github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E=
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg=
-github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/serf v0.8.1 h1:mYs6SMzu72+90OcPa5wr3nfznA4Dw9UyR791ZFNOIf4=
github.com/hashicorp/serf v0.8.1/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE=
-github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/json-iterator/go v0.0.0-20180315132816-ca39e5af3ece h1:3HJXp/18JmMk5sjBP3LDUBtWjczCvynxaeAF6b6kWp8=
-github.com/json-iterator/go v0.0.0-20180315132816-ca39e5af3ece/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
@@ -134,9 +120,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180228065516-1df9eeb2bb81 h1:ImOHKpmdLPXWX5KSYquUWXKaopEPuY7TPPUo18u9aOI=
github.com/modern-go/reflect2 v0.0.0-20180228065516-1df9eeb2bb81/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/mongodb/mongo-go-driver v0.2.0 h1:MBI/hnb0LiACJRVAlT+nL5wdtV4EFKTjJEhQdapZFB0=
-github.com/mongodb/mongo-go-driver v0.2.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU=
-github.com/mongodb/mongo-go-driver v1.0.0 h1:aq055NT+Xu6ta/f7D51gIbLHIZwM0Gwzt9RHfmrzs6A=
github.com/mongodb/mongo-go-driver v1.0.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -146,7 +129,6 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-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.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
@@ -158,39 +140,28 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nL
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
-github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245 h1:DNVk+NIkGS0RbLkjQOLCJb/759yfCysThkMbl7EXxyY=
github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245/go.mod h1:O1c8HleITsZqzNZDjSNzirUGsMT0oGu9LhHKoJrqO+A=
-github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51 h1:BP2bjP495BBPaBcS5rmqviTfrOkN5rO5ceKAMRZCRFc=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
-go.etcd.io/etcd v3.3.12+incompatible h1:xR2YQOYo5JV5BMrUj9i1kcf2rEbpCQKHH2sKTtpAHiQ=
+go.etcd.io/etcd v3.3.12+incompatible h1:V6PRYRGpU4k5EajJaaj/GL3hqIdzyPnBU8aPUp+35yw=
go.etcd.io/etcd v3.3.12+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
go.mongodb.org/mongo-driver v1.0.0 h1:KxPRDyfB2xXnDE2My8acoOWBQkfv3tz0SaWTRZjJR0c=
go.mongodb.org/mongo-driver v1.0.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
-golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4 h1:wviDUSmtheHRBfoY8B9U8ELl2USoXi2YFwdGdpIIkzI=
-golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225 h1:kNX+jCowfMYzvlSvJu5pQWEmyWFrBXJ3PBy10xKMXK8=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
@@ -201,9 +172,6 @@ golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180611080425-bff228c7b664 h1:GvcVmbE8Pa64iW3MTrVA9mxHx1HEjSSWV6zF1JSlFcg=
-golang.org/x/sys v0.0.0-20180611080425-bff228c7b664/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -212,13 +180,11 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@@ -227,55 +193,25 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.0.0-20180607235014-72d6e4405f81 h1:OTYaNzRYUjk5sXxfClCTJnBBDAxI43KuldJtfjxx2fE=
-k8s.io/api v0.0.0-20180607235014-72d6e4405f81/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/api v0.0.0-20181126151915-b503174bad59 h1:uXjIvSvNtNUQjqpBznXm29/Ntx/6Aezf/wa0yAFryWE=
k8s.io/api v0.0.0-20181126151915-b503174bad59/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
-k8s.io/api v0.0.0-20181130031204-d04500c8c3dd h1:5aHsneN62ehs/tdtS9tWZlhVk68V7yms/Qw7nsGmvCA=
-k8s.io/api v0.0.0-20181130031204-d04500c8c3dd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
-k8s.io/api v0.0.0-20181221193117-173ce66c1e39 h1:iGq7zEPXFb0IeXAQK5RiYT1SVKX/af9F9Wv0M+yudPY=
-k8s.io/api v0.0.0-20181221193117-173ce66c1e39/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/apiextensions-apiserver v0.0.0-20181126155829-0cd23ebeb688 h1:sadcWnjCmaJ/cYN8FpBylEjmjskFHLvjbC3MnkhCGIA=
k8s.io/apiextensions-apiserver v0.0.0-20181126155829-0cd23ebeb688/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
-k8s.io/apiextensions-apiserver v0.0.0-20190103235604-e7617803aceb h1:3yElwSbnV34qIVTlGgkbWwWM+wq7fw6i7EKRtLV6z58=
-k8s.io/apiextensions-apiserver v0.0.0-20190103235604-e7617803aceb/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
-k8s.io/apimachinery v0.0.0-20180515182440-31dade610c05 h1:IxbzCht0hGNBVprna3ou1lB+jvFGT2Sh83htT2jL4sk=
-k8s.io/apimachinery v0.0.0-20180515182440-31dade610c05/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674 h1:S3ImTLK1F6igG0/5Tx8hf08XMRSwxhPfgtCLjs0Q8q4=
k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
-k8s.io/apimachinery v0.0.0-20181215012845-4d029f033399 h1:xdXaRQ7uNX4x6NpvxXASvlVXtKa8+WbCXK7Hjr6XZ6c=
-k8s.io/apimachinery v0.0.0-20181215012845-4d029f033399/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
-k8s.io/apimachinery v0.0.0-20190104073114-849b284f3b75 h1:dLhsGWh58R0WYgTCX6ZdaqSz2FltMZsk+ByHsUgMWRU=
-k8s.io/apimachinery v0.0.0-20190104073114-849b284f3b75/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apiserver v0.0.0-20181126153457-92fdef3a232a h1:+GApCkYtoBEjQZC8bariB5dM4Xa4MmmKId5dLV3AODQ=
k8s.io/apiserver v0.0.0-20181126153457-92fdef3a232a/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w=
-k8s.io/apiserver v0.0.0-20190107233756-bcc52745160f h1:k2l9d/byRk1Tpjgx9Pu5qqiZFWiaY5CipqlMmB1zVd8=
-k8s.io/apiserver v0.0.0-20190107233756-bcc52745160f/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w=
k8s.io/cli-runtime v0.0.0-20190107235426-31214e12222d h1:hdarETxu5sE+zfQ8CPfvWbQzMe1yaJA1XvURyx1u514=
k8s.io/cli-runtime v0.0.0-20190107235426-31214e12222d/go.mod h1:qWnH3/b8sp/l7EvlDh7ulDU3UWA4P4N1NFbEEP791tM=
-k8s.io/client-go v2.0.0-alpha.0.0.20181126152608-d082d5923d3c+incompatible h1:+gASq5lVUhelbDuyHr/ojUKGLZVeUhAFKHbAK8Kymfs=
+k8s.io/client-go v2.0.0-alpha.0.0.20181126152608-d082d5923d3c+incompatible h1:QOMBR2qlbwRbUJbJDXFjS8YEiXQc3AJBcEac7z3769I=
k8s.io/client-go v2.0.0-alpha.0.0.20181126152608-d082d5923d3c+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v7.0.0+incompatible h1:gokIETH5yPpln/LuXmg1TLVH5bMSaVQTVxuRizwjWwU=
-k8s.io/client-go v7.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v9.0.0+incompatible h1:/PdJjifJTjMFe0G4ESclZDcwF1+bFePTJ2xf+MXjcvs=
-k8s.io/client-go v9.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v10.0.0+incompatible h1:h3fciHPG0O5QEzATTFoRw/YGtDsU6pxrMrAhxiTtcq0=
-k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v11.0.0+incompatible h1:X3ykd+Z4G8MojP9TVDOR+h/IrpYJEolfR8W2B/FGKrk=
-k8s.io/helm v2.12.1+incompatible h1:Fw6it7ALJfqbbX95U3is3aswD6E8nh4aUYtvgzfna8A=
-k8s.io/helm v2.12.1+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI=
-k8s.io/helm v2.12.2+incompatible h1:vtddbkiGNMOd8maDDZDc111Rm9E5JeeNWDndows18i8=
+k8s.io/helm v2.12.2+incompatible h1:xSDfcFN8X6lfMKWQB1GmU18pnzIthU+/c7kkcl8Xlb0=
k8s.io/helm v2.12.2+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI=
-k8s.io/klog v0.1.0 h1:I5HMfc/DtuVaGR1KPwUrTc476K8NCqNBldC7H4dYEzk=
k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/kube-openapi v0.0.0-20181114233023-0317810137be h1:aWEq4nbj7HRJ0mtKYjNSk/7X28Tl6TI6FeG8gKF+r7Q=
k8s.io/kube-openapi v0.0.0-20181114233023-0317810137be/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
-k8s.io/kubernetes v1.12.3 h1:LgVHLYuVlSgzMhn0ZRUZBLe2O7MKuJEplLth4s5jPtg=
+k8s.io/kubernetes v1.12.3 h1:5GPfYyyBylqcZUqL+ApYpYTm2IYjH56JUewYC0GbetU=
k8s.io/kubernetes v1.12.3/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
-k8s.io/kubernetes v1.13.1 h1:hkqyN83WwEjOwJmdVURGT5CP+2oOQ3OV0Dj3LUCs7u8=
-k8s.io/kubernetes v1.13.1/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
-k8s.io/utils v0.0.0-20181102055113-1bd4f387aa67 h1:+kBMW7D4cSYIhPz0fVs6NRp5QILMz6+65ec4kWJOoXs=
-k8s.io/utils v0.0.0-20181102055113-1bd4f387aa67/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
k8s.io/utils v0.0.0-20181221173059-8a16e7dd8fb6 h1:+jRzzMyx+I9J18BvwHYmZ5hpPwoZfh6g39WfNlsMCkY=
k8s.io/utils v0.0.0-20181221173059-8a16e7dd8fb6/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk=
diff --git a/src/k8splugin/internal/app/client.go b/src/k8splugin/internal/app/client.go
index 7024420c..158d21de 100644
--- a/src/k8splugin/internal/app/client.go
+++ b/src/k8splugin/internal/app/client.go
@@ -19,6 +19,8 @@ import (
"strings"
utils "k8splugin/internal"
+ "k8splugin/internal/config"
+ "k8splugin/internal/connection"
"k8splugin/internal/helm"
pkgerrors "github.com/pkg/errors"
@@ -43,12 +45,32 @@ type KubernetesClient struct {
restMapper meta.RESTMapper
}
-// GetKubeClient loads the Kubernetes configuation values stored into the local configuration file
-func (k *KubernetesClient) init(configPath string) error {
- if configPath == "" {
- return pkgerrors.New("config not passed and is not found in ~/.kube. ")
+// 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) {
+ conn := connection.NewConnectionClient()
+ kubeConfigPath, err := conn.Download(cloudregion, config.GetConfiguration().KubeConfigDir)
+ if err != nil {
+ return "", pkgerrors.Wrap(err, "Downloading kubeconfig")
+ }
+
+ return kubeConfigPath, nil
+}
+
+// init loads the Kubernetes configuation values stored into the local configuration file
+func (k *KubernetesClient) init(cloudregion string) error {
+ if cloudregion == "" {
+ return pkgerrors.New("Cloudregion is empty")
}
+ configPath, err := k.getKubeConfig(cloudregion)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Get kubeconfig file")
+ }
+
+ //Remove kubeconfigfile after the clients are created
+ defer os.Remove(configPath)
+
config, err := clientcmd.BuildConfigFromFlags("", configPath)
if err != nil {
return pkgerrors.Wrap(err, "setConfig: Build config from flags raised an error")
diff --git a/src/k8splugin/internal/app/client_test.go b/src/k8splugin/internal/app/client_test.go
index 4cc533e2..4bfbcb18 100644
--- a/src/k8splugin/internal/app/client_test.go
+++ b/src/k8splugin/internal/app/client_test.go
@@ -14,12 +14,16 @@ limitations under the License.
package app
import (
+ "encoding/base64"
+ "io/ioutil"
"os"
"plugin"
"reflect"
"testing"
utils "k8splugin/internal"
+ "k8splugin/internal/connection"
+ "k8splugin/internal/db"
"k8splugin/internal/helm"
pkgerrors "github.com/pkg/errors"
@@ -46,9 +50,29 @@ func LoadMockPlugins(krdLoadedPlugins map[string]*plugin.Plugin) error {
func TestInit(t *testing.T) {
t.Run("Successfully create Kube Client", func(t *testing.T) {
+ // Load the mock kube config file into memory
+ fd, err := ioutil.ReadFile("../../mock_files/mock_configs/mock_kube_config")
+ if err != nil {
+ t.Fatal("Unable to read mock_kube_config")
+ }
+
+ fdbase64 := base64.StdEncoding.EncodeToString(fd)
+
+ // Create mock db with connectivity information in it
+ db.DBconn = &db.MockDB{
+ Items: map[string]map[string][]byte{
+ connection.ConnectionKey{CloudRegion: "mock_connection"}.String(): {
+ "metadata": []byte(
+ "{\"cloud-region\":\"mock_connection\"," +
+ "\"cloud-owner\":\"mock_owner\"," +
+ "\"kubeconfig\": \"" + fdbase64 + "\"}"),
+ },
+ },
+ }
kubeClient := KubernetesClient{}
- err := kubeClient.init("../../mock_files/mock_configs/mock_kube_config")
+ // Refer to the connection via its name
+ err = kubeClient.init("mock_connection")
if err != nil {
t.Fatalf("TestGetKubeClient returned an error (%s)", err)
}
diff --git a/src/k8splugin/internal/app/instance.go b/src/k8splugin/internal/app/instance.go
index 8d289d85..6d0910d0 100644
--- a/src/k8splugin/internal/app/instance.go
+++ b/src/k8splugin/internal/app/instance.go
@@ -21,7 +21,6 @@ import (
"encoding/json"
"math/rand"
- "k8splugin/internal/config"
"k8splugin/internal/db"
"k8splugin/internal/helm"
"k8splugin/internal/rb"
@@ -120,7 +119,7 @@ func (v *InstanceClient) Create(i InstanceRequest) (InstanceResponse, error) {
}
k8sClient := KubernetesClient{}
- err = k8sClient.init(config.GetConfiguration().KubeConfigDir + "/" + i.CloudRegion)
+ err = k8sClient.init(i.CloudRegion)
if err != nil {
return InstanceResponse{}, pkgerrors.Wrap(err, "Getting CloudRegion Information")
}
@@ -185,7 +184,7 @@ func (v *InstanceClient) Delete(id string) error {
}
k8sClient := KubernetesClient{}
- err = k8sClient.init(config.GetConfiguration().KubeConfigDir + "/" + inst.CloudRegion)
+ err = k8sClient.init(inst.CloudRegion)
if err != nil {
return pkgerrors.Wrap(err, "Getting CloudRegion Information")
}
diff --git a/src/k8splugin/internal/app/instance_test.go b/src/k8splugin/internal/app/instance_test.go
index ab39dfb7..6ab14a34 100644
--- a/src/k8splugin/internal/app/instance_test.go
+++ b/src/k8splugin/internal/app/instance_test.go
@@ -14,12 +14,14 @@ limitations under the License.
package app
import (
+ "encoding/base64"
+ "io/ioutil"
"log"
"reflect"
"testing"
utils "k8splugin/internal"
- "k8splugin/internal/config"
+ "k8splugin/internal/connection"
"k8splugin/internal/db"
"k8splugin/internal/helm"
"k8splugin/internal/rb"
@@ -37,6 +39,12 @@ func TestInstanceCreate(t *testing.T) {
t.Fatalf("LoadMockPlugins returned an error (%s)", err)
}
+ // Load the mock kube config file into memory
+ fd, err := ioutil.ReadFile("../../mock_files/mock_configs/mock_kube_config")
+ if err != nil {
+ t.Fatal("Unable to read mock_kube_config")
+ }
+
t.Run("Successfully create Instance", func(t *testing.T) {
db.DBconn = &db.MockDB{
Items: map[string]map[string][]byte{
@@ -145,6 +153,12 @@ func TestInstanceCreate(t *testing.T) {
"RZQl9kOgrk+XoOzX68tJ3wYJb0N/RJ0NzPUr5y4YEDBw4cOHDgwIEDBw4cOHDgwIEDBw4" +
"cOHDgwIEDB18K/AcxEDJDAHgAAA=="),
},
+ connection.ConnectionKey{CloudRegion: "mock_connection"}.String(): {
+ "metadata": []byte(
+ "{\"cloud-region\":\"mock_connection\"," +
+ "\"cloud-owner\":\"mock_owner\"," +
+ "\"kubeconfig\": \"" + base64.StdEncoding.EncodeToString(fd) + "\"}"),
+ },
},
}
@@ -153,10 +167,9 @@ func TestInstanceCreate(t *testing.T) {
RBName: "test-rbdef",
RBVersion: "v1",
ProfileName: "profile1",
- CloudRegion: "mock_kube_config",
+ CloudRegion: "mock_connection",
}
- config.SetConfigValue("KubeConfigDir", "../../mock_files/mock_configs")
ir, err := ic.Create(input)
if err != nil {
t.Fatalf("TestInstanceCreate returned an error (%s)", err)
@@ -311,6 +324,12 @@ func TestInstanceDelete(t *testing.T) {
t.Fatalf("TestInstanceDelete returned an error (%s)", err)
}
+ // Load the mock kube config file into memory
+ fd, err := ioutil.ReadFile("../../mock_files/mock_configs/mock_kube_config")
+ if err != nil {
+ t.Fatal("Unable to read mock_kube_config")
+ }
+
t.Run("Successfully delete Instance", func(t *testing.T) {
db.DBconn = &db.MockDB{
Items: map[string]map[string][]byte{
@@ -322,7 +341,7 @@ func TestInstanceDelete(t *testing.T) {
"namespace":"testnamespace",
"rb-name":"test-rbdef",
"rb-version":"v1",
- "cloud-region":"mock_kube_config",
+ "cloud-region":"mock_connection",
"resources": [
{
"GVK": {
@@ -343,6 +362,12 @@ func TestInstanceDelete(t *testing.T) {
]
}`),
},
+ connection.ConnectionKey{CloudRegion: "mock_connection"}.String(): {
+ "metadata": []byte(
+ "{\"cloud-region\":\"mock_connection\"," +
+ "\"cloud-owner\":\"mock_owner\"," +
+ "\"kubeconfig\": \"" + base64.StdEncoding.EncodeToString(fd) + "\"}"),
+ },
},
}
diff --git a/src/k8splugin/internal/config/config.go b/src/k8splugin/internal/config/config.go
index c3ca9054..dc3f7a11 100644
--- a/src/k8splugin/internal/config/config.go
+++ b/src/k8splugin/internal/config/config.go
@@ -39,6 +39,7 @@ type Configuration struct {
EtcdCAFile string `json:"etcd-ca-file"`
KubeConfigDir string `json:"kube-config-dir"`
OVNCentralAddress string `json:"ovn-central-address"`
+ ServicePort string `json:"service-port"`
}
// Config is the structure that stores the configuration
@@ -87,6 +88,7 @@ func defaultConfiguration() *Configuration {
EtcdCAFile: "etcd-ca.cert",
KubeConfigDir: cwd,
OVNCentralAddress: "127.0.0.1",
+ ServicePort: "9015",
}
}
diff --git a/src/k8splugin/internal/connection/connection.go b/src/k8splugin/internal/connection/connection.go
index 3faa74bd..b2bdca32 100644
--- a/src/k8splugin/internal/connection/connection.go
+++ b/src/k8splugin/internal/connection/connection.go
@@ -17,7 +17,11 @@
package connection
import (
+ "encoding/base64"
"encoding/json"
+ "io/ioutil"
+ "path/filepath"
+
"k8splugin/internal/db"
pkgerrors "github.com/pkg/errors"
@@ -25,16 +29,15 @@ import (
// Connection contains the parameters needed for Connection information for a Cloud region
type Connection struct {
- ConnectionName string `json:"name"`
+ CloudRegion string `json:"cloud-region"`
CloudOwner string `json:"cloud-owner"`
- CloudRegionID string `json:"cloud-region-id"`
- Kubeconfig map[string]interface{} `json:"kubeconfig"`
+ Kubeconfig string `json:"kubeconfig"`
OtherConnectivityList map[string]interface{} `json:"other-connectivity-list"`
}
// ConnectionKey is the key structure that is used in the database
type ConnectionKey struct {
- ConnectionName string `json:"connection-name"`
+ CloudRegion string `json:"cloud-region"`
}
// We will use json marshalling to convert to string to
@@ -48,14 +51,14 @@ func (dk ConnectionKey) String() string {
return string(out)
}
-// ConnectionManager is an interface exposes the Connection functionality
+// ConnectionManager is an interface exposes the Connection functionality
type ConnectionManager interface {
Create(c Connection) (Connection, error)
Get(name string) (Connection, error)
Delete(name string) error
}
-// ConnectionClient implements the ConnectionManager
+// ConnectionClient implements the ConnectionManager
// It will also be used to maintain some localized state
type ConnectionClient struct {
storeName string
@@ -75,10 +78,10 @@ func NewConnectionClient() *ConnectionClient {
func (v *ConnectionClient) Create(c Connection) (Connection, error) {
//Construct composite key consisting of name
- key := ConnectionKey{ConnectionName: c.ConnectionName}
+ key := ConnectionKey{CloudRegion: c.CloudRegion}
//Check if this Connection already exists
- _, err := v.Get(c.ConnectionName)
+ _, err := v.Get(c.CloudRegion)
if err == nil {
return Connection{}, pkgerrors.New("Connection already exists")
}
@@ -95,7 +98,7 @@ func (v *ConnectionClient) Create(c Connection) (Connection, error) {
func (v *ConnectionClient) Get(name string) (Connection, error) {
//Construct the composite key to select the entry
- key := ConnectionKey{ConnectionName: name}
+ key := ConnectionKey{CloudRegion: name}
value, err := db.DBconn.Read(v.storeName, key, v.tagMeta)
if err != nil {
return Connection{}, pkgerrors.Wrap(err, "Get Connection")
@@ -114,14 +117,39 @@ func (v *ConnectionClient) Get(name string) (Connection, error) {
return Connection{}, pkgerrors.New("Error getting Connection")
}
-// Delete the Connection from database
+// Delete the Connection from database
func (v *ConnectionClient) Delete(name string) error {
//Construct the composite key to select the entry
- key := ConnectionKey{ConnectionName: name}
+ key := ConnectionKey{CloudRegion: name}
err := db.DBconn.Delete(v.storeName, key, v.tagMeta)
if err != nil {
return pkgerrors.Wrap(err, "Delete Connection")
}
return nil
}
+
+// Download the connection information onto a kubeconfig file
+// The file is named after the name of the connection and will
+// be placed in the provided parent directory
+func (v *ConnectionClient) Download(name string, parentdir string) (string, error) {
+
+ conn, err := v.Get(name)
+ if err != nil {
+ return "", pkgerrors.Wrap(err, "Getting Connection info")
+ }
+
+ //Decode the kubeconfig from base64 to string
+ kubeContent, err := base64.StdEncoding.DecodeString(conn.Kubeconfig)
+ if err != nil {
+ return "", pkgerrors.Wrap(err, "Converting from base64")
+ }
+
+ target := filepath.Join(parentdir, conn.CloudRegion)
+ err = ioutil.WriteFile(target, kubeContent, 0644)
+ if err != nil {
+ return "", pkgerrors.Wrap(err, "Writing kubeconfig to file")
+ }
+
+ return target, nil
+}
diff --git a/src/k8splugin/internal/connection/connectionhandler.go b/src/k8splugin/internal/connection/connectionhandler.go
index ddb43f57..8c860d31 100644
--- a/src/k8splugin/internal/connection/connectionhandler.go
+++ b/src/k8splugin/internal/connection/connectionhandler.go
@@ -17,8 +17,11 @@
package connection
import (
+ "bytes"
+ "encoding/base64"
"encoding/json"
"io"
+ "io/ioutil"
"net/http"
"github.com/gorilla/mux"
@@ -32,11 +35,25 @@ type ConnectionHandler struct {
Client ConnectionManager
}
-// createHandler handles creation of the connectivity entry in the database
+// CreateHandler handles creation of the connectivity entry in the database
+// This is a multipart handler. See following example curl request
+// curl -i -F "metadata={\"cloud-region\":\"kud\",\"cloud-owner\":\"me\"};type=application/json" \
+// -F file=@/home/user/.kube/config \
+// -X POST http://localhost:8081/v1/connectivity-info
func (h ConnectionHandler) CreateHandler(w http.ResponseWriter, r *http.Request) {
var v Connection
- err := json.NewDecoder(r.Body).Decode(&v)
+ // Implemenation using multipart form
+ // Review and enable/remove at a later date
+ // Set Max size to 16mb here
+ err := r.ParseMultipartForm(16777216)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+ return
+ }
+
+ jsn := bytes.NewBuffer([]byte(r.FormValue("metadata")))
+ err = json.NewDecoder(jsn).Decode(&v)
switch {
case err == io.EOF:
http.Error(w, "Empty body", http.StatusBadRequest)
@@ -47,7 +64,7 @@ func (h ConnectionHandler) CreateHandler(w http.ResponseWriter, r *http.Request)
}
// Name is required.
- if v.ConnectionName == "" {
+ if v.CloudRegion == "" {
http.Error(w, "Missing name in POST request", http.StatusBadRequest)
return
}
@@ -58,17 +75,24 @@ func (h ConnectionHandler) CreateHandler(w http.ResponseWriter, r *http.Request)
return
}
- // CloudRegionID is required.
- if v.CloudRegionID == "" {
- http.Error(w, "Missing CloudRegionID in POST request", http.StatusBadRequest)
+ //Read the file section and ignore the header
+ file, _, err := r.FormFile("file")
+ if err != nil {
+ http.Error(w, "Unable to process file", http.StatusUnprocessableEntity)
return
}
- // CloudRegionID is required.
- if v.Kubeconfig == nil {
- http.Error(w, "Missing Kubeconfig in POST request", http.StatusBadRequest)
+ defer file.Close()
+
+ //Convert the file content to base64 for storage
+ content, err := ioutil.ReadAll(file)
+ if err != nil {
+ http.Error(w, "Unable to read file", http.StatusUnprocessableEntity)
return
}
+
+ v.Kubeconfig = base64.StdEncoding.EncodeToString(content)
+
ret, err := h.Client.Create(v)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
diff --git a/src/k8splugin/internal/db/testing.go b/src/k8splugin/internal/db/testing.go
index 1fefd63c..5f69dcb4 100644
--- a/src/k8splugin/internal/db/testing.go
+++ b/src/k8splugin/internal/db/testing.go
@@ -35,6 +35,10 @@ type MockDB struct {
Err error
}
+func (m *MockDB) HealthCheck() error {
+ return m.Err
+}
+
func (m *MockDB) Create(table string, key Key, tag string, data interface{}) error {
return m.Err
}
diff --git a/src/k8splugin/internal/utils.go b/src/k8splugin/internal/utils.go
index 7785733d..681b1b52 100644
--- a/src/k8splugin/internal/utils.go
+++ b/src/k8splugin/internal/utils.go
@@ -42,7 +42,7 @@ type ResourceData struct {
}
// DecodeYAML reads a YAMl file to extract the Kubernetes object definition
-var DecodeYAML = func(path string, into runtime.Object) (runtime.Object, error) {
+func DecodeYAML(path string, into runtime.Object) (runtime.Object, error) {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return nil, pkgerrors.New("File " + path + " not found")
diff --git a/src/k8splugin/plugins/deployment/plugin.go b/src/k8splugin/plugins/deployment/plugin.go
deleted file mode 100644
index 7ac31753..00000000
--- a/src/k8splugin/plugins/deployment/plugin.go
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-Copyright 2018 Intel Corporation.
-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
- http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
- "log"
-
- pkgerrors "github.com/pkg/errors"
-
- appsV1 "k8s.io/api/apps/v1"
- metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/client-go/kubernetes"
-
- utils "k8splugin/internal"
-)
-
-// Create deployment object in a specific Kubernetes cluster
-func Create(data *utils.ResourceData, client kubernetes.Interface) (string, error) {
- namespace := data.Namespace
- if namespace == "" {
- namespace = "default"
- }
- obj, err := utils.DecodeYAML(data.YamlFilePath, nil)
- if err != nil {
- return "", pkgerrors.Wrap(err, "Decode deployment object error")
- }
-
- deployment, ok := obj.(*appsV1.Deployment)
- if !ok {
- return "", pkgerrors.New("Decoded object contains another resource different than Deployment")
- }
- deployment.Namespace = namespace
- result, err := client.AppsV1().Deployments(namespace).Create(deployment)
- if err != nil {
- return "", pkgerrors.Wrap(err, "Create Deployment error")
- }
-
- return result.GetObjectMeta().GetName(), nil
-}
-
-// List of existing deployments hosted in a specific Kubernetes cluster
-func List(namespace string, kubeclient kubernetes.Interface) ([]string, error) {
- if namespace == "" {
- namespace = "default"
- }
-
- opts := metaV1.ListOptions{
- Limit: utils.ResourcesListLimit,
- }
- opts.APIVersion = "apps/v1"
- opts.Kind = "Deployment"
-
- list, err := kubeclient.AppsV1().Deployments(namespace).List(opts)
- if err != nil {
- return nil, pkgerrors.Wrap(err, "Get Deployment list error")
- }
-
- result := make([]string, 0, utils.ResourcesListLimit)
- if list != nil {
- for _, deployment := range list.Items {
- log.Printf("%v", deployment.Name)
- result = append(result, deployment.Name)
- }
- }
-
- return result, nil
-}
-
-// Delete an existing deployment hosted in a specific Kubernetes cluster
-func Delete(name string, namespace string, kubeclient kubernetes.Interface) error {
- if namespace == "" {
- namespace = "default"
- }
-
- deletePolicy := metaV1.DeletePropagationForeground
- opts := &metaV1.DeleteOptions{
- PropagationPolicy: &deletePolicy,
- }
-
- log.Println("Deleting deployment: " + name)
- if err := kubeclient.AppsV1().Deployments(namespace).Delete(name, opts); err != nil {
- return pkgerrors.Wrap(err, "Delete Deployment error")
- }
-
- return nil
-}
-
-// Get an existing deployment hosted in a specific Kubernetes cluster
-func Get(name string, namespace string, kubeclient kubernetes.Interface) (string, error) {
- if namespace == "" {
- namespace = "default"
- }
-
- opts := metaV1.GetOptions{}
- opts.APIVersion = "apps/v1"
- opts.Kind = "Deployment"
-
- deployment, err := kubeclient.AppsV1().Deployments(namespace).Get(name, opts)
- if err != nil {
- return "", pkgerrors.Wrap(err, "Get Deployment error")
- }
-
- return deployment.Name, nil
-}
diff --git a/src/k8splugin/plugins/deployment/plugin_test.go b/src/k8splugin/plugins/deployment/plugin_test.go
deleted file mode 100644
index 446f3329..00000000
--- a/src/k8splugin/plugins/deployment/plugin_test.go
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
-Copyright 2018 Intel Corporation.
-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
- http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
- "reflect"
- "strings"
- "testing"
-
- utils "k8splugin/internal"
-
- appsV1 "k8s.io/api/apps/v1"
- metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- testclient "k8s.io/client-go/kubernetes/fake"
-)
-
-func TestCreateDeployment(t *testing.T) {
- namespace := "test1"
- name := "mock-deployment"
- testCases := []struct {
- label string
- input *utils.ResourceData
- clientOutput *appsV1.Deployment
- expectedResult string
- expectedError string
- }{
- {
- label: "Fail to create a deployment with invalid type",
- input: &utils.ResourceData{
- YamlFilePath: "../../mock_files/mock_yamls/service.yaml",
- },
- clientOutput: &appsV1.Deployment{},
- expectedError: "contains another resource different than Deployment",
- },
- {
- label: "Successfully create a deployment",
- input: &utils.ResourceData{
- YamlFilePath: "../../mock_files/mock_yamls/deployment.yaml",
- },
- clientOutput: &appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: name,
- Namespace: namespace,
- },
- },
- expectedResult: name,
- },
- }
-
- for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
- t.Run(testCase.label, func(t *testing.T) {
- result, err := Create(testCase.input, client)
- if err != nil {
- if testCase.expectedError == "" {
- t.Fatalf("Create method return an un-expected (%s)", err)
- }
- if !strings.Contains(string(err.Error()), testCase.expectedError) {
- t.Fatalf("Create method returned an error (%s)", err)
- }
- } else {
- if testCase.expectedError != "" && testCase.expectedResult == "" {
- t.Fatalf("Create method was expecting \"%s\" error message", testCase.expectedError)
- }
- if result == "" {
- t.Fatal("Create method returned nil result")
- }
- if !reflect.DeepEqual(testCase.expectedResult, result) {
-
- t.Fatalf("Create method returned: \n%v\n and it was expected: \n%v", result, testCase.expectedResult)
- }
- }
- })
- }
-}
-
-func TestListDeployment(t *testing.T) {
- namespace := "test"
- testCases := []struct {
- label string
- input string
- clientOutput *appsV1.DeploymentList
- expectedResult []string
- }{
- {
- label: "Sucessfully display an empty deployment list",
- input: namespace,
- clientOutput: &appsV1.DeploymentList{},
- expectedResult: []string{},
- },
- {
- label: "Sucessfully display a list of existing deployments",
- input: namespace,
- clientOutput: &appsV1.DeploymentList{
- Items: []appsV1.Deployment{
- appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test",
- Namespace: namespace,
- },
- },
- },
- },
- expectedResult: []string{"test"},
- },
- {
- label: "Sucessfully display a list of existing deployments in default namespace",
- input: "",
- clientOutput: &appsV1.DeploymentList{
- Items: []appsV1.Deployment{
- appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test",
- Namespace: "default",
- },
- },
- appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test2",
- Namespace: namespace,
- },
- },
- },
- },
- expectedResult: []string{"test"},
- },
- }
-
- for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
- t.Run(testCase.label, func(t *testing.T) {
- result, err := List(testCase.input, client)
- if err != nil {
- t.Fatalf("List method returned an error (%s)", err)
- } else {
- if result == nil {
- t.Fatal("List method returned nil result")
- }
- if !reflect.DeepEqual(testCase.expectedResult, result) {
-
- t.Fatalf("List method returned: \n%v\n and it was expected: \n%v", result, testCase.expectedResult)
- }
- }
- })
- }
-}
-
-func TestDeleteDeployment(t *testing.T) {
- testCases := []struct {
- label string
- input map[string]string
- clientOutput *appsV1.Deployment
- }{
- {
- label: "Sucessfully delete an existing deployment",
- input: map[string]string{"name": "test-deployment", "namespace": "test-namespace"},
- clientOutput: &appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test-deployment",
- Namespace: "test-namespace",
- },
- },
- },
- {
- label: "Sucessfully delete an existing deployment in default namespace",
- input: map[string]string{"name": "test-deployment", "namespace": ""},
- clientOutput: &appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test-deployment",
- Namespace: "default",
- },
- },
- },
- }
-
- for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
- t.Run(testCase.label, func(t *testing.T) {
- err := Delete(testCase.input["name"], testCase.input["namespace"], client)
- if err != nil {
- t.Fatalf("Delete method returned an error (%s)", err)
- }
- })
- }
-}
-
-func TestGetDeployment(t *testing.T) {
- testCases := []struct {
- label string
- input map[string]string
- clientOutput *appsV1.Deployment
- expectedResult string
- expectedError string
- }{
- {
- label: "Sucessfully get an existing deployment",
- input: map[string]string{"name": "test-deployment", "namespace": "test-namespace"},
- clientOutput: &appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test-deployment",
- Namespace: "test-namespace",
- },
- },
- expectedResult: "test-deployment",
- },
- {
- label: "Sucessfully get an existing deployment from default namespaces",
- input: map[string]string{"name": "test-deployment", "namespace": ""},
- clientOutput: &appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test-deployment",
- Namespace: "default",
- },
- },
- expectedResult: "test-deployment",
- },
- {
- label: "Fail to get an non-existing namespace",
- input: map[string]string{"name": "test-name", "namespace": "test-namespace"},
- clientOutput: &appsV1.Deployment{
- ObjectMeta: metaV1.ObjectMeta{
- Name: "test-deployment",
- Namespace: "default",
- },
- },
- expectedError: "not found",
- },
- }
-
- for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
- t.Run(testCase.label, func(t *testing.T) {
- result, err := Get(testCase.input["name"], testCase.input["namespace"], client)
- if err != nil {
- if testCase.expectedError == "" {
- t.Fatalf("Get method return an un-expected (%s)", err)
- }
- if !strings.Contains(string(err.Error()), testCase.expectedError) {
- t.Fatalf("Get method returned an error (%s)", err)
- }
- } else {
- if testCase.expectedError != "" && testCase.expectedResult == "" {
- t.Fatalf("Get method was expecting \"%s\" error message", testCase.expectedError)
- }
- if result == "" {
- t.Fatal("Get method returned nil result")
- }
- if !reflect.DeepEqual(testCase.expectedResult, result) {
-
- t.Fatalf("Get method returned: \n%v\n and it was expected: \n%v", result, testCase.expectedResult)
- }
- }
- })
- }
-}
diff --git a/src/k8splugin/plugins/generic/plugin.go b/src/k8splugin/plugins/generic/plugin.go
index f3b2798a..9ecaf68c 100644
--- a/src/k8splugin/plugins/generic/plugin.go
+++ b/src/k8splugin/plugins/generic/plugin.go
@@ -21,7 +21,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
- "k8s.io/client-go/kubernetes/scheme"
utils "k8splugin/internal"
"k8splugin/internal/app"
@@ -38,16 +37,11 @@ func (g genericPlugin) Create(yamlFilePath string, namespace string, client *app
}
//Decode the yaml file to create a runtime.Object
- obj, err := utils.DecodeYAML(yamlFilePath, nil)
- if err != nil {
- return "", pkgerrors.Wrap(err, "Decode deployment object error")
- }
-
- //Convert the runtime.Object to an unstructured Object
unstruct := &unstructured.Unstructured{}
- err = scheme.Scheme.Convert(obj, unstruct, nil)
+ //Ignore the returned obj as we expect the data in unstruct
+ _, err := utils.DecodeYAML(yamlFilePath, unstruct)
if err != nil {
- return "", pkgerrors.Wrap(err, "Converting to unstructured object")
+ return "", pkgerrors.Wrap(err, "Decode deployment object error")
}
dynClient := client.GetDynamicClient()