Skip to content

Commit 192cd9d

Browse files
committed
Create KubernetesAgent component to install the agent in Kubernetes
1 parent ddba83b commit 192cd9d

File tree

2 files changed

+282
-0
lines changed

2 files changed

+282
-0
lines changed
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package agent
2+
3+
import (
4+
"github.com/pulumi/pulumi-kubernetes/sdk/v3/go/kubernetes"
5+
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
6+
7+
"github.com/DataDog/test-infra-definitions/common/config"
8+
"github.com/DataDog/test-infra-definitions/components"
9+
"github.com/DataDog/test-infra-definitions/components/datadog/kubernetesagentparams"
10+
)
11+
12+
type KubernetesAgentOutput struct {
13+
components.JSONImporter
14+
15+
AgentInstallName string `json:"agentInstallName"`
16+
AgentInstallNameWindows string `json:"agentInstallNameWindows"`
17+
}
18+
19+
// DockerAgent is a Docker installer on a remote Host
20+
type KubernetesAgent struct {
21+
pulumi.ResourceState
22+
components.Component
23+
24+
AgentInstallName pulumi.StringOutput `pulumi:"agentInstallName"`
25+
AgentInstallNameWindows pulumi.StringOutput `pulumi:"agentInstallNameWindows"`
26+
}
27+
28+
func (h *KubernetesAgent) Export(ctx *pulumi.Context, out *KubernetesAgentOutput) error {
29+
return components.Export(ctx, h, out)
30+
}
31+
32+
func NewKubernetesAgent(e config.CommonEnvironment, clusterName string, kubeProvider *kubernetes.Provider, options ...kubernetesagentparams.Option) (*KubernetesAgent, error) {
33+
return components.NewComponent(e, clusterName, func(comp *KubernetesAgent) error {
34+
params, err := kubernetesagentparams.NewParams(&e, options...)
35+
if err != nil {
36+
return err
37+
}
38+
helmComponent, err := NewHelmInstallation(e, HelmInstallationArgs{
39+
KubeProvider: kubeProvider,
40+
Namespace: params.Namespace,
41+
ValuesYAML: params.HelmValues,
42+
}, params.PulumiDependsOn...)
43+
if err != nil {
44+
return err
45+
}
46+
47+
// Fill component
48+
comp.AgentInstallName = helmComponent.LinuxHelmReleaseName.Elem()
49+
comp.AgentInstallNameWindows = helmComponent.WindowsHelmReleaseName.Elem()
50+
return nil
51+
})
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
package kubernetesagentparams
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/DataDog/test-infra-definitions/common"
9+
"github.com/DataDog/test-infra-definitions/common/config"
10+
"github.com/DataDog/test-infra-definitions/common/utils"
11+
"github.com/DataDog/test-infra-definitions/components/datadog/fakeintake"
12+
"github.com/DataDog/test-infra-definitions/components/docker"
13+
14+
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
15+
)
16+
17+
const (
18+
defaultAgentNamespace = "datadog"
19+
)
20+
21+
// Params defines the parameters for the Kubernetes Agent installation.
22+
// The Params configuration uses the [Functional options pattern].
23+
//
24+
// The available options are:
25+
// - [WithImageTag]
26+
// - [WithRepository]
27+
// - [WithFullImagePath]
28+
// - [WithPulumiDependsOn]
29+
// - [WithEnvironmentVariables]
30+
// - [WithAgentServiceEnvVariable]
31+
// - [WithHostName]
32+
// - [WithFakeintake]
33+
// - [WithLogs]
34+
// - [WithExtraComposeManifest]
35+
//
36+
// [Functional options pattern]: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
37+
38+
type Params struct {
39+
// FullImagePath is the full path of the docker agent image to use.
40+
// It has priority over ImageTag and Repository.
41+
FullImagePath string
42+
// ImageTag is the docker agent image tag to use.
43+
ImageTag string
44+
// Repository is the docker repository to use.
45+
Repository string
46+
// Namespace is the namespace to deploy the agent to.
47+
Namespace string
48+
// AgentServiceEnvironment is a map of environment variables to set in the docker compose agent service's environment.
49+
AgentServiceEnvironment pulumi.Map
50+
// ExtraComposeManifests is a list of extra docker compose manifests to add beside the agent service.
51+
ExtraComposeManifests []docker.ComposeInlineManifest
52+
// EnvironmentVariables is a map of environment variables to set with the docker-compose context
53+
EnvironmentVariables pulumi.StringMap
54+
// HelmValues is the Helm values to use for the agent installation.
55+
HelmValues pulumi.AssetOrArchiveArray
56+
// PulumiDependsOn is a list of resources to depend on.
57+
PulumiDependsOn []pulumi.ResourceOption
58+
}
59+
60+
type Option = func(*Params) error
61+
62+
func NewParams(e *config.CommonEnvironment, options ...Option) (*Params, error) {
63+
version := &Params{
64+
Namespace: defaultAgentNamespace,
65+
AgentServiceEnvironment: pulumi.Map{},
66+
EnvironmentVariables: pulumi.StringMap{},
67+
}
68+
69+
if e.PipelineID() != "" && e.CommitSHA() != "" {
70+
options = append(options, WithFullImagePath(utils.BuildDockerImagePath("669783387624.dkr.ecr.us-east-1.amazonaws.com/agent", fmt.Sprintf("%s-%s", e.PipelineID(), e.CommitSHA()))))
71+
}
72+
73+
return common.ApplyOption(version, options)
74+
}
75+
76+
// WithImageTag sets the agent image tag to use.
77+
func WithImageTag(agentImageTag string) func(*Params) error {
78+
return func(p *Params) error {
79+
p.ImageTag = agentImageTag
80+
return nil
81+
}
82+
}
83+
84+
// WithRepository sets the repository to use for the agent installation.
85+
func WithRepository(repository string) func(*Params) error {
86+
return func(p *Params) error {
87+
p.Repository = repository
88+
return nil
89+
}
90+
}
91+
92+
// WithFullImagePath sets the full path of the agent image to use.
93+
func WithFullImagePath(fullImagePath string) func(*Params) error {
94+
return func(p *Params) error {
95+
p.FullImagePath = fullImagePath
96+
return nil
97+
}
98+
}
99+
100+
// WithNamespace sets the namespace to deploy the agent to.
101+
func WithNamespace(namespace string) func(*Params) error {
102+
return func(p *Params) error {
103+
p.Namespace = namespace
104+
return nil
105+
}
106+
}
107+
108+
// WithPulumiDependsOn sets the resources to depend on.
109+
func WithPulumiDependsOn(resources ...pulumi.ResourceOption) func(*Params) error {
110+
return func(p *Params) error {
111+
p.PulumiDependsOn = resources
112+
return nil
113+
}
114+
}
115+
116+
// WithEnvironmentVariables sets the environment variables to use for the agent installation.
117+
func WithEnvironmentVariables(environmentVariables pulumi.StringMap) func(*Params) error {
118+
return func(p *Params) error {
119+
p.EnvironmentVariables = environmentVariables
120+
return nil
121+
}
122+
}
123+
124+
// WithAgentServiceEnvVariable set an environment variable in the docker compose agent service's environment.
125+
func WithAgentServiceEnvVariable(key string, value pulumi.Input) func(*Params) error {
126+
return func(p *Params) error {
127+
p.AgentServiceEnvironment[key] = value
128+
return nil
129+
}
130+
}
131+
132+
// WithHelmValues sets the Helm values to use for the agent installation.
133+
func WithHelmValues(values string) func(*Params) error {
134+
return func(p *Params) error {
135+
p.HelmValues = pulumi.AssetOrArchiveArray{pulumi.NewStringAsset(values)}
136+
return nil
137+
}
138+
}
139+
140+
// WithIntake configures the agent to use the given hostname as intake.
141+
// The hostname must be a valid Datadog intake, with a SSL valid certificate
142+
//
143+
// To use a fakeintake, see WithFakeintake.
144+
//
145+
// This option is overwritten by `WithFakeintake`.
146+
func WithIntake(hostname string) func(*Params) error {
147+
return withIntakeHostname(pulumi.String(hostname), false)
148+
}
149+
150+
// WithFakeintake installs the fake intake and configures the Agent to use it.
151+
//
152+
// This option is overwritten by `WithIntakeHostname`.
153+
func WithFakeintake(fakeintake *fakeintake.Fakeintake) func(*Params) error {
154+
return withIntakeHostname(fakeintake.Host, true)
155+
}
156+
157+
func withIntakeHostname(hostname pulumi.StringInput, shouldSkipSSLCertificateValidation bool) func(*Params) error {
158+
shouldEnforceHTTPInput := hostname.ToStringOutput().ApplyT(func(host string) (bool, error) {
159+
return strings.HasPrefix(host, "https"), nil
160+
}).(pulumi.BoolOutput)
161+
return func(p *Params) error {
162+
envVars := pulumi.Map{
163+
"DD_DD_URL": pulumi.Sprintf("http://%s:80", hostname),
164+
"DD_LOGS_CONFIG_DD_URL": pulumi.Sprintf("%s:80", hostname),
165+
"DD_PROCESS_CONFIG_PROCESS_DD_URL": pulumi.Sprintf("http://%s:80", hostname),
166+
"DD_APM_DD_URL": pulumi.Sprintf("http://%s:80", hostname),
167+
"DD_SKIP_SSL_VALIDATION": pulumi.Bool(shouldSkipSSLCertificateValidation),
168+
"DD_REMOTE_CONFIGURATION_NO_TLS_VALIDATION": pulumi.Bool(shouldSkipSSLCertificateValidation),
169+
"DD_LOGS_CONFIG_LOGS_NO_SSL": pulumi.Bool(shouldSkipSSLCertificateValidation),
170+
"DD_LOGS_CONFIG_FORCE_USE_HTTP": shouldEnforceHTTPInput,
171+
}
172+
for key, value := range envVars {
173+
if err := WithAgentServiceEnvVariable(key, value)(p); err != nil {
174+
return err
175+
}
176+
}
177+
return nil
178+
}
179+
}
180+
181+
type additionalLogEndpointInput struct {
182+
Hostname string `json:"host"`
183+
APIKey string `json:"api_key,omitempty"`
184+
Port string `json:"port,omitempty"`
185+
IsReliable bool `json:"is_reliable,omitempty"`
186+
}
187+
188+
func WithAdditionalFakeintake(fakeintake *fakeintake.Fakeintake) func(*Params) error {
189+
additionalEndpointsContentInput := fakeintake.Host.ToStringOutput().ApplyT(func(host string) (string, error) {
190+
endpoints := map[string][]string{
191+
fmt.Sprintf("https://%s", host): {"00000000000000000000000000000000"},
192+
}
193+
194+
jsonContent, err := json.Marshal(endpoints)
195+
return string(jsonContent), err
196+
}).(pulumi.StringOutput)
197+
additionalLogsEndpointsContentInput := fakeintake.Host.ToStringOutput().ApplyT(func(host string) (string, error) {
198+
endpoints := []additionalLogEndpointInput{
199+
{
200+
Hostname: host,
201+
},
202+
}
203+
jsonContent, err := json.Marshal(endpoints)
204+
return string(jsonContent), err
205+
}).(pulumi.StringOutput)
206+
shouldEnforceHTTPInput := fakeintake.Host.ToStringOutput().ApplyT(func(host string) (bool, error) {
207+
return strings.HasPrefix(host, "https"), nil
208+
}).(pulumi.BoolOutput)
209+
return func(p *Params) error {
210+
logsEnvVars := pulumi.Map{
211+
"DD_ADDITIONAL_ENDPOINTS": additionalEndpointsContentInput,
212+
"DD_LOGS_CONFIG_ADDITIONAL_ENDPOINTS": additionalLogsEndpointsContentInput,
213+
"DD_SKIP_SSL_VALIDATION": pulumi.Bool(true),
214+
"DD_REMOTE_CONFIGURATION_NO_TLS_VALIDATION": pulumi.Bool(true),
215+
"DD_LOGS_CONFIG_LOGS_NO_SSL": pulumi.Bool(true),
216+
"DD_LOGS_CONFIG_FORCE_USE_HTTP": shouldEnforceHTTPInput,
217+
}
218+
for key, value := range logsEnvVars {
219+
if err := WithAgentServiceEnvVariable(key, value)(p); err != nil {
220+
return err
221+
}
222+
}
223+
return nil
224+
}
225+
}
226+
227+
// WithLogs enables the log agent
228+
func WithLogs() func(*Params) error {
229+
return WithAgentServiceEnvVariable("DD_LOGS_ENABLED", pulumi.String("true"))
230+
}

0 commit comments

Comments
 (0)