-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add E2E tests for Domain Controllers installation (#22507)
Add E2E tests for Domain Controllers installation
- Loading branch information
1 parent
7b675e6
commit c41a677
Showing
32 changed files
with
881 additions
and
20 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
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
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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
25 changes: 25 additions & 0 deletions
25
test/new-e2e/pkg/environments/activedirectory/active_directory.go
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,25 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
// Package activedirectory contains the code necessary to create an Active Directory environment for e2e tests | ||
package activedirectory | ||
|
||
import ( | ||
"github.com/DataDog/datadog-agent/test/new-e2e/pkg/components" | ||
"github.com/DataDog/test-infra-definitions/common/config" | ||
) | ||
|
||
// Env represents an Active Directory environment for an e2e test | ||
type Env struct { | ||
DomainControllerHost *components.RemoteHost | ||
DomainController *RemoteActiveDirectory | ||
FakeIntake *components.FakeIntake | ||
Environment *config.CommonEnvironment | ||
} | ||
|
||
// RemoteActiveDirectory represents an Active Directory domain setup on a remote host | ||
type RemoteActiveDirectory struct { | ||
Output | ||
} |
112 changes: 112 additions & 0 deletions
112
test/new-e2e/pkg/environments/activedirectory/component.go
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,112 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
package activedirectory | ||
|
||
import ( | ||
"github.com/DataDog/datadog-agent/test/new-e2e/tests/windows/common/powershell" | ||
"github.com/DataDog/test-infra-definitions/common" | ||
"github.com/DataDog/test-infra-definitions/common/config" | ||
"github.com/DataDog/test-infra-definitions/common/namer" | ||
infraComponents "github.com/DataDog/test-infra-definitions/components" | ||
"github.com/DataDog/test-infra-definitions/components/command" | ||
"github.com/DataDog/test-infra-definitions/components/remote" | ||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi" | ||
"github.com/pulumiverse/pulumi-time/sdk/go/time" | ||
) | ||
|
||
// Output is an object that models the output of the resource creation | ||
// from the Component. | ||
// See https://www.pulumi.com/docs/concepts/resources/components/#registering-component-outputs | ||
type Output struct { | ||
infraComponents.JSONImporter | ||
} | ||
|
||
// Component is an Active Directory domain component. | ||
// See https://www.pulumi.com/docs/concepts/resources/components/ | ||
type Component struct { | ||
pulumi.ResourceState | ||
infraComponents.Component | ||
namer namer.Namer | ||
host *remote.Host | ||
} | ||
|
||
// Export registers a key and value pair with the current context's stack. | ||
func (dc *Component) Export(ctx *pulumi.Context, out *Output) error { | ||
return infraComponents.Export(ctx, dc, out) | ||
} | ||
|
||
// NewActiveDirectory creates a new instance of an Active Directory domain deployment | ||
func NewActiveDirectory(ctx *pulumi.Context, e *config.CommonEnvironment, host *remote.Host, options ...Option) (*Component, error) { | ||
params, err := common.ApplyOption(&Configuration{ | ||
// JL: Should we set sensible defaults here ? | ||
}, options) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
domainControllerComp, err := infraComponents.NewComponent(*e, host.Name(), func(comp *Component) error { | ||
comp.namer = e.CommonNamer.WithPrefix(comp.Name()) | ||
comp.host = host | ||
|
||
installForestCmd, err := host.OS.Runner().Command(comp.namer.ResourceName("install-forest"), &command.Args{ | ||
Create: pulumi.String(powershell.PsHost(). | ||
AddActiveDirectoryDomainServicesWindowsFeature(). | ||
ImportActiveDirectoryDomainServicesModule(). | ||
InstallADDSForest(params.DomainName, params.DomainPassword). | ||
Compile()), | ||
// JL: I hesitated to provide a Delete function but Uninstall-ADDSDomainController looks | ||
// non-trivial to call, and I couldn't test it. | ||
}, pulumi.Parent(comp)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
timeProvider, err := time.NewProvider(ctx, comp.namer.ResourceName("time-provider"), &time.ProviderArgs{}, pulumi.DeletedWith(host)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
waitForRebootCmd, err := time.NewSleep(ctx, comp.namer.ResourceName("wait-for-host-to-reboot"), &time.SleepArgs{ | ||
CreateDuration: pulumi.String("30s"), | ||
}, pulumi.Provider(timeProvider), pulumi.DependsOn([]pulumi.Resource{ | ||
installForestCmd, | ||
})) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ensureAdwsStartedCmd, err := host.OS.Runner().Command(comp.namer.ResourceName("ensure-adws-started"), &command.Args{ | ||
Create: pulumi.String(powershell.PsHost().WaitForServiceStatus("ADWS", "Running").Compile()), | ||
}, pulumi.DependsOn([]pulumi.Resource{ | ||
waitForRebootCmd, | ||
})) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(params.DomainUsers) > 0 { | ||
cmdHost := powershell.PsHost() | ||
for _, user := range params.DomainUsers { | ||
cmdHost.AddActiveDirectoryUser(user.Username, user.Password) | ||
} | ||
_, err := host.OS.Runner().Command(comp.namer.ResourceName("create-domain-users"), &command.Args{ | ||
Create: pulumi.String(cmdHost.Compile()), | ||
}, pulumi.DependsOn([]pulumi.Resource{ | ||
ensureAdwsStartedCmd, | ||
})) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
}, pulumi.Parent(host), pulumi.DeletedWith(host)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return domainControllerComp, 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,56 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
package activedirectory | ||
|
||
import ( | ||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi" | ||
) | ||
|
||
// DomainUser represents an Active Directory user | ||
type DomainUser struct { | ||
Username string | ||
Password string | ||
} | ||
|
||
// Configuration represents the Active Directory configuration (domain name, password, users etc...) | ||
type Configuration struct { | ||
DomainName string | ||
DomainPassword string | ||
DomainUsers []DomainUser | ||
ResourceOptions []pulumi.ResourceOption | ||
} | ||
|
||
// Option is an optional function parameter type for Configuration options | ||
type Option = func(*Configuration) error | ||
|
||
// WithDomainName specifies the fully qualified domain name (FQDN) for the root domain in the forest. | ||
func WithDomainName(domainName string) func(*Configuration) error { | ||
return func(p *Configuration) error { | ||
p.DomainName = domainName | ||
return nil | ||
} | ||
} | ||
|
||
// WithDomainPassword specifies the password for the administrator account when the computer is started in Safe Mode or | ||
// a variant of Safe Mode, such as Directory Services Restore Mode. | ||
// You must supply a password that meets the password complexity rules of the domain and the password cannot be blank. | ||
func WithDomainPassword(domainPassword string) func(*Configuration) error { | ||
return func(p *Configuration) error { | ||
p.DomainPassword = domainPassword | ||
return nil | ||
} | ||
} | ||
|
||
// WithDomainUser adds a user in Active Directory. | ||
func WithDomainUser(username, password string) func(params *Configuration) error { | ||
return func(p *Configuration) error { | ||
p.DomainUsers = append(p.DomainUsers, DomainUser{ | ||
Username: username, | ||
Password: password, | ||
}) | ||
return nil | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
test/new-e2e/pkg/environments/activedirectory/provisioner.go
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,88 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-present Datadog, Inc. | ||
|
||
package activedirectory | ||
|
||
import ( | ||
"fmt" | ||
"github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e" | ||
"github.com/DataDog/datadog-agent/test/new-e2e/pkg/utils/optional" | ||
"github.com/DataDog/test-infra-definitions/components/os" | ||
"github.com/DataDog/test-infra-definitions/resources/aws" | ||
"github.com/DataDog/test-infra-definitions/scenarios/aws/ec2" | ||
"github.com/DataDog/test-infra-definitions/scenarios/aws/fakeintake" | ||
"github.com/pulumi/pulumi/sdk/v3/go/pulumi" | ||
) | ||
|
||
const ( | ||
provisionerBaseID = "aws-ec2vm-active-directory-" | ||
defaultVMName = "dcvm" | ||
) | ||
|
||
// GetProvisionerParams return ProvisionerParams from options opts setup | ||
func GetProvisionerParams(opts ...ProvisionerOption) *ProvisionerParams { | ||
params := newProvisionerParams() | ||
err := optional.ApplyOptions(params, opts) | ||
if err != nil { | ||
panic(fmt.Errorf("unable to apply ProvisionerOption, err: %w", err)) | ||
} | ||
return params | ||
} | ||
|
||
// Run deploys a environment given a pulumi.Context | ||
func Run(ctx *pulumi.Context, env *Env, params *ProvisionerParams) error { | ||
awsEnv, err := aws.NewEnvironment(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
env.Environment = awsEnv.CommonEnvironment | ||
|
||
// JL: should the ec2 VM be customizable by the user? | ||
vm, err := ec2.NewVM(awsEnv, params.name, ec2.WithOS(os.WindowsDefault)) | ||
if err != nil { | ||
return err | ||
} | ||
err = vm.Export(ctx, &env.DomainControllerHost.HostOutput) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
domainController, err := NewActiveDirectory(ctx, awsEnv.CommonEnvironment, vm, params.activeDirectoryOptions...) | ||
if err != nil { | ||
return err | ||
} | ||
err = domainController.Export(ctx, &env.DomainController.Output) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// JL: can params.fakeintakeOptions be nil, and how should we handle it? | ||
fakeIntake, err := fakeintake.NewECSFargateInstance(awsEnv, params.name, params.fakeintakeOptions...) | ||
if err != nil { | ||
return err | ||
} | ||
err = fakeIntake.Export(ctx, &env.FakeIntake.FakeintakeOutput) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Provisioner creates an Active Directory environment on a given VM. | ||
func Provisioner(opts ...ProvisionerOption) e2e.TypedProvisioner[Env] { | ||
// We need to build params here to be able to use params.name in the provisioner name | ||
params := GetProvisionerParams(opts...) | ||
|
||
provisioner := e2e.NewTypedPulumiProvisioner[Env](provisionerBaseID+params.name, func(ctx *pulumi.Context, env *Env) error { | ||
// We ALWAYS need to make a deep copy of `params`, as the provisioner can be called multiple times. | ||
// and it's easy to forget about it, leading to hard to debug issues. | ||
params := GetProvisionerParams(opts...) | ||
return Run(ctx, env, params) | ||
}, nil) | ||
|
||
return provisioner | ||
} |
Oops, something went wrong.