Skip to content

Commit 1d7d2f6

Browse files
author
Cory Schwartz
authored
Merge pull request #77 from ipfs-cluster/fix/secret-creator
Fix/secret creator
2 parents f411983 + edf3ec6 commit 1d7d2f6

File tree

4 files changed

+136
-86
lines changed

4 files changed

+136
-86
lines changed

controllers/ipfscluster_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func (r *IpfsClusterReconciler) createTrackedObjects(
145145
mutsvc, svcName := r.serviceCluster(instance, &svc)
146146

147147
mutCmScripts, cmScriptName := r.ConfigMapScripts(ctx, instance, &cmScripts)
148-
mutSecConfig, secConfigName := r.secretConfig(ctx, instance, &secConfig, []byte(clusterSecret), []byte(privateString))
148+
mutSecConfig, secConfigName := r.SecretConfig(ctx, instance, &secConfig, []byte(clusterSecret), []byte(privateString))
149149
mutCmConfig, cmConfigName := r.configMapConfig(instance, &cmConfig, peerID.String())
150150
mutSts := r.statefulSet(instance, &sts, svcName, secConfigName, cmConfigName, cmScriptName)
151151

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package controllers_test
2+
3+
import (
4+
"context"
5+
"encoding/base64"
6+
"math/rand"
7+
8+
. "github.com/onsi/ginkgo/v2"
9+
. "github.com/onsi/gomega"
10+
v1 "k8s.io/api/core/v1"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
13+
"github.com/redhat-et/ipfs-operator/api/v1alpha1"
14+
"github.com/redhat-et/ipfs-operator/controllers"
15+
)
16+
17+
var _ = Describe("IPFS Reconciler", func() {
18+
var ipfsReconciler *controllers.IpfsClusterReconciler
19+
var ipfs *v1alpha1.IpfsCluster
20+
var configMapScripts *v1.ConfigMap
21+
var ctx context.Context
22+
const myName = "my-fav-ipfs-node"
23+
24+
BeforeEach(func() {
25+
ctx = context.TODO()
26+
ipfsReconciler = &controllers.IpfsClusterReconciler{
27+
Scheme: k8sClient.Scheme(),
28+
Client: k8sClient,
29+
}
30+
configMapScripts = &v1.ConfigMap{}
31+
ipfs = &v1alpha1.IpfsCluster{
32+
ObjectMeta: metav1.ObjectMeta{
33+
Name: myName,
34+
Namespace: "test",
35+
},
36+
}
37+
})
38+
39+
When("ConfigMapScripts are edited", func() {
40+
It("populates the ConfigMap", func() {
41+
// configMap is empty
42+
Expect(len(configMapScripts.Data)).To(Equal(0))
43+
fn, _ := ipfsReconciler.ConfigMapScripts(ctx, ipfs, configMapScripts)
44+
// should not have errored
45+
Expect(fn()).NotTo(HaveOccurred())
46+
// the configmap should be populated with the following scripts
47+
Expect(len(configMapScripts.Data)).To(Equal(2))
48+
49+
expectedKeys := []string{
50+
controllers.ScriptConfigureIPFS,
51+
controllers.ScriptIPFSClusterEntryPoint,
52+
}
53+
for _, key := range expectedKeys {
54+
data, ok := configMapScripts.Data[key]
55+
Expect(ok).To(BeTrue())
56+
Expect(data).NotTo(BeEmpty())
57+
}
58+
})
59+
60+
It("contains the IPFS resource name", func() {
61+
fn, name := ipfsReconciler.ConfigMapScripts(ctx, ipfs, configMapScripts)
62+
Expect(fn).NotTo(BeNil())
63+
Expect(fn()).NotTo(HaveOccurred())
64+
Expect(name).To(ContainSubstring(myName))
65+
Expect(name).To(Equal("ipfs-cluster-scripts-" + myName))
66+
})
67+
})
68+
69+
When("replicas are edited", func() {
70+
// we always expect there to be cluster secrets, which have two values
71+
const alwaysKeys = 2
72+
var (
73+
clusterSec = []byte("cluster secret")
74+
bootstrapKey = []byte("bootstrap private key")
75+
replicas int32
76+
)
77+
BeforeEach(func() {
78+
replicas = rand.Int31n(100)
79+
ipfs.Spec.Replicas = replicas
80+
})
81+
It("creates a new peer ids", func() {
82+
secretConfig := &v1.Secret{}
83+
fn, _ := ipfsReconciler.SecretConfig(ctx, ipfs, secretConfig, clusterSec, bootstrapKey)
84+
Expect(fn()).To(BeNil())
85+
secretStringToData(secretConfig)
86+
expectedKeys := int(replicas)*2 + alwaysKeys
87+
Expect(len(secretConfig.Data)).To(Equal(expectedKeys))
88+
89+
// increase the replica count. Expect to see new keys generated.
90+
ipfs.Spec.Replicas++
91+
fn, _ = ipfsReconciler.SecretConfig(ctx, ipfs, secretConfig, clusterSec, bootstrapKey)
92+
Expect(fn()).To(BeNil())
93+
secretStringToData(secretConfig)
94+
Expect(len(secretConfig.Data)).To(Equal(expectedKeys + 2))
95+
96+
})
97+
})
98+
})
99+
100+
// The k8s client will encode and copy data from the StringData to Data
101+
// This function mimics the behavior for tests.
102+
func secretStringToData(secret *v1.Secret) {
103+
for k, v := range secret.StringData {
104+
bv := []byte(v)
105+
enc := make([]byte, base64.StdEncoding.EncodedLen(len(bv)))
106+
base64.StdEncoding.Encode(enc, bv)
107+
secret.Data[k] = enc
108+
}
109+
secret.StringData = make(map[string]string)
110+
}

controllers/scripts_test.go

Lines changed: 0 additions & 65 deletions
This file was deleted.

controllers/secret.go

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func errorFunc(err error) controllerutil.MutateFn {
2828
}
2929
}
3030

31-
func (r *IpfsClusterReconciler) secretConfig(
31+
func (r *IpfsClusterReconciler) SecretConfig(
3232
ctx context.Context,
3333
m *clusterv1alpha1.IpfsCluster,
3434
sec *corev1.Secret,
@@ -45,32 +45,33 @@ func (r *IpfsClusterReconciler) secretConfig(
4545
}
4646
// find secret
4747
err := r.Get(ctx, client.ObjectKeyFromObject(expectedSecret), expectedSecret)
48-
if err != nil && !errors.IsNotFound(err) {
49-
return errorFunc(err), ""
50-
}
51-
// initialize the secret, if needed
52-
if err != nil && errors.IsNotFound(err) {
48+
if err != nil {
49+
// test for unhandled errors
50+
if !errors.IsNotFound(err) {
51+
return errorFunc(err), ""
52+
}
53+
// secret is not found.
54+
// initialize new secret
5355
expectedSecret.Data = make(map[string][]byte, 0)
54-
expectedSecret.StringData = make(map[string]string, 0)
55-
// secret doesn't exist
5656
err = generateNewIdentities(expectedSecret, 0, m.Spec.Replicas)
5757
if err != nil {
5858
return errorFunc(err), ""
5959
}
6060
expectedSecret.Data["CLUSTER_SECRET"] = clusterSecret
6161
expectedSecret.Data["BOOTSTRAP_PEER_PRIV_KEY"] = bootstrapPrivateKey
62-
}
63-
64-
// secret does exist
65-
numIdentities := countIdentities(expectedSecret)
66-
if numIdentities != m.Spec.Replicas {
67-
// create more identities if needed, otherwise they will be reused
68-
// when scaling down and then up again
69-
if numIdentities < m.Spec.Replicas {
70-
// create more
71-
err = generateNewIdentities(expectedSecret, numIdentities, m.Spec.Replicas)
72-
if err != nil {
73-
return errorFunc(err), ""
62+
} else {
63+
// secret exists.
64+
// test if we need to add more identieis
65+
numIdentities := countIdentities(expectedSecret)
66+
if numIdentities != m.Spec.Replicas {
67+
// create more identities if needed, otherwise they will be reused
68+
// when scaling down and then up again
69+
if numIdentities < m.Spec.Replicas {
70+
// create more
71+
err = generateNewIdentities(expectedSecret, numIdentities, m.Spec.Replicas)
72+
if err != nil {
73+
return errorFunc(err), ""
74+
}
7475
}
7576
}
7677
}
@@ -82,6 +83,7 @@ func (r *IpfsClusterReconciler) secretConfig(
8283
}
8384
return func() error {
8485
sec.Data = expectedSecret.Data
86+
sec.StringData = expectedSecret.StringData
8587
return nil
8688
}, secName
8789
}
@@ -100,6 +102,9 @@ func countIdentities(secret *corev1.Secret) int32 {
100102
// generateNewIdentities Populates the secret data with new Peer IDs
101103
// and private keys which are mapped based on the replica number.
102104
func generateNewIdentities(secret *corev1.Secret, start, n int32) error {
105+
if secret.StringData == nil {
106+
secret.StringData = make(map[string]string, 0)
107+
}
103108
for i := start; i < n; i++ {
104109
// generate new private key & peer id
105110
peerID, privKey, err := generateIdentity()

0 commit comments

Comments
 (0)