Files
onepanel/kube/secret.go
2020-02-06 14:37:43 -08:00

188 lines
5.1 KiB
Go

package kube
import (
"encoding/base64"
"encoding/json"
goerrors "errors"
"github.com/onepanelio/core/model"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
func (c *Client) CreateSecret(namespace string, secret *model.Secret) (err error) {
_, err = c.CoreV1().Secrets(namespace).Create(&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secret.Name,
},
StringData: secret.Data,
})
return
}
func (c *Client) SecretExists(namespace string, secret *model.Secret) (*model.Secret, error) {
secretK8s, err := c.CoreV1().Secrets(namespace).Get(secret.Name, metav1.GetOptions{})
if err != nil {
return &model.Secret{}, err
}
retSecret := model.Secret{
Name: secretK8s.Name,
}
return &retSecret, nil
}
func (c *Client) GetSecret(namespace string, secret *model.Secret) (*model.Secret, error) {
foundSecret, err := c.CoreV1().Secrets(namespace).Get(secret.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if foundSecret != nil {
return &model.Secret{
Name: foundSecret.Name,
Data: convertSecretToMap(foundSecret),
}, nil
}
return nil, nil
}
func (c *Client) ListSecrets(namespace string) (secrets []*model.Secret, err error) {
secretsList, err := c.CoreV1().Secrets(namespace).List(metav1.ListOptions{})
if err != nil {
return
}
for _, secret := range secretsList.Items {
secretModel := model.Secret{
Name: secret.Name,
Data: convertSecretToMap(&secret),
}
secrets = append(secrets, &secretModel)
}
return
}
func (c *Client) DeleteSecret(namespace string, secret *model.Secret) (err error) {
return c.CoreV1().Secrets(namespace).Delete(secret.Name, &metav1.DeleteOptions{})
}
func (c *Client) DeleteSecretKey(namespace string, name string, key string) (deleted bool, err error) {
//Check if the secret has the key to delete
secretFound, secretFindErr := c.GetSecret(namespace, name)
if secretFindErr != nil {
return false, secretFindErr
}
secretDataKeyExists := false
for secretDataKey := range secretFound.Data {
if secretDataKey == key {
secretDataKeyExists = true
break
}
}
if secretDataKeyExists {
// patchStringPath specifies a patch operation for a secret key.
type patchStringPath struct {
Op string `json:"op"`
Path string `json:"path"`
}
payload := []patchStringPath{{
Op: "remove",
Path: "/data/" + key,
}}
payloadBytes, _ := json.Marshal(payload)
_, errSecret := c.CoreV1().Secrets(namespace).Patch(name, types.JSONPatchType, payloadBytes)
if errSecret != nil {
return false, errSecret
}
return true, nil
}
return true, nil
}
func (c *Client) AddSecretKeyValue(namespace string, name string, key string, value string) (inserted bool, err error) {
//Check if the secret has the key already
secretFound, secretFindErr := c.GetSecret(namespace, name)
if secretFindErr != nil {
return false, secretFindErr
}
if secretFound == nil {
return false, goerrors.New("Secret was not found.")
}
if len(secretFound.Data) > 0 {
secretDataKeyExists := false
for secretDataKey := range secretFound.Data {
if secretDataKey == key {
secretDataKeyExists = true
break
}
}
if secretDataKeyExists {
errorMsg := "Key: " + key + " already exists in secret."
return false, goerrors.New(errorMsg)
}
}
// patchStringPathAddNode specifies an add operation for a node
type patchStringPathAddNode struct {
Op string `json:"op"`
Path string `json:"path"`
Value map[string]string `json:"value"`
}
// "/data" may not exist due to 0 items. Create it so we can add an element.
if len(secretFound.Data) == 0 {
valMap := make(map[string]string)
valueEnc := base64.StdEncoding.EncodeToString([]byte(value))
valMap[key] = valueEnc
payloadAddNode := []patchStringPathAddNode{{
Op: "add",
Path: "/data",
Value: valMap,
}}
payloadAddNodeBytes, err := json.Marshal(payloadAddNode)
if err != nil {
return false, err
}
_, errSecret := c.CoreV1().Secrets(namespace).Patch(name, types.JSONPatchType, payloadAddNodeBytes)
if errSecret != nil {
return false, errSecret
}
return true, nil
}
// patchStringPathAddKeyValue specifies an add operation, a key and value
type patchStringPathAddKeyValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
valueEnc := base64.StdEncoding.EncodeToString([]byte(value))
payload := []patchStringPathAddKeyValue{{
Op: "add",
Path: "/data/" + key,
Value: valueEnc,
}}
payloadBytes, _ := json.Marshal(payload)
_, errSecret := c.CoreV1().Secrets(namespace).Patch(name, types.JSONPatchType, payloadBytes)
if errSecret != nil {
return false, errSecret
}
return true, nil
}
func (c *Client) UpdateSecretKeyValue(namespace string, name string, payloadBytes []byte) (err error) {
_, err = c.CoreV1().Secrets(namespace).Patch(name, types.JSONPatchType, payloadBytes)
return
}
func convertSecretToMap(foundSecret *corev1.Secret) (modelData map[string]string) {
modelData = make(map[string]string)
for secretKey, secretData := range foundSecret.Data {
modelData[secretKey] = string(secretData)
}
return modelData
}