diff --git a/CHANGELOG.md b/CHANGELOG.md index b6dc231ac..dde87b730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,15 @@ - [v0.1.1](#v011) - [v0.1.0](#v010) +## Unreleased + +> Release date: TBD + +### Added + +- Proper `User-Agent` header is now set on outgoing HTTP requests. + [#387](https://github.com/Kong/gateway-operator/pull/387) + ## [v1.3.0] > Release date: 2024-06-24 diff --git a/modules/manager/metadata/metadata.go b/modules/manager/metadata/metadata.go index 0fca1acbe..50c23dcf5 100644 --- a/modules/manager/metadata/metadata.go +++ b/modules/manager/metadata/metadata.go @@ -1,6 +1,11 @@ // Package metadata includes metadata variables for logging and reporting. package metadata +import ( + "fmt" + "strings" +) + // ----------------------------------------------------------------------------- // Controller Manager - Versioning Information // ----------------------------------------------------------------------------- @@ -8,6 +13,16 @@ package metadata // WARNING: moving any of these variables requires changes to both the Makefile // and the Dockerfile which modify them during the link step with -X +// BuildFlavor is the flavor of the build. +type BuildFlavor string + +const ( + // OSSFlavor is the open-source flavor. + OSSFlavor BuildFlavor = "oss" + // EEFlavor is the enterprise flavor. + EEFlavor BuildFlavor = "enterprise" +) + // Info is a struct type that holds the metadata for the controller manager. type Info struct { // Release returns the release version, generally a semver like v1.0.0. @@ -29,7 +44,16 @@ type Info struct { Organization string // Flavor is the flavor of the build. - Flavor string + Flavor BuildFlavor +} + +// UserAgent returns the User-Agent string to use in all HTTP requests made by KGO. +func (inf Info) UserAgent() string { + org := strings.ToLower(inf.Organization) + if inf.Flavor == OSSFlavor { + return fmt.Sprintf("%s-%s-%s/%s", org, inf.ProjectName, OSSFlavor, inf.Release) + } + return fmt.Sprintf("%s-%s/%s", org, inf.ProjectName, inf.Release) } var ( @@ -50,9 +74,6 @@ var ( // Organization is the Kong organization organization = "Kong" - - // Flavor is the flavor of the build. - flavor = "oss" ) // Metadata returns the metadata for the controller manager. @@ -64,6 +85,6 @@ func Metadata() Info { Commit: commit, ProjectName: projectName, Organization: organization, - Flavor: flavor, + Flavor: OSSFlavor, } } diff --git a/modules/manager/run.go b/modules/manager/run.go index d69f6526e..cef10fdee 100644 --- a/modules/manager/run.go +++ b/modules/manager/run.go @@ -36,7 +36,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" @@ -82,7 +81,7 @@ type Config struct { DataPlaneControllerEnabled bool DataPlaneBlueGreenControllerEnabled bool - // Controllers for speciality APIs and experimental features. + // Controllers for specialty APIs and experimental features. AIGatewayControllerEnabled bool // webhook and validation options @@ -156,7 +155,10 @@ func Run( setupLog.Info("leader election disabled") } - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + restCfg := ctrl.GetConfigOrDie() + restCfg.UserAgent = metadata.UserAgent() + + mgr, err := ctrl.NewManager(restCfg, ctrl.Options{ Scheme: scheme, Metrics: server.Options{ BindAddress: cfg.MetricsAddr, @@ -244,7 +246,7 @@ func Run( // Enable anonnymous reporting when configured but not for development builds // to reduce the noise. if cfg.AnonymousReports && !cfg.DevelopmentMode { - stopAnonymousReports, err := setupAnonymousReports(context.Background(), cfg, setupLog, metadata) + stopAnonymousReports, err := setupAnonymousReports(context.Background(), restCfg, setupLog, metadata) if err != nil { setupLog.Error(err, "failed setting up anonymous reports") } else { @@ -353,35 +355,19 @@ func (m *caManager) maybeCreateCACertificate(ctx context.Context) error { return nil } -func getKubeconfig(apiServerPath string, kubeconfig string) (*rest.Config, error) { - config, err := clientcmd.BuildConfigFromFlags(apiServerPath, kubeconfig) - if err != nil { - // Fall back to default client loading rules. - loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() - // if you want to change the loading rules (which files in which order), you can do so here - kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, nil) - return kubeConfig.ClientConfig() - } - return config, nil -} - // setupAnonymousReports sets up and starts the anonymous reporting and returns // a cleanup function and an error. // The caller is responsible to call the returned function - when the returned // error is not nil - to stop the reports sending. -func setupAnonymousReports(ctx context.Context, cfg Config, logger logr.Logger, metadata metadata.Info) (func(), error) { +func setupAnonymousReports(ctx context.Context, restCfg *rest.Config, logger logr.Logger, metadata metadata.Info) (func(), error) { logger.Info("starting anonymous reports") - restConfig, err := getKubeconfig(cfg.APIServerPath, cfg.KubeconfigPath) - if err != nil { - return nil, fmt.Errorf("failed to get kubeconfig: %w", err) - } payload := telemetry.Payload{ "v": metadata.Release, "flavor": metadata.Flavor, } - tMgr, err := telemetry.CreateManager(telemetry.SignalPing, restConfig, logger, payload) + tMgr, err := telemetry.CreateManager(telemetry.SignalPing, restCfg, logger, payload) if err != nil { return nil, fmt.Errorf("failed to create anonymous reports manager: %w", err) }