From 1d949fb44639e0c1316ccf87b447b4f318e2126a Mon Sep 17 00:00:00 2001
From: Ankit R Gadiya <git@argp.in>
Date: Sun, 29 Sep 2019 23:49:59 +0530
Subject: [PATCH] feat(secret): added generate function for secret

---
 go.sum               |  1 +
 pkg/secret/secret.go | 65 ++++++++++++++++++++++++++++++++++++++++++++
 pkg/secret/utils.go  | 22 +++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 pkg/secret/secret.go
 create mode 100644 pkg/secret/utils.go

diff --git a/go.sum b/go.sum
index 28728e8..c387abc 100644
--- a/go.sum
+++ b/go.sum
@@ -116,6 +116,7 @@ k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8 h1:q1Qvjzs/iEd
 k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
 k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA=
 k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
+k8s.io/apimachinery v0.0.0-20190927035529-0104e33c351d h1:oYLB5Nk2IOm17BHdatnaWAgzNGzq/5dlWy7Bzo5Htdc=
 k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible h1:U5Bt+dab9K8qaUmXINrkXO135kA11/i5Kg1RUydgaMQ=
 k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
 k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go
new file mode 100644
index 0000000..33310d0
--- /dev/null
+++ b/pkg/secret/secret.go
@@ -0,0 +1,65 @@
+package secret
+
+import (
+	"github.com/ankitrgadiya/operatorlib/pkg/meta"
+
+	"github.com/pkg/errors"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// GenerateSecret generates Secret object as per the `Conf` struct
+// passed. However, this does one special thing while generating
+// Secret. StringData is merged into Data because of how Secrets are
+// handled by Kubernetes. API Server never returns StringData field
+// and converts it into Data. One might thing that is fine since API
+// Server is already doing the conversion but the way this library
+// manages Update will break if the generated object, Secret do not
+// match the one in cluster. Merging the StringData ensures that if no
+// genuine change is made then generated Secret will match the one in
+// cluster.
+func GenerateSecret(c Conf) (s *corev1.Secret, err error) {
+	var om *metav1.ObjectMeta
+	var data map[string][]byte
+	var stringData map[string]string
+
+	om, err = meta.GenerateObjectMeta(meta.Conf{
+		Instance:           c.Instance,
+		Name:               c.Name,
+		Namespace:          c.Namespace,
+		GenLabelsFunc:      c.GenLabelsFunc,
+		GenAnnotationsFunc: c.GenAnnotationsFunc,
+		GenFinalizersFunc:  c.GenFinalizersFunc,
+		AppendLabels:       c.AppendLabels,
+	})
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to generate objectmeta")
+	}
+
+	if c.GenDataFunc != nil {
+		data, err = c.GenDataFunc(c.Instance)
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to generate data")
+		}
+	}
+
+	if c.GenStringDataFunc != nil {
+		stringData, err = c.GenStringDataFunc(c.Instance)
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to generate string data")
+		}
+	}
+
+	err = mergeData(data, stringData)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to merge string data and data")
+	}
+
+	s = &corev1.Secret{
+		ObjectMeta: *om,
+		Data:       data,
+		StringData: stringData,
+		Type:       corev1.SecretType(c.Type),
+	}
+	return s, nil
+}
diff --git a/pkg/secret/utils.go b/pkg/secret/utils.go
new file mode 100644
index 0000000..0e949ce
--- /dev/null
+++ b/pkg/secret/utils.go
@@ -0,0 +1,22 @@
+package secret
+
+import (
+	"github.com/imdario/mergo"
+)
+
+// mergeData utility function merges data and stringData. It does not
+// override the alreadyexisting keys in data and only append the keys
+// from stringData
+func mergeData(data map[string][]byte, stringData map[string]string) error {
+	newData := make(map[string][]byte, len(stringData))
+	for key, value := range stringData {
+		newData[key] = []byte(value)
+	}
+
+	err := mergo.Merge(data, newData)
+	if err != nil {
+		return nil
+	}
+
+	return nil
+}
-- 
GitLab