diff --git a/collectors/metrics/pkg/forwarder/forwarder.go b/collectors/metrics/pkg/forwarder/forwarder.go index 63e77c483..a1cf4ea58 100644 --- a/collectors/metrics/pkg/forwarder/forwarder.go +++ b/collectors/metrics/pkg/forwarder/forwarder.go @@ -49,6 +49,7 @@ type Config struct { FromTokenFile string FromCAFile string ToUploadCA string + IsCustomCA bool ToUploadCert string ToUploadKey string @@ -188,7 +189,7 @@ func createClients(cfg Config, metrics *metricsclient.ClientMetrics, interval ti // Create the `toClient`. - toTransport, err := metricsclient.MTLSTransport(logger, cfg.ToUploadCA, cfg.ToUploadCert, cfg.ToUploadKey) + toTransport, err := metricsclient.MTLSTransport(logger, cfg.IsCustomCA, cfg.ToUploadCA, cfg.ToUploadCert, cfg.ToUploadKey) if err != nil { return nil, nil, transformer, fmt.Errorf("failed to create TLS transport: %w", err) } diff --git a/collectors/metrics/pkg/metricsclient/metricsclient.go b/collectors/metrics/pkg/metricsclient/metricsclient.go index 24f1b76bc..7e885078c 100644 --- a/collectors/metrics/pkg/metricsclient/metricsclient.go +++ b/collectors/metrics/pkg/metricsclient/metricsclient.go @@ -9,6 +9,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -365,7 +366,7 @@ func withCancel(ctx context.Context, client *http.Client, req *http.Request, fn return err } -func MTLSTransport(logger log.Logger, caCertFile, tlsCrtFile, tlsKeyFile string) (*http.Transport, error) { +func MTLSTransport(logger log.Logger, isCustomCA bool, caCertFile, tlsCrtFile, tlsKeyFile string) (*http.Transport, error) { testMode := os.Getenv("UNIT_TEST") != "" if testMode { caCertFile = "../../testdata/tls/ca.crt" @@ -373,9 +374,18 @@ func MTLSTransport(logger log.Logger, caCertFile, tlsCrtFile, tlsKeyFile string) tlsCrtFile = "../../testdata/tls/tls.crt" } // Load Server CA cert - caCert, err := os.ReadFile(filepath.Clean(caCertFile)) - if err != nil { - return nil, fmt.Errorf("failed to load server ca cert file: %w", err) + caCert := []byte{} + var err error + if !isCustomCA { + caCert, err = os.ReadFile(filepath.Clean(caCertFile)) + if err != nil { + return nil, fmt.Errorf("failed to load server ca cert file: %w", err) + } + } else { + caCert, err = base64.StdEncoding.DecodeString(caCertFile) + if err != nil { + return nil, fmt.Errorf("failed to decode server ca cert: %w", err) + } } // Load client cert signed by Client CA cert, err := tls.LoadX509KeyPair(tlsCrtFile, tlsKeyFile) diff --git a/go.mod b/go.mod index f08186338..3b0e2eb5e 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/stolostron/observatorium-operator v0.0.0-20230411203847-4514321263d1 github.com/stretchr/testify v1.8.4 github.com/thanos-io/thanos v0.30.0 - go.uber.org/zap v1.24.0 + go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20221212164502-fae10dda9338 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.28.2 @@ -44,8 +44,8 @@ require ( k8s.io/client-go v12.0.0+incompatible k8s.io/klog v1.0.0 k8s.io/kubectl v0.27.2 - open-cluster-management.io/addon-framework v0.8.0 - open-cluster-management.io/api v0.12.0 + open-cluster-management.io/addon-framework v0.8.1-0.20231128122622-3bfdbffb237c + open-cluster-management.io/api v0.12.1-0.20231130134655-97a8a92a7f30 sigs.k8s.io/controller-runtime v0.15.1 sigs.k8s.io/kube-storage-version-migrator v0.0.4 sigs.k8s.io/kustomize/api v0.13.4 @@ -141,12 +141,12 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/goleak v1.2.0 // indirect - go.uber.org/multierr v1.8.0 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.13.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sync v0.3.0 // indirect + golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index 122ea301b..d4fb9e808 100644 --- a/go.sum +++ b/go.sum @@ -443,7 +443,6 @@ github.com/baidubce/bce-sdk-go v0.9.81/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFT github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -2031,8 +2030,8 @@ go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -2042,8 +2041,9 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2202,8 +2202,8 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2883,10 +2883,10 @@ k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -open-cluster-management.io/addon-framework v0.8.0 h1:i1OReMHuZIoAw2Q04SLjkieU25DnxYilzVZzBNyROwU= -open-cluster-management.io/addon-framework v0.8.0/go.mod h1:20DP06VXhJ9RE1PetAMEQyeFCP7+nhs92pCAkqbWUOg= -open-cluster-management.io/api v0.12.0 h1:sNkj4k2XyWA/GLsTiFg82bLIZ7JDZKkLLLyZjJUlJMs= -open-cluster-management.io/api v0.12.0/go.mod h1:/CZhelEH+30/pX7vXGSZOzLMX0zvjthYOkT/5ZTzVTQ= +open-cluster-management.io/addon-framework v0.8.1-0.20231128122622-3bfdbffb237c h1:s/xo9ggmrc0z4qdHdZU3q0E6vuyfu9JA0X8IQ17p1aQ= +open-cluster-management.io/addon-framework v0.8.1-0.20231128122622-3bfdbffb237c/go.mod h1:aj97pgpGJ0/LpQzBVtU2oDFqqIiZLOPnsjLKG/sVkFw= +open-cluster-management.io/api v0.12.1-0.20231130134655-97a8a92a7f30 h1:qzkatL1pCsMvA2KkuJ0ywWUqJ0ZI13ouMRVuAPTrhWk= +open-cluster-management.io/api v0.12.1-0.20231130134655-97a8a92a7f30/go.mod h1:fnoEBW9pbikOWOzF4zuT9DQAgWbY3PpPT/MSDZ/4bxw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector.go b/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector.go index 5fffc1905..0b403c8b4 100644 --- a/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector.go +++ b/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector.go @@ -66,6 +66,7 @@ type CollectorParams struct { httpProxy string httpsProxy string noProxy string + CABundle string replicaCount int32 } @@ -90,7 +91,18 @@ func getCommands(params CollectorParams) []string { "--from=$(FROM)", "--from-query=$(FROM_QUERY)", "--to-upload=$(TO)", - "--to-upload-ca=/tlscerts/ca/ca.crt", + "--to-upload-ca=" + func() string { + if params.CABundle == "" { + return "/tlscerts/ca/ca.crt" + } + return params.CABundle + }(), + "--custom-ca=" + func() string { + if params.CABundle != "" { + return "true" + } + return "false" + }(), "--to-upload-cert=/tlscerts/certs/tls.crt", "--to-upload-key=/tlscerts/certs/tls.key", "--interval=" + interval, @@ -305,6 +317,13 @@ func createDeployment(params CollectorParams) *appsv1.Deployment { Value: params.noProxy, }) } + if params.httpsProxy != "" && params.CABundle != "" { + metricsCollectorDep.Spec.Template.Spec.Containers[0].Env = append(metricsCollectorDep.Spec.Template.Spec.Containers[0].Env, + corev1.EnvVar{ + Name: "HTTPS_PROXY_CA_BUNDLE", + Value: params.CABundle, + }) + } if params.obsAddonSpec.Resources != nil { metricsCollectorDep.Spec.Template.Spec.Containers[0].Resources = *params.obsAddonSpec.Resources @@ -343,6 +362,8 @@ func updateMetricsCollectors(ctx context.Context, c client.Client, obsAddonSpec params.httpsProxy = env.Value } else if env.Name == "NO_PROXY" { params.noProxy = env.Value + } else if env.Name == "HTTPS_PROXY_CA_BUNDLE" { + params.CABundle = env.Value } } } diff --git a/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector_test.go b/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector_test.go index 8fa8d98b6..8a11e6717 100644 --- a/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector_test.go +++ b/operators/endpointmetrics/controllers/observabilityendpoint/metrics_collector_test.go @@ -115,6 +115,7 @@ func checkAnnotationsAndProxySettings( foundHTTPProxy := false foundHTTPSProxy := false foundNOProxy := false + foundCABundle := false for _, e := range env { if e.Name == "HTTP_PROXY" { foundHTTPProxy = true @@ -131,7 +132,14 @@ func checkAnnotationsAndProxySettings( if e.Value != "bar.com" { t.Fatalf("NO_PROXY is not set correctly: expected %s, got %s", "bar.com", e.Value) } + } else if e.Name == "HTTPS_PROXY_CA_BUNDLE" { + foundCABundle = true + if e.Value != "custom-ca.crt" { + t.Fatalf("HTTPS_PROXY_CA_BUNDLE is not set correctly: expected %s, got %s", "custom-ca.crt", e.Value) + } + } + } if !foundHTTPProxy { t.Fatalf("HTTP_PROXY is not present in env") @@ -174,6 +182,7 @@ func TestMetricsCollector(t *testing.T) { httpProxy: "http://foo.com", httpsProxy: "https://foo.com", noProxy: "bar.com", + CABundle: "custom-ca.crt", } _, err = updateMetricsCollector(ctx, c, params, false) diff --git a/operators/multiclusterobservability/controllers/placementrule/manifestwork.go b/operators/multiclusterobservability/controllers/placementrule/manifestwork.go index c85289f27..0dc282bd5 100644 --- a/operators/multiclusterobservability/controllers/placementrule/manifestwork.go +++ b/operators/multiclusterobservability/controllers/placementrule/manifestwork.go @@ -6,6 +6,7 @@ package placementrule import ( "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -325,31 +326,6 @@ func createManifestWorks( } } - // If ProxyConfig is specified as part of addonConfig, set the proxy envs - if clusterName != localClusterName { - for i := range spec.Containers { - container := &spec.Containers[i] - if addonConfig.Spec.ProxyConfig.HTTPProxy != "" { - container.Env = append(container.Env, corev1.EnvVar{ - Name: "HTTP_PROXY", - Value: addonConfig.Spec.ProxyConfig.HTTPProxy, - }) - } - if addonConfig.Spec.ProxyConfig.HTTPSProxy != "" { - container.Env = append(container.Env, corev1.EnvVar{ - Name: "HTTPS_PROXY", - Value: addonConfig.Spec.ProxyConfig.HTTPSProxy, - }) - } - if addonConfig.Spec.ProxyConfig.NoProxy != "" { - container.Env = append(container.Env, corev1.EnvVar{ - Name: "NO_PROXY", - Value: addonConfig.Spec.ProxyConfig.NoProxy, - }) - } - } - } - if hasCustomRegistry { oldImage := container.Image newImage, err := imageRegistryClient.Cluster(clusterName).ImageOverride(oldImage) @@ -360,6 +336,40 @@ func createManifestWorks( } } } + // If ProxyConfig is specified as part of addonConfig, set the proxy envs + for i := range spec.Containers { + if spec.Containers[i].Name == "endpoint-observability-operator" { + container := &spec.Containers[i] + + if clusterName != localClusterName { + if addonConfig.Spec.ProxyConfig.HTTPProxy != "" { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "HTTP_PROXY", + Value: addonConfig.Spec.ProxyConfig.HTTPProxy, + }) + } + if addonConfig.Spec.ProxyConfig.HTTPSProxy != "" { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "HTTPS_PROXY", + Value: addonConfig.Spec.ProxyConfig.HTTPSProxy, + }) + //CA is allowed only when HTTPS proxy is set + if addonConfig.Spec.ProxyConfig.CABundle != nil { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "HTTPS_PROXY_CA", + Value: base64.StdEncoding.EncodeToString(addonConfig.Spec.ProxyConfig.CABundle), + }) + } + } + if addonConfig.Spec.ProxyConfig.NoProxy != "" { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "NO_PROXY", + Value: addonConfig.Spec.ProxyConfig.NoProxy, + }) + } + } + } + } log.Info(fmt.Sprintf("Cluster: %+v, Spec.NodeSelector (after): %+v", clusterName, spec.NodeSelector)) log.Info(fmt.Sprintf("Cluster: %+v, Spec.Tolerations (after): %+v", clusterName, spec.Tolerations)) dep.Spec.Template.Spec = spec diff --git a/operators/multiclusterobservability/controllers/placementrule/manifestwork_test.go b/operators/multiclusterobservability/controllers/placementrule/manifestwork_test.go index a6ecae52f..3123c93a2 100644 --- a/operators/multiclusterobservability/controllers/placementrule/manifestwork_test.go +++ b/operators/multiclusterobservability/controllers/placementrule/manifestwork_test.go @@ -334,6 +334,7 @@ func TestManifestWork(t *testing.T) { HTTPProxy: "http://foo.com", HTTPSProxy: "https://foo.com", NoProxy: "bar.com", + CABundle: "custom-ca.crt", }, }, } @@ -361,6 +362,7 @@ func TestManifestWork(t *testing.T) { foundHTTPProxy := false foundHTTPSProxy := false foundNOProxy := false + foundCABundle := false for _, e := range env { if e.Name == "HTTP_PROXY" { foundHTTPProxy = true @@ -377,6 +379,11 @@ func TestManifestWork(t *testing.T) { if e.Value != "bar.com" { t.Fatalf("NO_PROXY is not set correctly: expected %s, got %s", "bar.com", e.Value) } + } else if e.Name == "HTTPS_PROXY_CA_BUNDLE" { + foundCABundle = true + if e.Value != "custom-ca.crt" { + t.Fatalf("HTTPS_PROXY_CA_BUNDLE is not set correctly: expected %s, got %s", "custom-ca.crt", e.Value) + } } } if !foundHTTPProxy { diff --git a/operators/multiclusterobservability/controllers/placementrule/placementrule_controller.go b/operators/multiclusterobservability/controllers/placementrule/placementrule_controller.go index abe3d4985..2a78a1de6 100644 --- a/operators/multiclusterobservability/controllers/placementrule/placementrule_controller.go +++ b/operators/multiclusterobservability/controllers/placementrule/placementrule_controller.go @@ -539,6 +539,29 @@ func (r *PlacementRuleReconciler) SetupWithManager(mgr ctrl.Manager) error { clusterPred := getClusterPreds() + // Watch changes for AddonDeploymentConfig + AddonDeploymentPred := predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + if e.ObjectNew.GetName() == defaultAddonDeploymentConfig.Name && + e.ObjectNew.GetNamespace() == defaultAddonDeploymentConfig.Namespace { + log.Info("default AddonDeploymentConfig is updated") + return true + } + return false + }, + DeleteFunc: func(e event.DeleteEvent) bool { + if e.Object.GetName() == defaultAddonDeploymentConfig.Name && + e.Object.GetNamespace() == defaultAddonDeploymentConfig.Namespace { + log.Info("default AddonDeploymentConfig is deleted") + return true + } + return false + }, + } + obsAddonPred := predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { return false @@ -829,6 +852,20 @@ func (r *PlacementRuleReconciler) SetupWithManager(mgr ctrl.Manager) error { // secondary watch for alertmanager accessor serviceaccount Watches(&source.Kind{Type: &corev1.ServiceAccount{}}, &handler.EnqueueRequestForObject{}, builder.WithPredicates(amAccessorSAPred)) + // watch for AddonDeploymentConfig + if _, err := r.RESTMapper.RESTMapping(schema.GroupKind{Group: addonv1alpha1.GroupVersion.Group, Kind: "AddOnDeploymentConfig"}, addonv1alpha1.GroupVersion.Version); err == nil { + ctrBuilder = ctrBuilder.Watches( + &source.Kind{Type: &addonv1alpha1.AddOnDeploymentConfig{}}, + handler.EnqueueRequestsFromMapFunc(func(obj client.Object) []reconcile.Request { + return []reconcile.Request{ + {NamespacedName: types.NamespacedName{ + Name: config.AddonDeploymentConfigUpdateName, + }}, + } + }), + builder.WithPredicates(AddonDeploymentPred), + ) + } manifestWorkGroupKind := schema.GroupKind{Group: workv1.GroupVersion.Group, Kind: "ManifestWork"} if _, err := r.RESTMapper.RESTMapping(manifestWorkGroupKind, workv1.GroupVersion.Version); err == nil { workPred := getManifestworkPred() @@ -937,7 +974,8 @@ func StartPlacementController(mgr manager.Manager, crdMap map[string]bool) error func isReconcileRequired(request ctrl.Request, managedCluster string) bool { if request.Name == config.MCOUpdatedRequestName || request.Name == config.MCHUpdatedRequestName || - request.Name == config.ClusterManagementAddOnUpdateName { + request.Name == config.ClusterManagementAddOnUpdateName || + request.Name == config.AddonDeploymentConfigUpdateName { return true } if request.Namespace == config.GetDefaultNamespace() || diff --git a/operators/multiclusterobservability/controllers/placementrule/placementrule_controller_test.go b/operators/multiclusterobservability/controllers/placementrule/placementrule_controller_test.go index d9f54b721..48f6e30e1 100644 --- a/operators/multiclusterobservability/controllers/placementrule/placementrule_controller_test.go +++ b/operators/multiclusterobservability/controllers/placementrule/placementrule_controller_test.go @@ -11,6 +11,8 @@ import ( "strings" "testing" + appsv1 "k8s.io/api/apps/v1" + ocinfrav1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" routev1 "github.com/openshift/api/route/v1" @@ -177,7 +179,7 @@ func TestObservabilityAddonController(t *testing.T) { }, } objs := []runtime.Object{mco, pull, newConsoleRoute(), newTestObsApiRoute(), newTestAlertmanagerRoute(), newTestIngressController(), newTestRouteCASecret(), newCASecret(), newCertSecret(mcoNamespace), NewMetricsAllowListCM(), - NewAmAccessorSA(), NewAmAccessorTokenSecret(), newManagedClusterAddon(), deprecatedRole, newClusterMgmtAddon(), + NewAmAccessorSA(), NewAmAccessorTokenSecret(), deprecatedRole, newClusterMgmtAddon(), newAddonDeploymentConfig(defaultAddonConfigName, namespace), newAddonDeploymentConfig(addonConfigName, namespace)} c := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build() r := &PlacementRuleReconciler{Client: c, Scheme: s, CRDMap: map[string]bool{config.IngressControllerCRD: true}} @@ -233,6 +235,68 @@ func TestObservabilityAddonController(t *testing.T) { if err != nil { t.Fatalf("reconcile: (%v)", err) } + foundAddonDeploymentConfig := &addonv1alpha1.AddOnDeploymentConfig{} + err = c.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: defaultAddonConfigName}, foundAddonDeploymentConfig) + if err != nil { + t.Fatalf("Failed to get addondeploymentconfig %s: (%v)", name, err) + } + + //Change proxyconfig in addondeploymentconfig + foundAddonDeploymentConfig.Spec.ProxyConfig = addonv1alpha1.ProxyConfig{ + HTTPProxy: "http://test1.com", + HTTPSProxy: "https://test1.com", + NoProxy: "test.com", + } + + err = c.Update(context.TODO(), foundAddonDeploymentConfig) + if err != nil { + t.Fatalf("Failed to update addondeploymentconfig %s: (%v)", name, err) + } + + req = ctrl.Request{ + NamespacedName: types.NamespacedName{ + Name: config.AddonDeploymentConfigUpdateName, + }, + } + + _, err = r.Reconcile(context.TODO(), req) + if err != nil { + t.Fatalf("reconcile after updating addondeploymentconfig: (%v)", err) + } + + foundManifestwork := &workv1.ManifestWork{} + err = c.Get(context.TODO(), types.NamespacedName{Name: namespace + workNameSuffix, Namespace: namespace}, foundManifestwork) + if err != nil { + t.Fatalf("Failed to get manifestwork %s: (%v)", namespace, err) + } + for _, manifest := range foundManifestwork.Spec.Workload.Manifests { + obj, _ := util.GetObject(manifest.RawExtension) + if obj.GetObjectKind().GroupVersionKind().Kind == "Deployment" { + //Check the proxy env variables + deployment := obj.(*appsv1.Deployment) + spec := deployment.Spec.Template.Spec + for _, c := range spec.Containers { + if c.Name == "endpoint-observability-operator" { + env := c.Env + for _, e := range env { + if e.Name == "HTTP_PROXY" { + if e.Value != "http://test1.com" { + t.Fatalf("HTTP_PROXY is not set correctly: expected %s, got %s", "http://test1.com", e.Value) + } + } else if e.Name == "HTTPS_PROXY" { + if e.Value != "https://test1.com" { + t.Fatalf("HTTPS_PROXY is not set correctly: expected %s, got %s", "https://test1.com", e.Value) + } + } else if e.Name == "NO_PROXY" { + if e.Value != "test.com" { + t.Fatalf("NO_PROXY is not set correctly: expected %s, got %s", "test.com", e.Value) + } + } + } + } + } + } + } err = c.Delete(context.TODO(), mco) if err != nil { @@ -310,7 +374,7 @@ func TestObservabilityAddonController(t *testing.T) { // test mco-disable-alerting annotation // 1. Verify that alertmanager-endpoint in secret hub-info-secret in the ManifestWork is not null t.Logf("check alertmanager endpoint is not null") - foundManifestwork := &workv1.ManifestWork{} + foundManifestwork = &workv1.ManifestWork{} err = c.Get(context.TODO(), types.NamespacedName{Name: namespace + workNameSuffix, Namespace: namespace}, foundManifestwork) if err != nil { t.Fatalf("Failed to get manifestwork %s: (%v)", namespace, err) @@ -553,6 +617,11 @@ func newAddonDeploymentConfig(name, namespace string) *addonv1alpha1.AddOnDeploy "kubernetes.io/os": "linux", }, }, + ProxyConfig: addonv1alpha1.ProxyConfig{ + HTTPProxy: "http://foo.com", + HTTPSProxy: "https://foo.com", + NoProxy: "bar.com", + }, }, } } diff --git a/operators/multiclusterobservability/pkg/config/config.go b/operators/multiclusterobservability/pkg/config/config.go index 7f9efe9da..d1440bc7e 100644 --- a/operators/multiclusterobservability/pkg/config/config.go +++ b/operators/multiclusterobservability/pkg/config/config.go @@ -56,6 +56,7 @@ const ( MCHUpdatedRequestName = "mch-updated-request" MCOUpdatedRequestName = "mco-updated-request" ClusterManagementAddOnUpdateName = "clustermgmtaddon-updated-request" + AddonDeploymentConfigUpdateName = "addondc-updated-request" MulticloudConsoleRouteName = "multicloud-console" ImageManifestConfigMapNamePrefix = "mch-image-manifest-" OCMManifestConfigMapTypeLabelKey = "ocm-configmap-type"