-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create KubernetesAgent component to install the agent in Kubernetes
- Loading branch information
1 parent
ddba83b
commit 192cd9d
Showing
2 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package agent | ||
|
||
import ( | ||
"github.com/pulumi/pulumi-kubernetes/sdk/v3/go/kubernetes" | ||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi" | ||
|
||
"github.com/DataDog/test-infra-definitions/common/config" | ||
"github.com/DataDog/test-infra-definitions/components" | ||
"github.com/DataDog/test-infra-definitions/components/datadog/kubernetesagentparams" | ||
) | ||
|
||
type KubernetesAgentOutput struct { | ||
components.JSONImporter | ||
|
||
AgentInstallName string `json:"agentInstallName"` | ||
AgentInstallNameWindows string `json:"agentInstallNameWindows"` | ||
} | ||
|
||
// DockerAgent is a Docker installer on a remote Host | ||
type KubernetesAgent struct { | ||
pulumi.ResourceState | ||
components.Component | ||
|
||
AgentInstallName pulumi.StringOutput `pulumi:"agentInstallName"` | ||
AgentInstallNameWindows pulumi.StringOutput `pulumi:"agentInstallNameWindows"` | ||
} | ||
|
||
func (h *KubernetesAgent) Export(ctx *pulumi.Context, out *KubernetesAgentOutput) error { | ||
return components.Export(ctx, h, out) | ||
} | ||
|
||
func NewKubernetesAgent(e config.CommonEnvironment, clusterName string, kubeProvider *kubernetes.Provider, options ...kubernetesagentparams.Option) (*KubernetesAgent, error) { | ||
return components.NewComponent(e, clusterName, func(comp *KubernetesAgent) error { | ||
params, err := kubernetesagentparams.NewParams(&e, options...) | ||
if err != nil { | ||
return err | ||
} | ||
helmComponent, err := NewHelmInstallation(e, HelmInstallationArgs{ | ||
KubeProvider: kubeProvider, | ||
Namespace: params.Namespace, | ||
ValuesYAML: params.HelmValues, | ||
}, params.PulumiDependsOn...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Fill component | ||
comp.AgentInstallName = helmComponent.LinuxHelmReleaseName.Elem() | ||
comp.AgentInstallNameWindows = helmComponent.WindowsHelmReleaseName.Elem() | ||
return nil | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package kubernetesagentparams | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/DataDog/test-infra-definitions/common" | ||
"github.com/DataDog/test-infra-definitions/common/config" | ||
"github.com/DataDog/test-infra-definitions/common/utils" | ||
"github.com/DataDog/test-infra-definitions/components/datadog/fakeintake" | ||
"github.com/DataDog/test-infra-definitions/components/docker" | ||
|
||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi" | ||
) | ||
|
||
const ( | ||
defaultAgentNamespace = "datadog" | ||
) | ||
|
||
// Params defines the parameters for the Kubernetes Agent installation. | ||
// The Params configuration uses the [Functional options pattern]. | ||
// | ||
// The available options are: | ||
// - [WithImageTag] | ||
// - [WithRepository] | ||
// - [WithFullImagePath] | ||
// - [WithPulumiDependsOn] | ||
// - [WithEnvironmentVariables] | ||
// - [WithAgentServiceEnvVariable] | ||
// - [WithHostName] | ||
// - [WithFakeintake] | ||
// - [WithLogs] | ||
// - [WithExtraComposeManifest] | ||
// | ||
// [Functional options pattern]: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis | ||
|
||
type Params struct { | ||
// FullImagePath is the full path of the docker agent image to use. | ||
// It has priority over ImageTag and Repository. | ||
FullImagePath string | ||
// ImageTag is the docker agent image tag to use. | ||
ImageTag string | ||
// Repository is the docker repository to use. | ||
Repository string | ||
// Namespace is the namespace to deploy the agent to. | ||
Namespace string | ||
// AgentServiceEnvironment is a map of environment variables to set in the docker compose agent service's environment. | ||
AgentServiceEnvironment pulumi.Map | ||
// ExtraComposeManifests is a list of extra docker compose manifests to add beside the agent service. | ||
ExtraComposeManifests []docker.ComposeInlineManifest | ||
// EnvironmentVariables is a map of environment variables to set with the docker-compose context | ||
EnvironmentVariables pulumi.StringMap | ||
// HelmValues is the Helm values to use for the agent installation. | ||
HelmValues pulumi.AssetOrArchiveArray | ||
// PulumiDependsOn is a list of resources to depend on. | ||
PulumiDependsOn []pulumi.ResourceOption | ||
} | ||
|
||
type Option = func(*Params) error | ||
|
||
func NewParams(e *config.CommonEnvironment, options ...Option) (*Params, error) { | ||
version := &Params{ | ||
Namespace: defaultAgentNamespace, | ||
AgentServiceEnvironment: pulumi.Map{}, | ||
EnvironmentVariables: pulumi.StringMap{}, | ||
} | ||
|
||
if e.PipelineID() != "" && e.CommitSHA() != "" { | ||
options = append(options, WithFullImagePath(utils.BuildDockerImagePath("669783387624.dkr.ecr.us-east-1.amazonaws.com/agent", fmt.Sprintf("%s-%s", e.PipelineID(), e.CommitSHA())))) | ||
} | ||
|
||
return common.ApplyOption(version, options) | ||
} | ||
|
||
// WithImageTag sets the agent image tag to use. | ||
func WithImageTag(agentImageTag string) func(*Params) error { | ||
return func(p *Params) error { | ||
p.ImageTag = agentImageTag | ||
return nil | ||
} | ||
} | ||
|
||
// WithRepository sets the repository to use for the agent installation. | ||
func WithRepository(repository string) func(*Params) error { | ||
return func(p *Params) error { | ||
p.Repository = repository | ||
return nil | ||
} | ||
} | ||
|
||
// WithFullImagePath sets the full path of the agent image to use. | ||
func WithFullImagePath(fullImagePath string) func(*Params) error { | ||
return func(p *Params) error { | ||
p.FullImagePath = fullImagePath | ||
return nil | ||
} | ||
} | ||
|
||
// WithNamespace sets the namespace to deploy the agent to. | ||
func WithNamespace(namespace string) func(*Params) error { | ||
return func(p *Params) error { | ||
p.Namespace = namespace | ||
return nil | ||
} | ||
} | ||
|
||
// WithPulumiDependsOn sets the resources to depend on. | ||
func WithPulumiDependsOn(resources ...pulumi.ResourceOption) func(*Params) error { | ||
return func(p *Params) error { | ||
p.PulumiDependsOn = resources | ||
return nil | ||
} | ||
} | ||
|
||
// WithEnvironmentVariables sets the environment variables to use for the agent installation. | ||
func WithEnvironmentVariables(environmentVariables pulumi.StringMap) func(*Params) error { | ||
return func(p *Params) error { | ||
p.EnvironmentVariables = environmentVariables | ||
return nil | ||
} | ||
} | ||
|
||
// WithAgentServiceEnvVariable set an environment variable in the docker compose agent service's environment. | ||
func WithAgentServiceEnvVariable(key string, value pulumi.Input) func(*Params) error { | ||
return func(p *Params) error { | ||
p.AgentServiceEnvironment[key] = value | ||
return nil | ||
} | ||
} | ||
|
||
// WithHelmValues sets the Helm values to use for the agent installation. | ||
func WithHelmValues(values string) func(*Params) error { | ||
return func(p *Params) error { | ||
p.HelmValues = pulumi.AssetOrArchiveArray{pulumi.NewStringAsset(values)} | ||
return nil | ||
} | ||
} | ||
|
||
// WithIntake configures the agent to use the given hostname as intake. | ||
// The hostname must be a valid Datadog intake, with a SSL valid certificate | ||
// | ||
// To use a fakeintake, see WithFakeintake. | ||
// | ||
// This option is overwritten by `WithFakeintake`. | ||
func WithIntake(hostname string) func(*Params) error { | ||
return withIntakeHostname(pulumi.String(hostname), false) | ||
} | ||
|
||
// WithFakeintake installs the fake intake and configures the Agent to use it. | ||
// | ||
// This option is overwritten by `WithIntakeHostname`. | ||
func WithFakeintake(fakeintake *fakeintake.Fakeintake) func(*Params) error { | ||
return withIntakeHostname(fakeintake.Host, true) | ||
} | ||
|
||
func withIntakeHostname(hostname pulumi.StringInput, shouldSkipSSLCertificateValidation bool) func(*Params) error { | ||
shouldEnforceHTTPInput := hostname.ToStringOutput().ApplyT(func(host string) (bool, error) { | ||
return strings.HasPrefix(host, "https"), nil | ||
}).(pulumi.BoolOutput) | ||
return func(p *Params) error { | ||
envVars := pulumi.Map{ | ||
"DD_DD_URL": pulumi.Sprintf("http://%s:80", hostname), | ||
"DD_LOGS_CONFIG_DD_URL": pulumi.Sprintf("%s:80", hostname), | ||
"DD_PROCESS_CONFIG_PROCESS_DD_URL": pulumi.Sprintf("http://%s:80", hostname), | ||
"DD_APM_DD_URL": pulumi.Sprintf("http://%s:80", hostname), | ||
"DD_SKIP_SSL_VALIDATION": pulumi.Bool(shouldSkipSSLCertificateValidation), | ||
"DD_REMOTE_CONFIGURATION_NO_TLS_VALIDATION": pulumi.Bool(shouldSkipSSLCertificateValidation), | ||
"DD_LOGS_CONFIG_LOGS_NO_SSL": pulumi.Bool(shouldSkipSSLCertificateValidation), | ||
"DD_LOGS_CONFIG_FORCE_USE_HTTP": shouldEnforceHTTPInput, | ||
} | ||
for key, value := range envVars { | ||
if err := WithAgentServiceEnvVariable(key, value)(p); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
type additionalLogEndpointInput struct { | ||
Hostname string `json:"host"` | ||
APIKey string `json:"api_key,omitempty"` | ||
Port string `json:"port,omitempty"` | ||
IsReliable bool `json:"is_reliable,omitempty"` | ||
} | ||
|
||
func WithAdditionalFakeintake(fakeintake *fakeintake.Fakeintake) func(*Params) error { | ||
additionalEndpointsContentInput := fakeintake.Host.ToStringOutput().ApplyT(func(host string) (string, error) { | ||
endpoints := map[string][]string{ | ||
fmt.Sprintf("https://%s", host): {"00000000000000000000000000000000"}, | ||
} | ||
|
||
jsonContent, err := json.Marshal(endpoints) | ||
return string(jsonContent), err | ||
}).(pulumi.StringOutput) | ||
additionalLogsEndpointsContentInput := fakeintake.Host.ToStringOutput().ApplyT(func(host string) (string, error) { | ||
endpoints := []additionalLogEndpointInput{ | ||
{ | ||
Hostname: host, | ||
}, | ||
} | ||
jsonContent, err := json.Marshal(endpoints) | ||
return string(jsonContent), err | ||
}).(pulumi.StringOutput) | ||
shouldEnforceHTTPInput := fakeintake.Host.ToStringOutput().ApplyT(func(host string) (bool, error) { | ||
return strings.HasPrefix(host, "https"), nil | ||
}).(pulumi.BoolOutput) | ||
return func(p *Params) error { | ||
logsEnvVars := pulumi.Map{ | ||
"DD_ADDITIONAL_ENDPOINTS": additionalEndpointsContentInput, | ||
"DD_LOGS_CONFIG_ADDITIONAL_ENDPOINTS": additionalLogsEndpointsContentInput, | ||
"DD_SKIP_SSL_VALIDATION": pulumi.Bool(true), | ||
"DD_REMOTE_CONFIGURATION_NO_TLS_VALIDATION": pulumi.Bool(true), | ||
"DD_LOGS_CONFIG_LOGS_NO_SSL": pulumi.Bool(true), | ||
"DD_LOGS_CONFIG_FORCE_USE_HTTP": shouldEnforceHTTPInput, | ||
} | ||
for key, value := range logsEnvVars { | ||
if err := WithAgentServiceEnvVariable(key, value)(p); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
// WithLogs enables the log agent | ||
func WithLogs() func(*Params) error { | ||
return WithAgentServiceEnvVariable("DD_LOGS_ENABLED", pulumi.String("true")) | ||
} |