Skip to content

Commit

Permalink
style: add event for boot strap api
Browse files Browse the repository at this point in the history
Signed-off-by: Rory Z <[email protected]>
  • Loading branch information
Rory-Z committed Nov 8, 2023
1 parent f8421c7 commit aaa103c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 66 deletions.
114 changes: 56 additions & 58 deletions controllers/apps/v2beta1/add_bootstrap_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

appsv2beta1 "github.com/emqx/emqx-operator/apis/apps/v2beta1"
innerReq "github.com/emqx/emqx-operator/internal/requester"
Expand All @@ -23,9 +22,14 @@ type addBootstrap struct {
}

func (a *addBootstrap) reconcile(ctx context.Context, instance *appsv2beta1.EMQX, _ innerReq.RequesterInterface) subResult {
bootstrapAPIKeys, err := a.getAPIKeyString(ctx, instance)
if err != nil {
return subResult{err: emperror.Wrap(err, "failed to get bootstrap api keys")}
}

for _, resource := range []client.Object{
generateNodeCookieSecret(instance),
generateBootstrapAPIKeySecret(a.Client, ctx, instance),
generateBootstrapAPIKeySecret(instance, bootstrapAPIKeys),
} {
if err := ctrl.SetControllerReference(instance, resource, a.Scheme); err != nil {
return subResult{err: emperror.Wrap(err, "failed to set controller reference")}
Expand All @@ -40,79 +44,73 @@ func (a *addBootstrap) reconcile(ctx context.Context, instance *appsv2beta1.EMQX
return subResult{}
}

func generateNodeCookieSecret(instance *appsv2beta1.EMQX) *corev1.Secret {
var cookie string
func (a *addBootstrap) getAPIKeyString(ctx context.Context, instance *appsv2beta1.EMQX) (string, error) {
var bootstrapAPIKeys string

config, _ := hocon.ParseString(instance.Spec.Config.Data)
cookie = config.GetString("node.cookie")
if cookie == "" {
cookie, _ = password.Generate(64, 10, 0, true, true)
for _, apiKey := range instance.Spec.BootstrapAPIKeys {
if apiKey.SecretRef != nil {
keyValue, err := a.readSecret(ctx, instance.Namespace, apiKey.SecretRef.Key.SecretName, apiKey.SecretRef.Key.SecretKey)
if err != nil {
a.EventRecorder.Event(instance, corev1.EventTypeWarning, "GetBootStrapSecretRef", err.Error())
return "", err
}
secretValue, err := a.readSecret(ctx, instance.Namespace, apiKey.SecretRef.Secret.SecretName, apiKey.SecretRef.Secret.SecretKey)
if err != nil {
a.EventRecorder.Event(instance, corev1.EventTypeWarning, "GetBootStrapSecretRef", err.Error())
return "", err
}
bootstrapAPIKeys += keyValue + ":" + secretValue + "\n"
} else {
bootstrapAPIKeys += apiKey.Key + ":" + apiKey.Secret + "\n"
}
}

return bootstrapAPIKeys, nil
}

func (a *addBootstrap) readSecret(ctx context.Context, namespace string, name string, key string) (string, error) {
secret := &corev1.Secret{}
if err := a.Client.Get(ctx, types.NamespacedName{
Namespace: namespace,
Name: name,
}, secret); err != nil {
return "", emperror.Wrap(err, "failed to get secret")
}

if _, ok := secret.Data[key]; !ok {
return "", emperror.NewWithDetails("secret does not contain the key", "secret", secret.Name, "key", key)
}

return string(secret.Data[key]), nil
}

func generateBootstrapAPIKeySecret(instance *appsv2beta1.EMQX, bootstrapAPIKeys string) *corev1.Secret {
defPassword, _ := password.Generate(64, 10, 0, true, true)
bootstrapAPIKeys += appsv2beta1.DefaultBootstrapAPIKey + ":" + defPassword
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: instance.Namespace,
Name: instance.NodeCookieNamespacedName().Name,
Name: instance.BootstrapAPIKeyNamespacedName().Name,
Labels: appsv2beta1.CloneAndMergeMap(appsv2beta1.DefaultLabels(instance), instance.Labels),
},
StringData: map[string]string{
"node_cookie": cookie,
"bootstrap_api_key": bootstrapAPIKeys,
},
}
}

// ReadSecret reads a secret from the Kubernetes cluster.
func ReadSecret(k8sClient client.Client, ctx context.Context, namespace string, name string, key string) (string, error) {
// Define a new Secret object
secret := &corev1.Secret{}

// Define the Secret Name and Namespace
secretName := types.NamespacedName{
Namespace: namespace,
Name: name,
}

// Use the client to fetch the Secret
if err := k8sClient.Get(ctx, secretName, secret); err != nil {
return "", err
}

// secret.Data is a map[string][]byte
secretValue := string(secret.Data[key])

return secretValue, nil
}

func generateBootstrapAPIKeySecret(k8sClient client.Client, ctx context.Context, instance *appsv2beta1.EMQX) *corev1.Secret {
logger := log.FromContext(ctx)
bootstrapAPIKeys := ""

for _, apiKey := range instance.Spec.BootstrapAPIKeys {
if apiKey.SecretRef != nil {
logger.V(1).Info("Read SecretRef")
func generateNodeCookieSecret(instance *appsv2beta1.EMQX) *corev1.Secret {
var cookie string

// Read key and secret values from the refenced secrets
keyValue, err := ReadSecret(k8sClient, ctx, instance.Namespace, apiKey.SecretRef.Key.SecretName, apiKey.SecretRef.Key.SecretKey)
if err != nil {
logger.V(1).Error(err, "read secretRef", "key")
continue
}
secretValue, err := ReadSecret(k8sClient, ctx, instance.Namespace, apiKey.SecretRef.Secret.SecretName, apiKey.SecretRef.Secret.SecretKey)
if err != nil {
logger.V(1).Error(err, "read secretRef", "secret")
continue
}
bootstrapAPIKeys += keyValue + ":" + secretValue + "\n"
} else {
bootstrapAPIKeys += apiKey.Key + ":" + apiKey.Secret + "\n"
}
config, _ := hocon.ParseString(instance.Spec.Config.Data)
cookie = config.GetString("node.cookie")
if cookie == "" {
cookie, _ = password.Generate(64, 10, 0, true, true)
}
defPassword, _ := password.Generate(64, 10, 0, true, true)
bootstrapAPIKeys += appsv2beta1.DefaultBootstrapAPIKey + ":" + defPassword

return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
Expand All @@ -121,11 +119,11 @@ func generateBootstrapAPIKeySecret(k8sClient client.Client, ctx context.Context,
},
ObjectMeta: metav1.ObjectMeta{
Namespace: instance.Namespace,
Name: instance.BootstrapAPIKeyNamespacedName().Name,
Name: instance.NodeCookieNamespacedName().Name,
Labels: appsv2beta1.CloneAndMergeMap(appsv2beta1.DefaultLabels(instance), instance.Labels),
},
StringData: map[string]string{
"bootstrap_api_key": bootstrapAPIKeys,
"node_cookie": cookie,
},
}
}
45 changes: 37 additions & 8 deletions controllers/apps/v2beta1/add_bootstrap_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

appsv2beta1 "github.com/emqx/emqx-operator/apis/apps/v2beta1"
"github.com/emqx/emqx-operator/internal/handler"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -46,7 +47,13 @@ func TestGenerateBootstrapAPIKeySecret(t *testing.T) {
t.Fatal(err)
}

fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
a := &addBootstrap{
EMQXReconciler: &EMQXReconciler{
Handler: &handler.Handler{
Client: fake.NewClientBuilder().WithScheme(scheme).Build(),
},
},
}

// Create a context
ctx := context.Background()
Expand All @@ -66,7 +73,12 @@ func TestGenerateBootstrapAPIKeySecret(t *testing.T) {
},
}

got := generateBootstrapAPIKeySecret(fakeClient, ctx, instance)
str, err := a.getAPIKeyString(ctx, instance)
if err != nil {
t.Fatal(err)
}

got := generateBootstrapAPIKeySecret(instance, str)
assert.Equal(t, "emqx-bootstrap-api-key", got.Name)
data, ok := got.StringData["bootstrap_api_key"]
assert.True(t, ok)
Expand Down Expand Up @@ -109,17 +121,23 @@ func TestGenerateBootstrapAPIKeySecretWithSecretRef(t *testing.T) {
},
}

fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
a := &addBootstrap{
EMQXReconciler: &EMQXReconciler{
Handler: &handler.Handler{
Client: fake.NewClientBuilder().WithScheme(scheme).Build(),
},
},
}

// Create a context
ctx := context.Background()

// Add secrets to the fake client
err = fakeClient.Create(ctx, keySecret)
err = a.Client.Create(ctx, keySecret)
if err != nil {
t.Fatal(err)
}
err = fakeClient.Create(ctx, valueSecret)
err = a.Client.Create(ctx, valueSecret)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -147,7 +165,12 @@ func TestGenerateBootstrapAPIKeySecretWithSecretRef(t *testing.T) {
},
}

got := generateBootstrapAPIKeySecret(fakeClient, ctx, instance)
str, err := a.getAPIKeyString(ctx, instance)
if err != nil {
t.Fatal(err)
}

got := generateBootstrapAPIKeySecret(instance, str)
assert.Equal(t, "emqx-bootstrap-api-key", got.Name)
data, ok := got.StringData["bootstrap_api_key"]
assert.True(t, ok)
Expand Down Expand Up @@ -185,12 +208,18 @@ func TestReadSecret(t *testing.T) {
Data: secretData,
}

fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(secret).Build()
a := &addBootstrap{
EMQXReconciler: &EMQXReconciler{
Handler: &handler.Handler{
Client: fake.NewClientBuilder().WithScheme(scheme).WithObjects(secret).Build(),
},
},
}

// Create a context
ctx := context.Background()

val, err := ReadSecret(fakeClient, ctx, "default", "test-secret", "key")
val, err := a.readSecret(ctx, "default", "test-secret", "key")
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit aaa103c

Please sign in to comment.