diff --git a/CHANGELOG.md b/CHANGELOG.md index 6122acd..dfea077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* Added support for entity namespaces + ## v1.5.0 ### Added diff --git a/src/cmd/pkg/client/client.go b/src/cmd/pkg/client/client.go index c83f0a6..2e88839 100644 --- a/src/cmd/pkg/client/client.go +++ b/src/cmd/pkg/client/client.go @@ -48,6 +48,8 @@ const ( ChronosphereOrgKey = "CHRONOSPHERE_ORG" // fallback for CHRONOSPHERE_ORG_NAME // ChronosphereAPITokenKey is the environment variable that specifies the Chronosphere API token ChronosphereAPITokenKey = "CHRONOSPHERE_API_TOKEN" + // ChronosphereEntityNamespace is the environment variable that specifies the Chronosphere entity namespace + ChronosphereEntityNamespace = "CHRONOSPHERE_ENTITY_NAMESPACE" ) // Clients is a list of clients our generated CLI needs access to. @@ -129,6 +131,7 @@ func (f *Flags) Transport(component transport.Component, basePath string) (*http InsecureSkipVerify: f.InsecureSkipVerify, AllowHTTP: f.AllowHTTP, DefaultBasePath: basePath, + EntityNamespace: f.getEntityNamespace(), }) if err != nil { return nil, err @@ -159,6 +162,13 @@ func (f *Flags) Timeout() time.Duration { return time.Duration(f.TimeoutSeconds) * time.Second } +func (f *Flags) getEntityNamespace() string { + if ns := os.Getenv(ChronosphereEntityNamespace); ns != "" { + return ns + } + return "" +} + func (f *Flags) getAPIToken() (string, error) { if f.APIToken != "" && f.APITokenFilename != "" { return "", errors.New("only one of --api-token and --api-token-filename can be set") diff --git a/src/cmd/pkg/client/client_test.go b/src/cmd/pkg/client/client_test.go index af02712..4f9e4d3 100644 --- a/src/cmd/pkg/client/client_test.go +++ b/src/cmd/pkg/client/client_test.go @@ -228,7 +228,7 @@ func TestClientFlagsTransport(t *testing.T) { assert.NotNil(t, tp.DefaultAuthentication) if tt.wantInsecureSkipVerify { - httpTransport := tp.Transport.(swagger.RequestIDTrailerTransport).RT.(transport.VersionHeaderTransport).Rt.(*http.Transport) //nolint:errcheck + httpTransport := tp.Transport.(swagger.RequestIDTrailerTransport).RT.(transport.CustomHeaderTransport).Rt.(*http.Transport) //nolint:errcheck assert.Equal(t, tt.wantInsecureSkipVerify, httpTransport.TLSClientConfig.InsecureSkipVerify) } }) diff --git a/src/cmd/pkg/transport/transport.go b/src/cmd/pkg/transport/transport.go index bcd82ca..ae70e1a 100644 --- a/src/cmd/pkg/transport/transport.go +++ b/src/cmd/pkg/transport/transport.go @@ -60,6 +60,7 @@ type RuntimeConfig struct { InsecureSkipVerify bool AllowHTTP bool DefaultBasePath string + EntityNamespace string } // New creates a new HTTP transport that can communicate with the Chronosphere API. @@ -104,7 +105,10 @@ func New(config RuntimeConfig) (*httptransport.Runtime, error) { } transport.DefaultAuthentication = httptransport.APIKeyAuth(apiTokenHeader, "header", config.APIToken) - transport.Transport = xswagger.WithRequestIDTrailerTransport(withVersionHeader(config.Component, transport.Transport)) + + transport.Transport = xswagger.WithRequestIDTrailerTransport( + withCustomHeaders(config.Component, config.EntityNamespace, transport.Transport), + ) transport.Consumers[httpruntime.JSONMime] = xswagger.JSONConsumer() transport.Consumers[httpruntime.HTMLMime] = xswagger.TextConsumer() transport.Consumers[httpruntime.TextMime] = xswagger.TextConsumer() @@ -115,18 +119,20 @@ func New(config RuntimeConfig) (*httptransport.Runtime, error) { const userAgentHeader = "User-Agent" -// VersionHeaderTransport is a RoundTripper that adds a User-Agent header to all requests. -type VersionHeaderTransport struct { - agent string - Rt http.RoundTripper +// CustomHeaderTransport is a RoundTripper that adds a custom headres to all requests +// for example: User-Agent, and Chrono-Entity-Namespace +type CustomHeaderTransport struct { + agent string + entityNamespace string + Rt http.RoundTripper } -func withVersionHeader(component Component, rt http.RoundTripper) http.RoundTripper { +func withCustomHeaders(component Component, entityNamespace string, rt http.RoundTripper) http.RoundTripper { if rt == nil { rt = http.DefaultTransport } - return VersionHeaderTransport{ + return CustomHeaderTransport{ Rt: rt, agent: fmt.Sprintf("%s/%v-%v (%s; %s; %s)", component, @@ -136,11 +142,15 @@ func withVersionHeader(component Component, rt http.RoundTripper) http.RoundTrip runtime.GOOS, runtime.GOARCH, ), + entityNamespace: entityNamespace, } } // RoundTrip implements the RoundTripper interface. -func (v VersionHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error) { - req.Header.Set(userAgentHeader, v.agent) - return v.Rt.RoundTrip(req) +func (c CustomHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req.Header.Set(userAgentHeader, c.agent) + if c.entityNamespace != "" { + req.Header.Set("Chrono-Entity-Namespace", c.entityNamespace) + } + return c.Rt.RoundTrip(req) }