Skip to content

Commit

Permalink
Merge pull request #206 from castai/store-metadata-in-secret
Browse files Browse the repository at this point in the history
feat: store cluster id in a metadata secret
  • Loading branch information
laimonasr authored Dec 5, 2024
2 parents 01d33bb + 1f81167 commit 88447eb
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 2 deletions.
17 changes: 15 additions & 2 deletions cmd/agent/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"castai-agent/internal/services/controller"
"castai-agent/internal/services/controller/scheme"
"castai-agent/internal/services/discovery"
"castai-agent/internal/services/metadata"
"castai-agent/internal/services/monitor"
"castai-agent/internal/services/providers"
"castai-agent/internal/services/replicas"
Expand Down Expand Up @@ -174,6 +175,18 @@ func runAgentMode(ctx context.Context, castaiclient castai.Client, log *logrus.E
return fmt.Errorf("getting provider: %w", err)
}

metadataStore := metadata.New(clientset, cfg)

clusterIDChangedHandler := func(clusterID string) {
if err := metadataStore.StoreMetadataConfigMap(ctx, &metadata.Metadata{
ClusterID: clusterID,
}); err != nil {
log.Warnf("failed to store metadata in a config map: %v", err)
}

clusterIDChanged(clusterID)
}

log.Data["provider"] = provider.Name()
log.Infof("using provider %q", provider.Name())

Expand All @@ -189,10 +202,10 @@ func runAgentMode(ctx context.Context, castaiclient castai.Client, log *logrus.E
return fmt.Errorf("registering cluster: %w", err)
}
clusterID = reg.ClusterID
clusterIDChanged(clusterID)
clusterIDChangedHandler(clusterID)
log.Infof("cluster registered: %v, clusterID: %s", reg, clusterID)
} else {
clusterIDChanged(clusterID)
clusterIDChangedHandler(clusterID)
log.Infof("clusterID: %s provided by env variable", clusterID)
}

Expand Down
12 changes: 12 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type Config struct {
PprofPort int `mapstructure:"pprof.port"`
HealthzPort int `mapstructure:"healthz_port"`

MetadataStore *MetadataStoreConfig `mapstructure:"metadata_store"`

LeaderElection LeaderElectionConfig `mapstructure:"leader_election"`

MonitorMetadata string `mapstructure:"monitor_metadata"`
Expand Down Expand Up @@ -110,6 +112,12 @@ type Static struct {
ClusterID string `mapstructure:"cluster_id"`
}

type MetadataStoreConfig struct {
Enabled bool `mapstructure:"enabled"`
ConfigMapNamespace string `mapstructure:"config_map_namespace"`
ConfigMapName string `mapstructure:"config_map_name"`
}

type Anywhere struct {
ClusterName string `mapstructure:"cluster_name"`
}
Expand Down Expand Up @@ -169,6 +177,10 @@ func Get() Config {
viper.SetDefault("leader_election.lock_name", "agent-leader-election-lock")
viper.SetDefault("leader_election.namespace", "castai-agent")

viper.SetDefault("metadata_store.enabled", false)
viper.SetDefault("metadata_store.config_map_name", "castai-agent-metadata")
viper.SetDefault("metadata_store.config_map_namespace", "castai-agent")

viper.AutomaticEnv()
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AllowEmptyEnv(true)
Expand Down
55 changes: 55 additions & 0 deletions internal/services/metadata/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package metadata

import (
"context"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"

"castai-agent/internal/config"
)

type Store interface {
// StoreMetadataConfigMap stores relevant agent runtime metadata in a config map.
StoreMetadataConfigMap(ctx context.Context, metadata *Metadata) error
}

var _ Store = (*StoreImpl)(nil)

type StoreImpl struct {
clientset kubernetes.Interface
cfg config.Config
}

func New(clientset kubernetes.Interface, cfg config.Config) *StoreImpl {
return &StoreImpl{
clientset: clientset,
cfg: cfg,
}
}

func (s *StoreImpl) StoreMetadataConfigMap(ctx context.Context, metadata *Metadata) error {
if !s.cfg.MetadataStore.Enabled {
return nil
}

configMapNamespace := s.cfg.MetadataStore.ConfigMapNamespace
configMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: s.cfg.MetadataStore.ConfigMapName,
Namespace: configMapNamespace,
},
Data: map[string]string{
"CLUSTER_ID": metadata.ClusterID,
},
}

_, err := s.clientset.CoreV1().ConfigMaps(configMapNamespace).Update(ctx, configMap, metav1.UpdateOptions{})
if errors.IsNotFound(err) {
_, err = s.clientset.CoreV1().ConfigMaps(configMapNamespace).Create(ctx, configMap, metav1.CreateOptions{})
}

return err
}
98 changes: 98 additions & 0 deletions internal/services/metadata/store_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package metadata

import (
"context"
"testing"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakeclientset "k8s.io/client-go/kubernetes/fake"

"castai-agent/internal/config"
)

func TestStoreImpl_StoreMetadataConfigMap(t *testing.T) {
tests := []struct {
name string
cfg config.Config
metadata *Metadata
existingConfigMap *corev1.ConfigMap
expectedError bool
}{
{
name: "should store metadata successfully when config map does not exist",
cfg: config.Config{
MetadataStore: &config.MetadataStoreConfig{
Enabled: true,
ConfigMapName: "castai-agent-metadata",
ConfigMapNamespace: "default",
},
},
metadata: &Metadata{
ClusterID: "test-cluster-id",
},
expectedError: false,
},
{
name: "should store metadata successfully when config map exists",
cfg: config.Config{
MetadataStore: &config.MetadataStoreConfig{
Enabled: true,
ConfigMapName: "castai-agent-metadata",
ConfigMapNamespace: "default",
},
},
metadata: &Metadata{
ClusterID: "test-cluster-id",
},
existingConfigMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "castai-agent-metadata",
Namespace: "default",
},
Data: map[string]string{
"CLUSTER_ID": "original-test-cluster-id",
},
},
expectedError: false,
},
{
name: "should not store metadata when store is disabled",
cfg: config.Config{
MetadataStore: &config.MetadataStoreConfig{
Enabled: false,
},
},
metadata: &Metadata{
ClusterID: "test-cluster-id",
},
expectedError: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := require.New(t)
clientset := fakeclientset.NewSimpleClientset()
store := New(clientset, tt.cfg)

if tt.existingConfigMap != nil {
_, err := clientset.CoreV1().ConfigMaps(tt.cfg.MetadataStore.ConfigMapNamespace).Create(context.Background(), tt.existingConfigMap, metav1.CreateOptions{})
r.NoError(err)
}

err := store.StoreMetadataConfigMap(context.Background(), tt.metadata)
if tt.expectedError {
r.Error(err)
} else {
r.NoError(err)
if tt.cfg.MetadataStore.Enabled {
configMap, err := clientset.CoreV1().ConfigMaps(tt.cfg.MetadataStore.ConfigMapNamespace).Get(context.Background(), tt.cfg.MetadataStore.ConfigMapName, metav1.GetOptions{})
r.NoError(err)
r.Equal(tt.metadata.ClusterID, configMap.Data["CLUSTER_ID"])
}
}
})
}
}
5 changes: 5 additions & 0 deletions internal/services/metadata/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package metadata

type Metadata struct {
ClusterID string
}

0 comments on commit 88447eb

Please sign in to comment.