Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Dynamic Config Push #379

Merged
merged 17 commits into from
Jan 29, 2025
7 changes: 4 additions & 3 deletions admiral/apis/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ const (
)

type AdmiralConfig struct {
IdpsConfig IdpsConfig `yaml:"idps,omitempty"`
IgnoreIdentityList IgnoreIdentityList `yaml:"ignoreIdentityList,omitempty"`
WorkloadDatabase DynamoDB `yaml:"workloadDynamoDB,omitempty"`
IdpsConfig IdpsConfig `yaml:"idps,omitempty"`
IgnoreIdentityList IgnoreIdentityList `yaml:"ignoreIdentityList,omitempty"`
WorkloadDatabase DynamoDB `yaml:"workloadDynamoDB,omitempty"`
DynamicConfigDatabase DynamoDB `yaml:"dynamicConfigDynamoDB,omitempty"`
}

type IgnoreIdentityList struct {
Expand Down
14 changes: 14 additions & 0 deletions admiral/cmd/admiral/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ func GetRootCmd(args []string) *cobra.Command {
log.Fatalf("Error: %v", err)
}

if common.IsAdmiralDynamicConfigEnabled() {
go clusters.UpdateASyncAdmiralConfig(remoteRegistry.DynamicConfigDatabaseClient, params.DynamicSyncPeriod)
}

// This is required for PERF tests only.
// Perf tests requires remote registry object for validations.
// There is no way to inject this object
Expand Down Expand Up @@ -268,6 +272,16 @@ func GetRootCmd(args []string) *cobra.Command {
rootCmd.PersistentFlags().StringSliceVar(&params.ClientDiscoveryClustersForJobs, "client_discovery_clusters_for_jobs", []string{}, "List of clusters for client discovery for k8s jobs")
rootCmd.PersistentFlags().StringSliceVar(&params.DiscoveryClustersForNumaflow, "client_discovery_clusters_for_numaflow", []string{}, "List of clusters for client discovery for numaflow types")

//Parameter for DynamicConfigPush
rootCmd.PersistentFlags().BoolVar(&params.EnableDynamicConfig, "enable_dynamic_config", true, "Enable/Disable Dynamic Configuration")
rootCmd.PersistentFlags().StringVar(&params.DynamicConfigDynamoDBTableName, "dynamic_config_dynamodb_table_name", "dynamic-config-dev", "The name of the dynamic config dynamodb table")
rootCmd.PersistentFlags().IntVar(&params.DynamicSyncPeriod, "dynamic_sync_period", 10, "Duration in min after which the dynamic sync get performed")

//Parameter for NLB releated migration
rootCmd.PersistentFlags().StringSliceVar(&params.NLBEnabledClusters, "nlb_enabled_clusters", []string{}, "Comma seperated list of enabled clusters to be enabled for NLB")
rootCmd.PersistentFlags().StringSliceVar(&params.NLBEnabledIdentityList, "nlb_enabled_identity_list", []string{}, "Comma seperated list of enabled idenity list to be enabled for NLB")
rootCmd.PersistentFlags().StringSliceVar(&params.CLBEnabledClusters, "clb_enabled_clusters", []string{}, "Comma seperated list of enabled clusters to be enabled for CLB")

return rootCmd
}

Expand Down
135 changes: 127 additions & 8 deletions admiral/pkg/clusters/admiralDatabaseClient.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package clusters

import (
"crypto/md5"
"errors"
"fmt"
"github.com/istio-ecosystem/admiral/admiral/apis/v1"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/common"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
"io/ioutil"
"time"
)

// TODO: make this more generic to handle new dynamoDB tables
Expand All @@ -14,6 +18,11 @@ type WorkloadDatabaseClient struct {
database *v1.DynamoDB
}

type DynamicConfigDatabaseClient struct {
dynamoClient *DynamoClient
database *v1.DynamoDB
}

type DummyDatabaseClient struct{}

type AdmiralDatabaseManager interface {
Expand Down Expand Up @@ -65,6 +74,23 @@ func checkIfDatabaseClientIsInitialize(workloadDatabaseClient *WorkloadDatabaseC
return nil
}

func (dynamicConfigDatabaseClient *DynamicConfigDatabaseClient) Update(data interface{}, logger *log.Entry) error {
//TODO implement me
//At point of release there is no plan to support push config to dyanmic config storage
panic("implement me")
}

func (dynamicConfigDatabaseClient *DynamicConfigDatabaseClient) Delete(data interface{}, logger *log.Entry) error {
//TODO implement me
//At point of release there is no plan to support delete config to dyanmic config storage
panic("implement me")
}

func (dynamicConfigDatabaseClient *DynamicConfigDatabaseClient) Get(env, identity string) (interface{}, error) {
//Variable renaming is done to re-purpose existing interface
return dynamicConfigDatabaseClient.dynamoClient.getDynamicConfig(env, identity, dynamicConfigDatabaseClient.database.TableName)
}

func (databaseClient *DummyDatabaseClient) Update(data interface{}, logger *log.Entry) error {
return nil
}
Expand All @@ -78,12 +104,28 @@ func (databaseClient *DummyDatabaseClient) Get(env, identity string) (interface{
}

func NewAdmiralDatabaseClient(admiralConfigPath string, dynamoClientInitFunc func(string, string) (*DynamoClient, error)) (*WorkloadDatabaseClient, error) {
var (
workloadDatabaseClient = &WorkloadDatabaseClient{}
admiralConfig *v1.AdmiralConfig
var workloadDatabaseClient = &WorkloadDatabaseClient{}

admiralConfig, err := ReadDynamoConfigForDynamoDB(admiralConfigPath)
if err != nil {
return nil, fmt.Errorf("error unmarshalling admiral config file, err: %v", err)
}

workloadDatabaseClient.database = &admiralConfig.WorkloadDatabase
workloadDatabaseClient.dynamoClient, err = dynamoClientInitFunc(
admiralConfig.WorkloadDatabase.Role,
admiralConfig.WorkloadDatabase.Region,
)
if err != nil {
return nil, fmt.Errorf("unable to instantiate dynamo client, err: %v", err)
}
return workloadDatabaseClient, nil
}

data, err := ioutil.ReadFile(admiralConfigPath)
func ReadDynamoConfigForDynamoDB(path string) (*v1.AdmiralConfig, error) {
var admiralConfig *v1.AdmiralConfig

data, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("error reading admiral config file, err: %v", err)
}
Expand All @@ -93,13 +135,90 @@ func NewAdmiralDatabaseClient(admiralConfigPath string, dynamoClientInitFunc fun
return nil, fmt.Errorf("error unmarshalling admiral config file, err: %v", err)
}

workloadDatabaseClient.database = &admiralConfig.WorkloadDatabase
workloadDatabaseClient.dynamoClient, err = dynamoClientInitFunc(
return admiralConfig, nil
}

func NewDynamicConfigDatabaseClient(path string, dynamoClientInitFunc func(role string, region string) (*DynamoClient, error)) (*DynamicConfigDatabaseClient, error) {
var dynamicConfigClient = DynamicConfigDatabaseClient{}

admiralConfig, err := ReadDynamoConfigForDynamoDB(path)
if err != nil {
return nil, fmt.Errorf("task=%v, error unmarshalling admiral config file, err: %v", common.DynamicConfigUpdate, err)
}

dynamicConfigClient.database = &admiralConfig.DynamicConfigDatabase
dynamicConfigClient.database.TableName = common.GetAdmiralParams().DynamicConfigDynamoDBTableName
dynamicConfigClient.dynamoClient, err = dynamoClientInitFunc(
admiralConfig.WorkloadDatabase.Role,
admiralConfig.WorkloadDatabase.Region,
)
if err != nil {
return nil, fmt.Errorf("unable to instantiate dynamo client, err: %v", err)
return &dynamicConfigClient, fmt.Errorf("task=%v, unable to instantiate dynamo client for DynamicConfig, err: %v", common.DynamicConfigUpdate, err)
}
return &dynamicConfigClient, nil
}

func UpdateASyncAdmiralConfig(dbClient AdmiralDatabaseManager, syncTime int) {

for range time.Tick(time.Minute * time.Duration(syncTime)) {
ReadAndUpdateSyncAdmiralConfig(dbClient)
}
}

func ReadAndUpdateSyncAdmiralConfig(dbClient AdmiralDatabaseManager) error {

dbRawData, err := dbClient.Get("EnableDynamicConfig", common.Admiral)
if err != nil {
log.Errorf("task=%s, error getting EnableDynamicConfig admiral config, err: %v", common.DynamicConfigUpdate, err)
return err
}

configData, ok := dbRawData.(DynamicConfigData)
if !ok {
return errors.New(fmt.Sprintf("task=%s, failed to parse DynamicConfigData", common.DynamicConfigUpdate))
}

if IsDynamicConfigChanged(configData) {
log.Infof(fmt.Sprintf("task=%s, updating DynamicConfigData with Admiral config", common.DynamicConfigUpdate))
UpdateSyncAdmiralConfig(configData)
} else {
log.Infof(fmt.Sprintf("task=%s, no need to update DynamicConfigData", common.DynamicConfigUpdate))
}

return nil
}

func IsDynamicConfigChanged(config DynamicConfigData) bool {

if config.EnableDynamicConfig != common.Admiral {
return false
}

if DynamicConfigCheckSum == md5.Sum([]byte(fmt.Sprintf("%v", config))) {
return false
} else {
DynamicConfigCheckSum = md5.Sum([]byte(fmt.Sprintf("%v", config)))
return true
}
}

func UpdateSyncAdmiralConfig(configData DynamicConfigData) {
vinay-g marked this conversation as resolved.
Show resolved Hide resolved
if configData.EnableDynamicConfig == common.Admiral {
//Fetch Existing config and update which are changed.
newAdmiralConfig := common.GetAdmiralParams()
if len(configData.NLBEnabledClusters) > 0 {
newAdmiralConfig.NLBEnabledClusters = configData.NLBEnabledClusters
}

if len(configData.CLBEnabledClusters) > 0 {
newAdmiralConfig.CLBEnabledClusters = configData.CLBEnabledClusters
}

if len(configData.NLBEnabledIdentityList) > 0 {
newAdmiralConfig.NLBEnabledIdentityList = configData.NLBEnabledIdentityList
}

common.UpdateAdmiralParams(newAdmiralConfig)

}
return workloadDatabaseClient, nil
}
Loading