diff --git a/cli/cmd/profile.go b/cli/cmd/profile.go index d7f4e9e8dd..83ff9ab30b 100644 --- a/cli/cmd/profile.go +++ b/cli/cmd/profile.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "os" + "slices" "github.com/odigos-io/odigos/cli/cmd/resources" "github.com/odigos-io/odigos/cli/cmd/resources/odigospro" @@ -102,17 +103,8 @@ var addProfileCmd = &cobra.Command{ os.Exit(1) } - // Fetch the available profiles for the current tier profiles := profiles.GetAvailableProfilesForTier(currentTier) - var selectedProfile *profile.Profile - - // Search for the specified profile in the available profiles - for _, profile := range profiles { - if string(profile.ProfileName) == profileName { - selectedProfile = &profile - break - } - } + selectedProfile := profile.FindProfileByName(common.ProfileName(profileName), profiles) if selectedProfile == nil { fmt.Printf("\033[31mERROR\033[0m Profile '%s' not available.\n", profileName) @@ -127,11 +119,9 @@ var addProfileCmd = &cobra.Command{ config.ConfigVersion += 1 // Check if the profile is already applied - for _, appliedProfile := range config.Profiles { - if string(appliedProfile) == profileName { - fmt.Println("\033[34mINFO\033[0m Profile", profileName, "is already applied.") - os.Exit(0) - } + if slices.Contains(config.Profiles, selectedProfile.ProfileName) { + fmt.Println("\033[34mINFO\033[0m Profile", profileName, "is already applied.") + os.Exit(0) } // Add the profile to the current configuration diff --git a/cli/cmd/resources/managers.go b/cli/cmd/resources/managers.go index 40d9057123..43dc7ff263 100644 --- a/cli/cmd/resources/managers.go +++ b/cli/cmd/resources/managers.go @@ -32,7 +32,6 @@ func CreateResourceManagers(client *kube.Client, odigosNs string, odigosTier com NewOdigletResourceManager(client, odigosNs, config, odigosTier, odigosVersion), NewAutoScalerResourceManager(client, odigosNs, config, odigosVersion), NewUIResourceManager(client, odigosNs, config, odigosVersion), - NewProfilesResourceManager(client, odigosNs, config, odigosTier), }...) if odigosTier == common.CloudOdigosTier { diff --git a/cli/cmd/resources/profiles.go b/cli/cmd/resources/profiles.go deleted file mode 100644 index badb75c074..0000000000 --- a/cli/cmd/resources/profiles.go +++ /dev/null @@ -1,67 +0,0 @@ -package resources - -import ( - "context" - "fmt" - - "github.com/odigos-io/odigos/cli/cmd/resources/resourcemanager" - "github.com/odigos-io/odigos/cli/pkg/kube" - "github.com/odigos-io/odigos/common" - "github.com/odigos-io/odigos/profiles" - "github.com/odigos-io/odigos/profiles/manifests" - "github.com/odigos-io/odigos/profiles/profile" -) - -func GetResourcesForProfileName(profileName common.ProfileName, tier common.OdigosTier) ([]profile.K8sObject, error) { - allAvailableProfiles := profiles.GetAvailableProfilesForTier(tier) - for _, p := range allAvailableProfiles { - if p.ProfileName == common.ProfileName(profileName) { - if p.KubeObject != nil { - filename := fmt.Sprintf("%s.yaml", profileName) - return manifests.GetEmbeddedResourceManifestsAsObjects(filename, p.KubeObject) - } - if len(p.Dependencies) > 0 { - allResources := []profile.K8sObject{} - for _, dep := range p.Dependencies { - resources, err := GetResourcesForProfileName(dep, tier) - if err != nil { - return nil, err - } - allResources = append(allResources, resources...) - } - return allResources, nil - } - return nil, nil // a profile might not be implemented as a resource necessarily - } - } - - return nil, nil -} - -type profilesResourceManager struct { - client *kube.Client - ns string - config *common.OdigosConfiguration - tier common.OdigosTier -} - -func NewProfilesResourceManager(client *kube.Client, ns string, config *common.OdigosConfiguration, tier common.OdigosTier) resourcemanager.ResourceManager { - return &profilesResourceManager{client: client, ns: ns, config: config, tier: tier} -} - -func (a *profilesResourceManager) Name() string { return "Profiles" } - -func (a *profilesResourceManager) InstallFromScratch(ctx context.Context) error { - allResources := []kube.Object{} - for _, profile := range a.config.Profiles { - profileResources, err := GetResourcesForProfileName(profile, a.tier) - if err != nil { - return err - } - for _, r := range profileResources { - r.SetNamespace(a.ns) - allResources = append(allResources, r) - } - } - return a.client.ApplyResources(ctx, a.config.ConfigVersion, allResources) -} diff --git a/cli/cmd/resources/scheduler.go b/cli/cmd/resources/scheduler.go index 9c1501909c..c3cb3cb232 100644 --- a/cli/cmd/resources/scheduler.go +++ b/cli/cmd/resources/scheduler.go @@ -105,6 +105,11 @@ func NewSchedulerRole(ns string) *rbacv1.Role { Resources: []string{"destinations"}, Verbs: []string{"get", "list", "watch"}, }, + { // apply profiles + APIGroups: []string{"odigos.io"}, + Resources: []string{"processors", "instrumentationrules"}, + Verbs: []string{"get", "list", "watch", "patch", "delete", "create"}, + }, }, } } @@ -242,6 +247,17 @@ func NewSchedulerDeployment(ns string, version string, imagePrefix string) *apps }, }, }, + { + Name: consts.OdigosVersionEnvVarName, + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: k8sconsts.OdigosDeploymentConfigMapName, + }, + Key: k8sconsts.OdigosDeploymentConfigMapVersionKey, + }, + }, + }, }, EnvFrom: []corev1.EnvFromSource{ { diff --git a/helm/odigos/templates/scheduler/role.yaml b/helm/odigos/templates/scheduler/role.yaml index 6210ae7718..e2ac3a3682 100644 --- a/helm/odigos/templates/scheduler/role.yaml +++ b/helm/odigos/templates/scheduler/role.yaml @@ -46,3 +46,15 @@ rules: - get - list - watch + - apiGroups: + - odigos.io + resources: + - instrumentationrules + - processors + verbs: + - get + - list + - watch + - patch + - delete + - create diff --git a/k8sutils/pkg/consts/consts.go b/k8sutils/pkg/consts/consts.go index 82eb639f2d..07a515f06a 100644 --- a/k8sutils/pkg/consts/consts.go +++ b/k8sutils/pkg/consts/consts.go @@ -23,6 +23,15 @@ const ( OdigosInjectInstrumentationLabel = "odigos.io/inject-instrumentation" // OdigosCollectorRoleLabel is the label used to identify the role of the Odigos collector. OdigosCollectorRoleLabel = "odigos.io/collector-role" + + // used to label resources created by profiles with the hash that created them. + // when a new profiles is reconciled, we will apply them with a new hash + // and use the label to identify the resources that needs to be deleted. + OdigosProfilesHashLabel = "odigos.io/profiles-hash" + + // for resources auto created by a profile, this annotation will record + // the name of the profile that created them. + OdigosProfileAnnotation = "odigos.io/profile" ) const ( diff --git a/profiles/attributes/categoryattributes.go b/profiles/attributes/categoryattributes.go index 18859a177f..e49c4b7be1 100644 --- a/profiles/attributes/categoryattributes.go +++ b/profiles/attributes/categoryattributes.go @@ -1,7 +1,6 @@ package attributes import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,5 +9,4 @@ var CategoryAttributesProfile = profile.Profile{ ProfileName: common.ProfileName("category-attributes"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Add category attributes to the spans", - KubeObject: &odigosv1alpha1.Processor{}, } diff --git a/profiles/attributes/copyscope.go b/profiles/attributes/copyscope.go index f00fdef943..cf0fa61f56 100644 --- a/profiles/attributes/copyscope.go +++ b/profiles/attributes/copyscope.go @@ -1,7 +1,6 @@ package attributes import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,5 +9,4 @@ var CopyScopeProfile = profile.Profile{ ProfileName: common.ProfileName("copy-scope"), MinimumTier: common.OdigosTier(common.CommunityOdigosTier), ShortDescription: "Copy the scope name into a separate attribute for backends that do not support scopes", - KubeObject: &odigosv1alpha1.Processor{}, } diff --git a/profiles/attributes/hostnameaspodname.go b/profiles/attributes/hostnameaspodname.go index 6482305c8c..45f845ef1a 100644 --- a/profiles/attributes/hostnameaspodname.go +++ b/profiles/attributes/hostnameaspodname.go @@ -1,7 +1,6 @@ package attributes import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,5 +9,4 @@ var HostnameAsPodNameProfile = profile.Profile{ ProfileName: common.ProfileName("hostname-as-podname"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Populate the spans resource `host.name` attribute with value of `k8s.pod.name`", - KubeObject: &odigosv1alpha1.Processor{}, } diff --git a/profiles/attributes/payloadcollection.go b/profiles/attributes/payloadcollection.go index da592fa23f..9e0d8ed8f3 100644 --- a/profiles/attributes/payloadcollection.go +++ b/profiles/attributes/payloadcollection.go @@ -1,7 +1,6 @@ package attributes import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,12 +9,10 @@ var FullPayloadCollectionProfile = profile.Profile{ ProfileName: common.ProfileName("full-payload-collection"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Collect any payload from the cluster where supported with default settings", - KubeObject: &odigosv1alpha1.InstrumentationRule{}, } var DbPayloadCollectionProfile = profile.Profile{ ProfileName: common.ProfileName("db-payload-collection"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Collect db payload from the cluster where supported with default settings", - KubeObject: &odigosv1alpha1.InstrumentationRule{}, } diff --git a/profiles/attributes/queryoperationdetector.go b/profiles/attributes/queryoperationdetector.go index 393102fccc..20f372f9cf 100644 --- a/profiles/attributes/queryoperationdetector.go +++ b/profiles/attributes/queryoperationdetector.go @@ -1,7 +1,6 @@ package attributes import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,5 +9,4 @@ var QueryOperationDetector = profile.Profile{ ProfileName: common.ProfileName("query-operation-detector"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Detect the SQL operation name from the query text", - KubeObject: &odigosv1alpha1.Processor{}, } diff --git a/profiles/attributes/semconvupgrader.go b/profiles/attributes/semconvupgrader.go index 9320c828a9..e5941c03ba 100644 --- a/profiles/attributes/semconvupgrader.go +++ b/profiles/attributes/semconvupgrader.go @@ -1,7 +1,6 @@ package attributes import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,5 +9,4 @@ var SemconvUpgraderProfile = profile.Profile{ ProfileName: common.ProfileName("semconv"), MinimumTier: common.OdigosTier(common.CommunityOdigosTier), ShortDescription: "Upgrade and align some attribute names to a newer version of the OpenTelemetry semantic conventions", - KubeObject: &odigosv1alpha1.Processor{}, } diff --git a/profiles/go.mod b/profiles/go.mod index ab091c53d0..afb42dc8a2 100644 --- a/profiles/go.mod +++ b/profiles/go.mod @@ -2,62 +2,15 @@ module github.com/odigos-io/odigos/profiles go 1.23.0 -require ( - github.com/odigos-io/odigos/api v0.0.0 - github.com/odigos-io/odigos/common v0.0.0 - k8s.io/apimachinery v0.32.0 - sigs.k8s.io/yaml v1.4.0 -) +require github.com/odigos-io/odigos/common v0.0.0 require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fatih/color v1.10.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.23.0 // indirect - github.com/goccy/go-yaml v1.11.3 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/odigos-io/odigos/k8sutils v0.0.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/x448/float16 v0.8.4 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect - golang.org/x/net v0.30.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/term v0.25.0 // indirect - golang.org/x/text v0.19.0 // indirect - golang.org/x/time v0.7.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/protobuf v1.35.1 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.32.0 // indirect - k8s.io/client-go v0.32.0 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - sigs.k8s.io/controller-runtime v0.19.0 // indirect - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect ) replace ( diff --git a/profiles/go.sum b/profiles/go.sum index a2e67c8d25..9da195a5eb 100644 --- a/profiles/go.sum +++ b/profiles/go.sum @@ -1,198 +1,18 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I= -github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= -github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= -github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= -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/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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= -k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= -k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= -k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/profiles/instrumentation/java-distro.go b/profiles/instrumentation/java-distro.go index 51716bd0e5..d8e274e587 100644 --- a/profiles/instrumentation/java-distro.go +++ b/profiles/instrumentation/java-distro.go @@ -1,7 +1,6 @@ package instrumentation import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -15,5 +14,4 @@ var JavaEbpfInstrumentationsProfile = profile.Profile{ ProfileName: common.ProfileName("java-ebpf-instrumentations"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Instrument Java applications using eBPF instrumentation and eBPF enterprise processing", - KubeObject: &odigosv1alpha1.InstrumentationRule{}, } diff --git a/profiles/manifests/render.go b/profiles/manifests/render.go index 6bd579a75a..816614aa13 100644 --- a/profiles/manifests/render.go +++ b/profiles/manifests/render.go @@ -2,40 +2,26 @@ package manifests import ( "embed" + "errors" "fmt" - "reflect" + "io/fs" - "github.com/odigos-io/odigos/profiles/profile" - "sigs.k8s.io/yaml" + "github.com/odigos-io/odigos/common" ) //go:embed *.yaml var embeddedFiles embed.FS -// GetEmbeddedResourceManifestsAsObjects is a generic function to read embedded YAML files and convert them into runtime.Object -func GetEmbeddedResourceManifestsAsObjects(filename string, obj profile.K8sObject) ([]profile.K8sObject, error) { +func ReadProfileYamlManifests(profileName common.ProfileName) ([][]byte, error) { - // Read the embedded YAML file content + // TODO: allow multiple files per profiles with any name (not just profileName.yaml) + filename := fmt.Sprintf("%s.yaml", profileName) yamlBytes, err := embeddedFiles.ReadFile(filename) if err != nil { - return nil, fmt.Errorf("failed to read embedded file %s: %v", filename, err) + if errors.Is(err, fs.ErrNotExist) { + return [][]byte{}, nil + } } - // Create a new instance of the passed object type - objType := reflect.TypeOf(obj).Elem() - newObj := reflect.New(objType).Interface() - - // Unmarshal the YAML content into the new object - err = yaml.Unmarshal(yamlBytes, newObj) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal YAML: %v", err) - } - - k8sObj, ok := newObj.(profile.K8sObject) - if !ok { - return nil, fmt.Errorf("unmarshaled object is not a k8s object") - } - - // Return the object wrapped in a slice - return []profile.K8sObject{k8sObj}, nil + return [][]byte{yamlBytes}, nil } diff --git a/profiles/pipeline/smallbatches.go b/profiles/pipeline/smallbatches.go index 2a919a35b8..18949bc82f 100644 --- a/profiles/pipeline/smallbatches.go +++ b/profiles/pipeline/smallbatches.go @@ -1,7 +1,6 @@ package pipeline import ( - odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/profiles/profile" ) @@ -10,5 +9,4 @@ var SmallBatchesProfile = profile.Profile{ ProfileName: common.ProfileName("small-batches"), MinimumTier: common.OdigosTier(common.OnPremOdigosTier), ShortDescription: "Reduce the batch size for exports", - KubeObject: &odigosv1alpha1.Processor{}, } diff --git a/profiles/profile/profile.go b/profiles/profile/profile.go index 84c2ec29b1..b845ece741 100644 --- a/profiles/profile/profile.go +++ b/profiles/profile/profile.go @@ -2,21 +2,21 @@ package profile import ( "github.com/odigos-io/odigos/common" - "k8s.io/apimachinery/pkg/runtime" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type Profile struct { ProfileName common.ProfileName MinimumTier common.OdigosTier ShortDescription string - KubeObject K8sObject // used to read it from the embedded YAML file Dependencies []common.ProfileName // other profiles that are applied by the current profile ModifyConfigFunc func(*common.OdigosConfiguration) // function to update the configuration based on the profile } -type K8sObject interface { - metav1.Object - runtime.Object +func FindProfileByName(profileName common.ProfileName, profiles []Profile) *Profile { + for i := range profiles { + if profiles[i].ProfileName == profileName { + return &profiles[i] + } + } + return nil } diff --git a/scheduler/controllers/odigosconfig/manager.go b/scheduler/controllers/odigosconfig/manager.go index 35bc3dcf86..3f9804d5f7 100644 --- a/scheduler/controllers/odigosconfig/manager.go +++ b/scheduler/controllers/odigosconfig/manager.go @@ -4,19 +4,22 @@ import ( "github.com/odigos-io/odigos/common" odigospredicates "github.com/odigos-io/odigos/k8sutils/pkg/predicate" corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/dynamic" ctrl "sigs.k8s.io/controller-runtime" ) -func SetupWithManager(mgr ctrl.Manager, tier common.OdigosTier) error { +func SetupWithManager(mgr ctrl.Manager, tier common.OdigosTier, odigosVersion string, dynamicClient *dynamic.DynamicClient) error { err := ctrl.NewControllerManagedBy(mgr). For(&corev1.ConfigMap{}). Named("odigosconfig-odigosconfig"). WithEventFilter(&odigospredicates.OdigosConfigMapPredicate). Complete(&odigosConfigController{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Tier: tier, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Tier: tier, + OdigosVersion: odigosVersion, + DynamicClient: dynamicClient, }) if err != nil { return err diff --git a/scheduler/controllers/odigosconfig/odigosconfig_controller.go b/scheduler/controllers/odigosconfig/odigosconfig_controller.go index 8d66a48b38..f2056e3750 100644 --- a/scheduler/controllers/odigosconfig/odigosconfig_controller.go +++ b/scheduler/controllers/odigosconfig/odigosconfig_controller.go @@ -2,18 +2,25 @@ package odigosconfig import ( "context" + "fmt" + odigosv1alpha1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" "github.com/odigos-io/odigos/common" "github.com/odigos-io/odigos/common/consts" k8sconsts "github.com/odigos-io/odigos/k8sutils/pkg/consts" "github.com/odigos-io/odigos/k8sutils/pkg/env" "github.com/odigos-io/odigos/profiles" - "github.com/odigos-io/odigos/profiles/profile" + "github.com/odigos-io/odigos/profiles/manifests" "github.com/odigos-io/odigos/profiles/sizing" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/dynamic" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" @@ -21,8 +28,10 @@ import ( type odigosConfigController struct { client.Client - Scheme *runtime.Scheme - Tier common.OdigosTier + Scheme *runtime.Scheme + Tier common.OdigosTier + OdigosVersion string + DynamicClient *dynamic.DynamicClient } func (r *odigosConfigController) Reconcile(ctx context.Context, _ ctrl.Request) (ctrl.Result, error) { @@ -32,6 +41,16 @@ func (r *odigosConfigController) Reconcile(ctx context.Context, _ ctrl.Request) return ctrl.Result{}, err } + // effective profiles are what is actually used in the cluster (minus non existing profiles and plus dependencies) + availableProfiles := profiles.GetAvailableProfilesForTier(r.Tier) + effectiveProfiles := calculateEffectiveProfiles(odigosConfig.Profiles, availableProfiles) + + // apply the current profiles list to the cluster + err = r.applyProfileManifests(ctx, effectiveProfiles) + if err != nil { + return ctrl.Result{}, err + } + // make sure the default ignored namespaces are always present odigosConfig.IgnoredNamespaces = mergeIgnoredItemLists(odigosConfig.IgnoredNamespaces, k8sconsts.DefaultIgnoredNamespaces) odigosConfig.IgnoredNamespaces = append(odigosConfig.IgnoredNamespaces, env.GetCurrentNamespace()) @@ -39,11 +58,8 @@ func (r *odigosConfigController) Reconcile(ctx context.Context, _ ctrl.Request) // make sure the default ignored containers are always present odigosConfig.IgnoredContainers = mergeIgnoredItemLists(odigosConfig.IgnoredContainers, k8sconsts.DefaultIgnoredContainers) - // effective profiles are what is actually used in the cluster - availableProfiles := profiles.GetAvailableProfilesForTier(r.Tier) - effectiveProfiles := calculateEffectiveProfiles(odigosConfig.Profiles, availableProfiles) - odigosConfig.Profiles = effectiveProfiles modifyConfigWithEffectiveProfiles(effectiveProfiles, odigosConfig) + odigosConfig.Profiles = effectiveProfiles // if none of the profiles set sizing for collectors, use size_s as default, so the values are never nil // if the values were already set (by user or profile) this is a no-op @@ -117,45 +133,109 @@ func (r *odigosConfigController) persistEffectiveConfig(ctx context.Context, eff return nil } -func modifyConfigWithEffectiveProfiles(effectiveProfiles []common.ProfileName, odigosConfig *common.OdigosConfiguration) { +func (r *odigosConfigController) applyProfileManifests(ctx context.Context, effectiveProfiles []common.ProfileName) error { + + profileDeploymentHash := calculateProfilesDeploymentHash(effectiveProfiles, r.OdigosVersion) + for _, profileName := range effectiveProfiles { - p := profiles.ProfilesByName[profileName] - if p.ModifyConfigFunc != nil { - p.ModifyConfigFunc(odigosConfig) + + yamls, err := manifests.ReadProfileYamlManifests(profileName) + if err != nil { + return err + } + + for _, yamlBytes := range yamls { + err = r.applySingleProfileManifest(ctx, profileName, yamlBytes, profileDeploymentHash) + if err != nil { + return err + } } } -} -// from the list of input profiles, calculate the effective profiles: -// - check the dependencies of each profile and add them to the list -// - remove profiles which are not present in the profiles list -func calculateEffectiveProfiles(configProfiles []common.ProfileName, availableProfiles []profile.Profile) []common.ProfileName { + // after we applied all the current profiles, we need to deleted resources + // which did not participate in the current deployment. + // we will delete any resource with the "odigos.io/profiles-hash" label which is not the current hash. + differentHashSelector, _ := labels.NewRequirement(k8sconsts.OdigosProfilesHashLabel, selection.NotEquals, []string{profileDeploymentHash}) + differentHashLabelSelector := labels.NewSelector().Add(*differentHashSelector) + listOptions := &client.ListOptions{LabelSelector: differentHashLabelSelector, Namespace: env.GetCurrentNamespace()} - effectiveProfiles := []common.ProfileName{} - for _, profileName := range configProfiles { + processesList := odigosv1alpha1.ProcessorList{} + err := r.Client.List(ctx, &processesList, listOptions) + if err != nil { + return err + } + // TODO: migrate to DeleteAllOf once we drop support for old k8s versions + for i := range processesList.Items { + err = r.Client.Delete(ctx, &processesList.Items[i]) + if err != nil { + return err + } + } - // ignored missing profiles (either not available for tier or typos) - p, found := findProfileNameInAvailableList(profileName, availableProfiles) - if !found { - continue + instrumentationRulesList := odigosv1alpha1.InstrumentationRuleList{} + err = r.Client.List(ctx, &instrumentationRulesList, listOptions) + if err != nil { + return err + } + for i := range instrumentationRulesList.Items { + err = r.Client.Delete(ctx, &instrumentationRulesList.Items[i]) + if err != nil { + return err } + } - effectiveProfiles = append(effectiveProfiles, profileName) + return nil +} - // if this profile has dependencies, add them to the list - if p.Dependencies != nil { - effectiveProfiles = append(effectiveProfiles, calculateEffectiveProfiles(p.Dependencies, availableProfiles)...) - } +func (r *odigosConfigController) applySingleProfileManifest(ctx context.Context, profileName common.ProfileName, yamlBytes []byte, profileDeploymentHash string) error { + + obj := &unstructured.Unstructured{} + err := yaml.Unmarshal(yamlBytes, obj) + if err != nil { + return err + } + + labels := obj.GetLabels() + if labels == nil { + labels = make(map[string]string) } - return effectiveProfiles + labels[k8sconsts.OdigosProfilesHashLabel] = profileDeploymentHash + obj.SetLabels(labels) + + annotations := obj.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + annotations[k8sconsts.OdigosProfileAnnotation] = string(profileName) + obj.SetAnnotations(annotations) + + gvk := obj.GroupVersionKind() + resource, found := supportedKindToResource[gvk.Kind] + if !found { + return fmt.Errorf("unsupported kind for profile manifest %s", gvk.Kind) + } + gvr := schema.GroupVersionResource{ + Group: gvk.Group, + Version: gvk.Version, + Resource: resource, + } + + resourceClient := r.DynamicClient.Resource(gvr).Namespace(env.GetCurrentNamespace()) + _, err = resourceClient.Apply(ctx, obj.GetName(), obj, metav1.ApplyOptions{ + FieldManager: "scheduler-odigosconfig", + }) + if err != nil { + return err + } + + return nil } -func findProfileNameInAvailableList(profileName common.ProfileName, availableProfiles []profile.Profile) (profile.Profile, bool) { - // there aren't many profiles, so a linear search is fine - for _, p := range availableProfiles { - if p.ProfileName == profileName { - return p, true +func modifyConfigWithEffectiveProfiles(effectiveProfiles []common.ProfileName, odigosConfig *common.OdigosConfiguration) { + for _, profileName := range effectiveProfiles { + p := profiles.ProfilesByName[profileName] + if p.ModifyConfigFunc != nil { + p.ModifyConfigFunc(odigosConfig) } } - return profile.Profile{}, false } diff --git a/scheduler/controllers/odigosconfig/profileutils.go b/scheduler/controllers/odigosconfig/profileutils.go new file mode 100644 index 0000000000..19ce97ac35 --- /dev/null +++ b/scheduler/controllers/odigosconfig/profileutils.go @@ -0,0 +1,61 @@ +package odigosconfig + +import ( + "crypto/sha256" + "encoding/hex" + "sort" + "strings" + + "github.com/odigos-io/odigos/common" + "github.com/odigos-io/odigos/profiles/profile" +) + +var supportedKindToResource = map[string]string{ + "Processor": "processors", + "InstrumentationRule": "instrumentationrules", +} + +// when applying the manifests, we need to mark the new resources so we know to cleanup +// previous resources which are not relevant after the new profiles are applied. +// this hash is used to mark the resources. +func calculateProfilesDeploymentHash(profiles []common.ProfileName, odigosVersion string) string { + + // convert profiles to a list of strings and sort it for consistency + sortedProfiles := make([]string, len(profiles)+1) + for i, p := range profiles { + sortedProfiles[i] = string(p) + } + sortedProfiles[len(profiles)] = odigosVersion + sort.Strings(sortedProfiles) + + // Concatenate the sorted strings to create a hash + concatenated := strings.Join(sortedProfiles, "") + hash := sha256.Sum256([]byte(concatenated)) + + // Return the hash as a hex string + return hex.EncodeToString(hash[:16]) +} + +// from the list of input profiles, calculate the effective profiles: +// - check the dependencies of each profile and add them to the list +// - remove profiles which are not present in the profiles list +func calculateEffectiveProfiles(configProfiles []common.ProfileName, availableProfiles []profile.Profile) []common.ProfileName { + + effectiveProfiles := []common.ProfileName{} + for _, profileName := range configProfiles { + + // ignored missing profiles (either not available for tier or typos) + p := profile.FindProfileByName(profileName, availableProfiles) + if p == nil { + continue + } + + effectiveProfiles = append(effectiveProfiles, profileName) + + // if this profile has dependencies, add them to the list + if p.Dependencies != nil { + effectiveProfiles = append(effectiveProfiles, calculateEffectiveProfiles(p.Dependencies, availableProfiles)...) + } + } + return effectiveProfiles +} diff --git a/scheduler/main.go b/scheduler/main.go index a8bb7782d4..7decbf30b4 100644 --- a/scheduler/main.go +++ b/scheduler/main.go @@ -31,10 +31,12 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth" odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1" + "github.com/odigos-io/odigos/common/consts" "github.com/odigos-io/odigos/k8sutils/pkg/env" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/dynamic" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" @@ -77,8 +79,10 @@ func main() { logger := zapr.NewLogger(zapLogger) ctrl.SetLogger(logger) - tier := env.GetOdigosTierFromEnv() odigosNs := env.GetCurrentNamespace() + tier := env.GetOdigosTierFromEnv() + odigosVersion := os.Getenv(consts.OdigosVersionEnvVarName) + nsSelector := client.InNamespace(odigosNs).AsSelector() mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ @@ -98,6 +102,12 @@ func main() { &odigosv1.Destination{}: { Field: nsSelector, }, + &odigosv1.Processor{}: { + Field: nsSelector, + }, + &odigosv1.InstrumentationRule{}: { + Field: nsSelector, + }, }, }, HealthProbeBindAddress: probeAddr, @@ -109,6 +119,13 @@ func main() { os.Exit(1) } + // create dynamic k8s client to apply profile manifests + dyanmicClient, err := dynamic.NewForConfig(mgr.GetConfig()) + if err != nil { + setupLog.Error(err, "unable to create dynamic client") + os.Exit(1) + } + err = clustercollectorsgroup.SetupWithManager(mgr) if err != nil { setupLog.Error(err, "unable to create controllers for cluster collectors group") @@ -119,7 +136,7 @@ func main() { setupLog.Error(err, "unable to create controllers for node collectors group") os.Exit(1) } - err = odigosconfig.SetupWithManager(mgr, tier) + err = odigosconfig.SetupWithManager(mgr, tier, odigosVersion, dyanmicClient) if err != nil { setupLog.Error(err, "unable to create controllers for odigos config") os.Exit(1)