Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Podman based local host #1240

Merged
merged 11 commits into from
Nov 27, 2024
3 changes: 3 additions & 0 deletions common/config/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,11 @@ type Env interface {
CloudEnv
}
type CloudEnv interface {
// InternalDockerhubMirror returns the internal Dockerhub mirror.
InternalDockerhubMirror() string
// InternalRegistry returns the internal registry.
InternalRegistry() string
// InternalRegistryImageTagExists returns true if the image tag exists in the internal registry.
InternalRegistryImageTagExists(image, tag string) (bool, error)
}

Expand Down
46 changes: 27 additions & 19 deletions components/datadog/agentparams/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,37 +234,37 @@ func WithPulumiResourceOptions(resources ...pulumi.ResourceOption) func(*Params)
}
}

func withIntakeHostname(hostname pulumi.StringInput) func(*Params) error {
func withIntakeHostname(hostname pulumi.StringInput, port uint32) func(*Params) error {
return func(p *Params) error {
extraConfig := pulumi.Sprintf(`dd_url: http://%[1]s:80
logs_config.logs_dd_url: %[1]s:80
extraConfig := pulumi.Sprintf(`dd_url: http://%[1]s:%[2]d
logs_config.logs_dd_url: %[1]s:%[2]d
logs_config.logs_no_ssl: true
logs_config.force_use_http: true
process_config.process_dd_url: http://%[1]s:80
apm_config.apm_dd_url: http://%[1]s:80
database_monitoring.metrics.logs_dd_url: %[1]s:80
process_config.process_dd_url: http://%[1]s:%[2]d
apm_config.apm_dd_url: http://%[1]s:%[2]d
database_monitoring.metrics.logs_dd_url: %[1]s:%[2]d
database_monitoring.metrics.logs_no_ssl: true
database_monitoring.activity.logs_dd_url: %[1]s:80
database_monitoring.activity.logs_dd_url: %[1]s:%[2]d
database_monitoring.activity.logs_no_ssl: true
database_monitoring.samples.logs_dd_url: %[1]s:80
database_monitoring.samples.logs_dd_url: %[1]s:%[2]d
database_monitoring.samples.logs_no_ssl: true
network_devices.metadata.logs_dd_url: %[1]s:80
network_devices.metadata.logs_dd_url: %[1]s:%[2]d
network_devices.metadata.logs_no_ssl: true
network_devices.snmp_traps.forwarder.logs_dd_url: %[1]s:80
network_devices.snmp_traps.forwarder.logs_dd_url: %[1]s:%[2]d
network_devices.snmp_traps.forwarder.logs_no_ssl: true
network_devices.netflow.forwarder.logs_dd_url: %[1]s:80
network_devices.netflow.forwarder.logs_dd_url: %[1]s:%[2]d
network_devices.netflow.forwarder.logs_no_ssl: true
network_path.forwarder.logs_dd_url: %[1]s:80
network_path.forwarder.logs_dd_url: %[1]s:%[2]d
network_path.forwarder.logs_no_ssl: true
container_lifecycle.logs_dd_url: %[1]s:80
container_lifecycle.logs_dd_url: %[1]s:%[2]d
container_lifecycle.logs_no_ssl: true
container_image.logs_dd_url: %[1]s:80
container_image.logs_dd_url: %[1]s:%[2]d
container_image.logs_no_ssl: true
sbom.logs_dd_url: %[1]s:80
sbom.logs_dd_url: %[1]s:%[2]d
sbom.logs_no_ssl: true
service_discovery.forwarder.logs_dd_url: %[1]s:80
service_discovery.forwarder.logs_dd_url: %[1]s:%[2]d
service_discovery.forwarder.logs_no_ssl: true
`, hostname)
`, hostname, port)
p.ExtraAgentConfig = append(p.ExtraAgentConfig, extraConfig)
return nil
}
Expand All @@ -276,7 +276,7 @@ service_discovery.forwarder.logs_no_ssl: true
//
// This option is overwritten by `WithFakeintake`.
func WithIntakeHostname(hostname string) func(*Params) error {
return withIntakeHostname(pulumi.String(hostname))
return withIntakeHostname(pulumi.String(hostname), 80)
}

// WithFakeintake installs the fake intake and configures the Agent to use it.
Expand All @@ -285,7 +285,7 @@ func WithIntakeHostname(hostname string) func(*Params) error {
func WithFakeintake(fakeintake *fakeintake.Fakeintake) func(*Params) error {
return func(p *Params) error {
p.ResourceOptions = append(p.ResourceOptions, utils.PulumiDependsOn(fakeintake))
return withIntakeHostname(fakeintake.Host)(p)
return withIntakeHostname(fakeintake.Host, fakeintake.Port)(p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will change the behavior because currently we always use port 80. We might end up with the config using port 443 when the fakeintake is deployed in ECS. Are we sure it still works as expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, testing it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, this does not work with ecs. Good catch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no, agentparams is used only on hosts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this made me realise that inv aws.create-ecs does not work without LB, because we assume https endpoints on ecs agent params https://github.com/DataDog/test-infra-definitions/blob/pducolin/docker-localhost/components/datadog/agent/ecs.go#L257

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the same time we don't support LB on hosts, because we always assume http protocol. Creating a card to track those

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}

Expand Down Expand Up @@ -320,3 +320,11 @@ func WithTags(tags []string) func(*Params) error {
return nil
}
}

// WithHostname add hostname to the agent configuration
func WithHostname(hostname string) func(*Params) error {
return func(p *Params) error {
p.ExtraAgentConfig = append(p.ExtraAgentConfig, pulumi.Sprintf("hostname: %s", hostname))
return nil
}
}
4 changes: 3 additions & 1 deletion components/remote/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type HostOutput struct {
CloudProvider components.CloudProviderIdentifier `json:"cloudProvider"`

Address string `json:"address"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
OSFamily os.Family `json:"osFamily"`
Expand All @@ -28,14 +29,15 @@ type Host struct {

OS os.OS

CloudProvider pulumi.StringOutput `pulumi:"cloudProvider"`
Address pulumi.StringOutput `pulumi:"address"`
Port pulumi.IntOutput `pulumi:"port"`
Username pulumi.StringOutput `pulumi:"username"`
Password pulumi.StringOutput `pulumi:"password"`
Architecture pulumi.StringOutput `pulumi:"architecture"`
OSFamily pulumi.IntOutput `pulumi:"osFamily"`
OSFlavor pulumi.IntOutput `pulumi:"osFlavor"`
OSVersion pulumi.StringOutput `pulumi:"osVersion"`
CloudProvider pulumi.StringOutput `pulumi:"cloudProvider"`
}

func (h *Host) Export(ctx *pulumi.Context, out *HostOutput) error {
Expand Down
24 changes: 15 additions & 9 deletions components/remote/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,35 @@ const (

// NewConnection creates a remote connection to a host.
// Host and user are mandatory.
func NewConnection(host pulumi.StringInput, user, sshKeyPath, sshKeyPassword, sshAgentPath string) (*remote.ConnectionArgs, error) {
func NewConnection(host pulumi.StringInput, user string, options ...ConnectionOption) (*remote.ConnectionArgs, error) {
args, err := buildConnectionArgs(host, user, options...)

if err != nil {
return nil, err
}
conn := &remote.ConnectionArgs{
Host: host,
User: pulumi.String(user),
Host: args.host,
User: pulumi.String(args.user),
PerDialTimeout: pulumi.IntPtr(dialTimeoutSeconds),
DialErrorLimit: pulumi.IntPtr(dialErrorLimit),
Port: pulumi.Float64Ptr(float64(args.port)),
}

if sshKeyPath != "" {
privateKey, err := utils.ReadSecretFile(sshKeyPath)
if args.privateKeyPath != "" {
privateKey, err := utils.ReadSecretFile(args.privateKeyPath)
if err != nil {
return nil, err
}

conn.PrivateKey = privateKey
}

if sshKeyPassword != "" {
conn.PrivateKeyPassword = pulumi.StringPtr(sshKeyPassword)
if args.privateKeyPassword != "" {
conn.PrivateKeyPassword = pulumi.StringPtr(args.privateKeyPassword)
}

if sshAgentPath != "" {
conn.AgentSocketPath = pulumi.StringPtr(sshAgentPath)
if args.sshAgentPath != "" {
conn.AgentSocketPath = pulumi.StringPtr(args.sshAgentPath)
}

return conn, nil
Expand Down
60 changes: 60 additions & 0 deletions components/remote/connectionargs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package remote

import (
"github.com/DataDog/test-infra-definitions/common"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

type connectionArgs struct {
host pulumi.StringInput
user string

// ==== Optional ====
privateKeyPath string
privateKeyPassword string
sshAgentPath string
port int
}

type ConnectionOption = func(*connectionArgs) error

func buildConnectionArgs(host pulumi.StringInput, user string, options ...ConnectionOption) (*connectionArgs, error) {
args := &connectionArgs{
host: host,
user: user,
port: 22,
}
return common.ApplyOption(args, options)
}

// WithPrivateKeyPath [optional] sets the path to the private key to use for the connection
func WithPrivateKeyPath(path string) ConnectionOption {
return func(args *connectionArgs) error {
args.privateKeyPath = path
return nil
}
}

// WithPrivateKeyPassword [optional] sets the password to use in case the private key is encrypted
func WithPrivateKeyPassword(password string) ConnectionOption {
return func(args *connectionArgs) error {
args.privateKeyPassword = password
return nil
}
}

// WithSSHAgentPath [optional] sets the path to the SSH Agent socket. Default to environment variable SSH_AUTH_SOCK if present.
func WithSSHAgentPath(path string) ConnectionOption {
return func(args *connectionArgs) error {
args.sshAgentPath = path
return nil
}
}

// WithPort [optional] sets the port to use for the connection. Default to 22.
func WithPort(port int) ConnectionOption {
return func(args *connectionArgs) error {
args.port = port
return nil
}
}
7 changes: 7 additions & 0 deletions components/remote/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ func InitHost(e config.Env, conn remote.ConnectionOutput, osDesc os.Descriptor,
host.OSFlavor = pulumi.Int(osDesc.Flavor).ToIntOutput()
host.OSVersion = pulumi.String(osDesc.Version).ToStringOutput()
host.Password = password
host.Port = conn.Port().ApplyT(func(p *float64) int {
if p == nil {
// default port to 22
return 22
}
return int(*p)
}).(pulumi.IntOutput)

// Set the OS for internal usage
host.OS = os.NewOS(e, osDesc, runner)
Expand Down
27 changes: 15 additions & 12 deletions registry/scenarios.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package registry

import (
"github.com/DataDog/test-infra-definitions/scenarios/gcp/gke"
"strings"

"github.com/DataDog/test-infra-definitions/scenarios/gcp/gke"

"github.com/DataDog/test-infra-definitions/scenarios/aws/ec2"
"github.com/DataDog/test-infra-definitions/scenarios/aws/ecs"
"github.com/DataDog/test-infra-definitions/scenarios/aws/eks"
Expand All @@ -13,6 +14,7 @@ import (
"github.com/DataDog/test-infra-definitions/scenarios/azure/aks"
computerun "github.com/DataDog/test-infra-definitions/scenarios/azure/compute/run"
gcpcompute "github.com/DataDog/test-infra-definitions/scenarios/gcp/compute/run"
localpodmanrun "github.com/DataDog/test-infra-definitions/scenarios/local/podman/run"

"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
Expand All @@ -21,17 +23,18 @@ type ScenarioRegistry map[string]pulumi.RunFunc

func Scenarios() ScenarioRegistry {
return ScenarioRegistry{
"aws/vm": ec2.VMRun,
"aws/dockervm": ec2.VMRunWithDocker,
"aws/ecs": ecs.Run,
"aws/eks": eks.Run,
"aws/installer": installer.Run,
"aws/microvms": microvms.Run,
"aws/kind": kindvm.Run,
"az/vm": computerun.VMRun,
"az/aks": aks.Run,
"gcp/vm": gcpcompute.VMRun,
"gcp/gke": gke.Run,
"aws/vm": ec2.VMRun,
"aws/dockervm": ec2.VMRunWithDocker,
"aws/ecs": ecs.Run,
"aws/eks": eks.Run,
"aws/installer": installer.Run,
"aws/microvms": microvms.Run,
"aws/kind": kindvm.Run,
"az/vm": computerun.VMRun,
"az/aks": aks.Run,
"gcp/vm": gcpcompute.VMRun,
"gcp/gke": gke.Run,
"localpodman/vm": localpodmanrun.VMRun,
}
}

Expand Down
7 changes: 6 additions & 1 deletion resources/hyperv/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ func NewVM(e Environment, args VMArgs, opts ...pulumi.ResourceOption) (*remote.H

return components.NewComponent(&e, args.Name, func(comp *remote.Host) error {
// Let's say you get IP address from the command output (only output in the command).
conn, err := remote.NewConnection(cmd.Stdout, "<SSH_USER_NAME>", e.DefaultPrivateKeyPath(), e.DefaultPrivateKeyPassword(), "")
conn, err := remote.NewConnection(
cmd.Stdout,
"<SSH_USER_NAME>",
remote.WithPrivateKeyPath(e.DefaultPrivateKeyPath()),
remote.WithPrivateKeyPassword(e.DefaultPrivateKeyPassword()),
)
if err != nil {
return err
}
Expand Down
26 changes: 21 additions & 5 deletions resources/local/environment.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
package local

import (
"github.com/DataDog/test-infra-definitions/common/config"
config "github.com/DataDog/test-infra-definitions/common/config"
"github.com/DataDog/test-infra-definitions/common/namer"

"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

const (
localNamerNamespace = "local"
// local Infra (local)
DDInfraDefaultPublicKeyPath = "local/defaultPublicKeyPath"
)

type Environment struct {
// CommonEnvironment is the common environment for all the components
// in the test-infra-definitions.
*config.CommonEnvironment

Namer namer.Namer
}

var _ config.Env = (*Environment)(nil)

// NewEnvironment creates a new local environment.
func NewEnvironment(ctx *pulumi.Context) (Environment, error) {
env := Environment{}
env := Environment{
Namer: namer.NewNamer(ctx, localNamerNamespace),
}

commonEnv, err := config.NewCommonEnvironment(ctx)
if err != nil {
Expand All @@ -27,6 +36,8 @@ func NewEnvironment(ctx *pulumi.Context) (Environment, error) {
return env, nil
}

// Cross Cloud Provider config

// InternalRegistry returns the internal registry.
func (e *Environment) InternalRegistry() string {
return "none"
Expand All @@ -41,3 +52,8 @@ func (e *Environment) InternalDockerhubMirror() string {
func (e *Environment) InternalRegistryImageTagExists(_, _ string) (bool, error) {
return true, nil
}

// Common
func (e *Environment) DefaultPublicKeyPath() string {
return e.InfraConfig.Get(DDInfraDefaultPublicKeyPath)
}
26 changes: 26 additions & 0 deletions resources/local/podman/data/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

RUN set -eu && \
apt update; \
apt install -y \
--no-install-recommends \
ca-certificates \
curl \
systemd \
systemd-cron \
sudo \
openssh-server;

# setup ssh
RUN mkdir -p /etc/ssh/sshd_config.d && echo "PermitRootLogin without-password" > /etc/ssh/sshd_config.d/allow_root.conf
ARG DOCKER_HOST_SSH_PUBLIC_KEY
RUN mkdir -p /root/.ssh && echo $DOCKER_HOST_SSH_PUBLIC_KEY >> /root/.ssh/authorized_keys
RUN chmod 600 /root/.ssh/authorized_keys

RUN service ssh start

EXPOSE 22

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Code Vulnerability

do not expose ssh service from your container (...read more)

Never expose admin ports such as the SSH port 22 in your container. It increases the surface of attack of your containers.

View in Datadog  Leave us feedback  Documentation


CMD ["/usr/sbin/init"]
Loading