ci: add e2e test for constellation recover (#845)

* AB#2256 Add recover e2e test

* AB#2256 move test & fix minor objections

* AB#2256 fix path

* AB#2256 rename hacky filename
This commit is contained in:
Moritz Sanft 2023-01-19 10:41:07 +01:00 committed by GitHub
parent 2cee7cb454
commit ae2db08f3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 202 additions and 32 deletions

View file

@ -17,7 +17,7 @@ import (
type terraformClient interface {
PrepareWorkspace(path string, input terraform.Variables) error
CreateCluster(ctx context.Context) (string, string, error)
CreateCluster(ctx context.Context) (terraform.CreateOutput, error)
CreateIAMConfig(ctx context.Context, provider cloudprovider.Provider) (terraform.IAMOutput, error)
DestroyCluster(ctx context.Context) error
CleanUpWorkspace() error

View file

@ -29,6 +29,7 @@ type stubTerraformClient struct {
ip string
initSecret string
iamOutput terraform.IAMOutput
uid string
cleanUpWorkspaceCalled bool
removeInstallerCalled bool
destroyClusterCalled bool
@ -39,8 +40,12 @@ type stubTerraformClient struct {
iamOutputErr error
}
func (c *stubTerraformClient) CreateCluster(ctx context.Context) (string, string, error) {
return c.ip, c.initSecret, c.createClusterErr
func (c *stubTerraformClient) CreateCluster(ctx context.Context) (terraform.CreateOutput, error) {
return terraform.CreateOutput{
IP: c.ip,
Secret: c.initSecret,
UID: c.uid,
}, c.createClusterErr
}
func (c *stubTerraformClient) CreateIAMConfig(ctx context.Context, provider cloudprovider.Provider) (terraform.IAMOutput, error) {

View file

@ -123,15 +123,16 @@ func (c *Creator) createAWS(ctx context.Context, cl terraformClient, config *con
}
defer rollbackOnError(context.Background(), c.out, &retErr, &rollbackerTerraform{client: cl})
ip, initSecret, err := cl.CreateCluster(ctx)
tfOutput, err := cl.CreateCluster(ctx)
if err != nil {
return clusterid.File{}, err
}
return clusterid.File{
CloudProvider: cloudprovider.AWS,
InitSecret: []byte(initSecret),
IP: ip,
InitSecret: []byte(tfOutput.Secret),
IP: tfOutput.IP,
UID: tfOutput.UID,
}, nil
}
@ -160,15 +161,16 @@ func (c *Creator) createGCP(ctx context.Context, cl terraformClient, config *con
}
defer rollbackOnError(context.Background(), c.out, &retErr, &rollbackerTerraform{client: cl})
ip, initSecret, err := cl.CreateCluster(ctx)
tfOutput, err := cl.CreateCluster(ctx)
if err != nil {
return clusterid.File{}, err
}
return clusterid.File{
CloudProvider: cloudprovider.GCP,
InitSecret: []byte(initSecret),
IP: ip,
InitSecret: []byte(tfOutput.Secret),
IP: tfOutput.IP,
UID: tfOutput.UID,
}, nil
}
@ -200,15 +202,16 @@ func (c *Creator) createAzure(ctx context.Context, cl terraformClient, config *c
}
defer rollbackOnError(context.Background(), c.out, &retErr, &rollbackerTerraform{client: cl})
ip, initSecret, err := cl.CreateCluster(ctx)
tfOutput, err := cl.CreateCluster(ctx)
if err != nil {
return clusterid.File{}, err
}
return clusterid.File{
CloudProvider: cloudprovider.Azure,
IP: ip,
InitSecret: []byte(initSecret),
IP: tfOutput.IP,
InitSecret: []byte(tfOutput.Secret),
UID: tfOutput.UID,
}, nil
}
@ -313,14 +316,15 @@ func (c *Creator) createQEMU(ctx context.Context, cl terraformClient, lv libvirt
// Allow rollback of QEMU Terraform workspace from this point on
qemuRollbacker.createdWorkspace = true
ip, initSecret, err := cl.CreateCluster(ctx)
tfOutput, err := cl.CreateCluster(ctx)
if err != nil {
return clusterid.File{}, err
}
return clusterid.File{
CloudProvider: cloudprovider.QEMU,
InitSecret: []byte(initSecret),
IP: ip,
InitSecret: []byte(tfOutput.Secret),
IP: tfOutput.IP,
UID: tfOutput.UID,
}, nil
}

View file

@ -74,39 +74,59 @@ func (c *Client) PrepareWorkspace(path string, vars Variables) error {
}
// CreateCluster creates a Constellation cluster using Terraform.
func (c *Client) CreateCluster(ctx context.Context) (string, string, error) {
func (c *Client) CreateCluster(ctx context.Context) (CreateOutput, error) {
if err := c.tf.Init(ctx); err != nil {
return "", "", err
return CreateOutput{}, err
}
if err := c.tf.Apply(ctx); err != nil {
return "", "", err
return CreateOutput{}, err
}
tfState, err := c.tf.Show(ctx)
if err != nil {
return "", "", err
return CreateOutput{}, err
}
ipOutput, ok := tfState.Values.Outputs["ip"]
if !ok {
return "", "", errors.New("no IP output found")
return CreateOutput{}, errors.New("no IP output found")
}
ip, ok := ipOutput.Value.(string)
if !ok {
return "", "", errors.New("invalid type in IP output: not a string")
return CreateOutput{}, errors.New("invalid type in IP output: not a string")
}
secretOutput, ok := tfState.Values.Outputs["initSecret"]
if !ok {
return "", "", errors.New("no initSecret output found")
return CreateOutput{}, errors.New("no initSecret output found")
}
secret, ok := secretOutput.Value.(string)
if !ok {
return "", "", errors.New("invalid type in initSecret output: not a string")
return CreateOutput{}, errors.New("invalid type in initSecret output: not a string")
}
return ip, secret, nil
uidOutput, ok := tfState.Values.Outputs["uid"]
if !ok {
return CreateOutput{}, errors.New("no uid output found")
}
uid, ok := uidOutput.Value.(string)
if !ok {
return CreateOutput{}, errors.New("invalid type in uid output: not a string")
}
return CreateOutput{
IP: ip,
Secret: secret,
UID: uid,
}, nil
}
// CreateOutput contains the Terraform output values of a cluster creation.
type CreateOutput struct {
IP string
Secret string
UID string
}
// IAMOutput contains the output information of the Terraform IAM operations.

View file

@ -2,6 +2,10 @@ output "ip" {
value = aws_eip.lb.public_ip
}
output "uid" {
value = local.uid
}
output "initSecret" {
value = random_password.initSecret.result
sensitive = true

View file

@ -2,6 +2,10 @@ output "ip" {
value = azurerm_public_ip.loadbalancer_ip.ip_address
}
output "uid" {
value = local.uid
}
output "initSecret" {
value = random_password.initSecret.result
sensitive = true

View file

@ -2,6 +2,10 @@ output "ip" {
value = google_compute_global_address.loadbalancer_ip.address
}
output "uid" {
value = local.uid
}
output "initSecret" {
value = random_password.initSecret.result
sensitive = true

View file

@ -214,6 +214,9 @@ func TestCreateCluster(t *testing.T) {
"initSecret": {
Value: "initSecret",
},
"uid": {
Value: "12345abc",
},
},
},
}
@ -300,6 +303,34 @@ func TestCreateCluster(t *testing.T) {
fs: afero.NewMemMapFs(),
wantErr: true,
},
"no uid": {
pathBase: "terraform",
provider: cloudprovider.QEMU,
vars: qemuVars,
tf: &stubTerraform{
showState: &tfjson.State{
Values: &tfjson.StateValues{
Outputs: map[string]*tfjson.StateOutput{},
},
},
},
fs: afero.NewMemMapFs(),
wantErr: true,
},
"uid has wrong type": {
pathBase: "terraform",
provider: cloudprovider.QEMU,
vars: qemuVars,
tf: &stubTerraform{
showState: &tfjson.State{
Values: &tfjson.StateValues{
Outputs: map[string]*tfjson.StateOutput{"uid": {Value: 42}},
},
},
},
fs: afero.NewMemMapFs(),
wantErr: true,
},
}
for name, tc := range testCases {
@ -315,15 +346,16 @@ func TestCreateCluster(t *testing.T) {
path := path.Join(tc.pathBase, strings.ToLower(tc.provider.String()))
require.NoError(c.PrepareWorkspace(path, tc.vars))
ip, initSecret, err := c.CreateCluster(context.Background())
tfOutput, err := c.CreateCluster(context.Background())
if tc.wantErr {
assert.Error(err)
return
}
assert.NoError(err)
assert.Equal("192.0.2.100", ip)
assert.Equal("initSecret", initSecret)
assert.Equal("192.0.2.100", tfOutput.IP)
assert.Equal("initSecret", tfOutput.Secret)
assert.Equal("12345abc", tfOutput.UID)
})
}
}