summaryrefslogtreecommitdiffstats
path: root/src/k8splugin/internal/connection/connection.go
blob: b2bdca3299ca8cb878ad2e5afbc734bc5eda0dfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * 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 connection

import (
	"encoding/base64"
	"encoding/json"
	"io/ioutil"
	"path/filepath"

	"k8splugin/internal/db"

	pkgerrors "github.com/pkg/errors"
)

// Connection contains the parameters needed for Connection information for a Cloud region
type Connection struct {
	CloudRegion           string                 `json:"cloud-region"`
	CloudOwner            string                 `json:"cloud-owner"`
	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 {
	CloudRegion string `json:"cloud-region"`
}

// We will use json marshalling to convert to string to
// preserve the underlying structure.
func (dk ConnectionKey) String() string {
	out, err := json.Marshal(dk)
	if err != nil {
		return ""
	}

	return string(out)
}

// 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
// It will also be used to maintain some localized state
type ConnectionClient struct {
	storeName string
	tagMeta   string
}

// New ConnectionClient returns an instance of the  ConnectionClient
// which implements the  ConnectionManager
func NewConnectionClient() *ConnectionClient {
	return &ConnectionClient{
		storeName: "connection",
		tagMeta:   "metadata",
	}
}

// Create an entry for the Connection resource in the database`
func (v *ConnectionClient) Create(c Connection) (Connection, error) {

	//Construct composite key consisting of name
	key := ConnectionKey{CloudRegion: c.CloudRegion}

	//Check if this Connection already exists
	_, err := v.Get(c.CloudRegion)
	if err == nil {
		return Connection{}, pkgerrors.New("Connection already exists")
	}

	err = db.DBconn.Create(v.storeName, key, v.tagMeta, c)
	if err != nil {
		return Connection{}, pkgerrors.Wrap(err, "Creating DB Entry")
	}

	return c, nil
}

// Get returns Connection for corresponding to name
func (v *ConnectionClient) Get(name string) (Connection, error) {

	//Construct the composite key to select the entry
	key := ConnectionKey{CloudRegion: name}
	value, err := db.DBconn.Read(v.storeName, key, v.tagMeta)
	if err != nil {
		return Connection{}, pkgerrors.Wrap(err, "Get Connection")
	}

	//value is a byte array
	if value != nil {
		c := Connection{}
		err = db.DBconn.Unmarshal(value, &c)
		if err != nil {
			return Connection{}, pkgerrors.Wrap(err, "Unmarshaling Value")
		}
		return c, nil
	}

	return Connection{}, pkgerrors.New("Error getting Connection")
}

// Delete the Connection from database
func (v *ConnectionClient) Delete(name string) error {

	//Construct the composite key to select the entry
	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
}