mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-12-15 16:09:39 -05:00
AB#2579 Add constellation iam create command (#624)
This commit is contained in:
parent
be01cf7129
commit
286803fb97
38 changed files with 2029 additions and 108 deletions
|
|
@ -11,11 +11,9 @@ import (
|
|||
"embed"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
|
@ -29,9 +27,8 @@ var terraformFS embed.FS
|
|||
|
||||
// prepareWorkspace loads the embedded Terraform files,
|
||||
// and writes them into the workspace.
|
||||
func prepareWorkspace(fileHandler file.Handler, provider cloudprovider.Provider, workingDir string) error {
|
||||
// use path.Join to ensure no forward slashes are used to read the embedded FS
|
||||
rootDir := path.Join("terraform", strings.ToLower(provider.String()))
|
||||
func prepareWorkspace(path string, fileHandler file.Handler, workingDir string) error {
|
||||
rootDir := path
|
||||
return fs.WalkDir(terraformFS, rootDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ package terraform
|
|||
|
||||
import (
|
||||
"io/fs"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
|
|
@ -21,11 +23,13 @@ import (
|
|||
|
||||
func TestLoader(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
pathBase string
|
||||
provider cloudprovider.Provider
|
||||
fileList []string
|
||||
testAlreadyUnpacked bool
|
||||
}{
|
||||
"aws": {
|
||||
"awsCluster": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.AWS,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
|
|
@ -34,7 +38,8 @@ func TestLoader(t *testing.T) {
|
|||
"modules",
|
||||
},
|
||||
},
|
||||
"gcp": {
|
||||
"gcpCluster": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.GCP,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
|
|
@ -43,7 +48,8 @@ func TestLoader(t *testing.T) {
|
|||
"modules",
|
||||
},
|
||||
},
|
||||
"qemu": {
|
||||
"qemuCluster": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
|
|
@ -52,7 +58,35 @@ func TestLoader(t *testing.T) {
|
|||
"modules",
|
||||
},
|
||||
},
|
||||
"gcpIAM": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
"variables.tf",
|
||||
"outputs.tf",
|
||||
},
|
||||
},
|
||||
"azureIAM": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
"variables.tf",
|
||||
"outputs.tf",
|
||||
},
|
||||
},
|
||||
"awsIAM": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
"variables.tf",
|
||||
"outputs.tf",
|
||||
},
|
||||
},
|
||||
"continue on (partially) unpacked": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.AWS,
|
||||
fileList: []string{
|
||||
"main.tf",
|
||||
|
|
@ -71,14 +105,16 @@ func TestLoader(t *testing.T) {
|
|||
|
||||
file := file.NewHandler(afero.NewMemMapFs())
|
||||
|
||||
err := prepareWorkspace(file, tc.provider, constants.TerraformWorkingDir)
|
||||
path := path.Join(tc.pathBase, strings.ToLower(tc.provider.String()))
|
||||
err := prepareWorkspace(path, file, constants.TerraformWorkingDir)
|
||||
|
||||
require.NoError(err)
|
||||
checkFiles(t, file, func(err error) { assert.NoError(err) }, tc.fileList)
|
||||
|
||||
if tc.testAlreadyUnpacked {
|
||||
// Let's try the same again and check if we don't get a "file already exists" error.
|
||||
require.NoError(file.Remove(filepath.Join(constants.TerraformWorkingDir, "variables.tf")))
|
||||
err := prepareWorkspace(file, tc.provider, constants.TerraformWorkingDir)
|
||||
err := prepareWorkspace(path, file, constants.TerraformWorkingDir)
|
||||
assert.NoError(err)
|
||||
checkFiles(t, file, func(err error) { assert.NoError(err) }, tc.fileList)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ func New(ctx context.Context, workingDir string) (*Client, error) {
|
|||
}
|
||||
|
||||
// PrepareWorkspace prepares a Terraform workspace for a Constellation cluster.
|
||||
func (c *Client) PrepareWorkspace(provider cloudprovider.Provider, vars Variables) error {
|
||||
if err := prepareWorkspace(c.file, provider, c.workingDir); err != nil {
|
||||
func (c *Client) PrepareWorkspace(path string, vars Variables) error {
|
||||
if err := prepareWorkspace(path, c.file, c.workingDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +109,141 @@ func (c *Client) CreateCluster(ctx context.Context) (string, string, error) {
|
|||
return ip, secret, nil
|
||||
}
|
||||
|
||||
// IAMOutput contains the output information of the Terraform IAM operations.
|
||||
type IAMOutput struct {
|
||||
GCP GCPIAMOutput
|
||||
Azure AzureIAMOutput
|
||||
AWS AWSIAMOutput
|
||||
}
|
||||
|
||||
// GCPIAMOutput contains the output information of the Terraform IAM operation on GCP.
|
||||
type GCPIAMOutput struct {
|
||||
SaKey string
|
||||
}
|
||||
|
||||
// AzureIAMOutput contains the output information of the Terraform IAM operation on Microsoft Azure.
|
||||
type AzureIAMOutput struct {
|
||||
SubscriptionID string
|
||||
TenantID string
|
||||
ApplicationID string
|
||||
UAMIID string
|
||||
ApplicationClientSecretValue string
|
||||
}
|
||||
|
||||
// AWSIAMOutput contains the output information of the Terraform IAM operation on GCP.
|
||||
type AWSIAMOutput struct {
|
||||
ControlPlaneInstanceProfile string
|
||||
WorkerNodeInstanceProfile string
|
||||
}
|
||||
|
||||
// CreateIAMConfig creates an IAM configuration using Terraform.
|
||||
func (c *Client) CreateIAMConfig(ctx context.Context, provider cloudprovider.Provider) (IAMOutput, error) {
|
||||
if err := c.tf.Init(ctx); err != nil {
|
||||
return IAMOutput{}, err
|
||||
}
|
||||
|
||||
if err := c.tf.Apply(ctx); err != nil {
|
||||
return IAMOutput{}, err
|
||||
}
|
||||
|
||||
tfState, err := c.tf.Show(ctx)
|
||||
if err != nil {
|
||||
return IAMOutput{}, err
|
||||
}
|
||||
|
||||
switch provider {
|
||||
case cloudprovider.GCP:
|
||||
saKeyOutputRaw, ok := tfState.Values.Outputs["sa_key"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no service account key output found")
|
||||
}
|
||||
saKeyOutput, ok := saKeyOutputRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in service account key output: not a string")
|
||||
}
|
||||
return IAMOutput{
|
||||
GCP: GCPIAMOutput{
|
||||
SaKey: saKeyOutput,
|
||||
},
|
||||
}, nil
|
||||
case cloudprovider.Azure:
|
||||
subscriptionIDRaw, ok := tfState.Values.Outputs["subscription_id"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no subscription id output found")
|
||||
}
|
||||
subscriptionIDOutput, ok := subscriptionIDRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in subscription id output: not a string")
|
||||
}
|
||||
tenantIDRaw, ok := tfState.Values.Outputs["tenant_id"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no tenant id output found")
|
||||
}
|
||||
tenantIDOutput, ok := tenantIDRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in tenant id output: not a string")
|
||||
}
|
||||
applicationIDRaw, ok := tfState.Values.Outputs["application_id"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no application id output found")
|
||||
}
|
||||
applicationIDOutput, ok := applicationIDRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in application id output: not a string")
|
||||
}
|
||||
uamiIDRaw, ok := tfState.Values.Outputs["uami_id"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no UAMI id output found")
|
||||
}
|
||||
uamiIDOutput, ok := uamiIDRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in UAMI id output: not a string")
|
||||
}
|
||||
appClientSecretRaw, ok := tfState.Values.Outputs["application_client_secret_value"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no application client secret value output found")
|
||||
}
|
||||
appClientSecretOutput, ok := appClientSecretRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in application client secret valueoutput: not a string")
|
||||
}
|
||||
return IAMOutput{
|
||||
Azure: AzureIAMOutput{
|
||||
SubscriptionID: subscriptionIDOutput,
|
||||
TenantID: tenantIDOutput,
|
||||
ApplicationID: applicationIDOutput,
|
||||
UAMIID: uamiIDOutput,
|
||||
ApplicationClientSecretValue: appClientSecretOutput,
|
||||
},
|
||||
}, nil
|
||||
case cloudprovider.AWS:
|
||||
controlPlaneProfileRaw, ok := tfState.Values.Outputs["control_plane_instance_profile"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no control plane instance profile output found")
|
||||
}
|
||||
controlPlaneProfileOutput, ok := controlPlaneProfileRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in control plane instance profile output: not a string")
|
||||
}
|
||||
workerNodeProfileRaw, ok := tfState.Values.Outputs["worker_nodes_instance_profile"]
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("no worker node instance profile output found")
|
||||
}
|
||||
workerNodeProfileOutput, ok := workerNodeProfileRaw.Value.(string)
|
||||
if !ok {
|
||||
return IAMOutput{}, errors.New("invalid type in worker node instance profile output: not a string")
|
||||
}
|
||||
return IAMOutput{
|
||||
AWS: AWSIAMOutput{
|
||||
ControlPlaneInstanceProfile: controlPlaneProfileOutput,
|
||||
WorkerNodeInstanceProfile: workerNodeProfileOutput,
|
||||
},
|
||||
}, nil
|
||||
default:
|
||||
return IAMOutput{}, errors.New("unsupported cloud provider")
|
||||
}
|
||||
}
|
||||
|
||||
// DestroyCluster destroys a Constellation cluster using Terraform.
|
||||
func (c *Client) DestroyCluster(ctx context.Context) error {
|
||||
if err := c.tf.Init(ctx); err != nil {
|
||||
|
|
|
|||
61
cli/internal/terraform/terraform/iam/aws/.terraform.lock.hcl
generated
Normal file
61
cli/internal/terraform/terraform/iam/aws/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "4.45.0"
|
||||
constraints = "4.45.0"
|
||||
hashes = [
|
||||
"h1:/zHxqox3/4xqLyZq71sfwkQMBMorroA/JF5eBgkYjxs=",
|
||||
"h1:2Q1ZOA3hNuS0cJvyl5HcKELREDE9ULMrxFu6TTS6ZFA=",
|
||||
"h1:AKX4R3U+kBpQB5oU08kSrzl5CLsMhbK+BKZVrwYDXZQ=",
|
||||
"h1:EQ5L9Mfn1TLcSvslSYJ3xfrunQPzSi6jXewWqQZ7uRI=",
|
||||
"h1:IKlAzeFeTENTaXij4jVZqOhZ9sJDxcJODV12p2QQ+Rs=",
|
||||
"h1:J/XjRsEJIpxi+mczXQfnH3nvfACv3LRDtrthQJCIibY=",
|
||||
"h1:SldVY6f+D5uiApQNemxU5jsmwsbzuSY14Gcs5axMmIw=",
|
||||
"h1:VKmkAkwT5y56lSDzRMU4U/1TuCOt/W4PrTVEV7QO5xw=",
|
||||
"h1:ZFb6RqY48Fe+18sOC62wiE38XYPaTg98RJZO+EnsvCU=",
|
||||
"h1:aXWTWsY7wOAFvbyS4asC5L6TAnz1OWUj403tQdKTZjo=",
|
||||
"h1:hJ8sqJFjzU/rc5mXEocl1b0wOrbkrsuOvMBP7vPdL8g=",
|
||||
"h1:iNgrQzAnLH2z11JZghsx+mZ2qIMrwOCP1EL290Ehhko=",
|
||||
"h1:jAJjxVeu+cHso5A/4DBVnaoed0sonKirD33Z/4GZB90=",
|
||||
"h1:xwleZVEjEfgCEom/Pfk4kMY0RZllUEAx62NLbXSItFI=",
|
||||
"zh:22da03786f25658a000d1bcc28c780816a97e7e8a1f59fff6eee7d452830e95e",
|
||||
"zh:2543be56eee0491eb0c79ca1c901dcbf71da26625961fe719f088263fef062f4",
|
||||
"zh:31a1da1e3beedfd88c3c152ab505bdcf330427f26b75835885526f7bb75c4857",
|
||||
"zh:4409afe50f225659d5f378fe9303a45052953a1219f7f1acc82b69d07528b7ba",
|
||||
"zh:4dadec3b783f10d2f8eef3dab5e817baae9c932a7967d45fe3d77fcbcbdaa438",
|
||||
"zh:55be80d6e24828dcb0db7a0226fb275415c1c0ad63dd2f33b76f3ac0cd64e6a6",
|
||||
"zh:560bba29efb7dbe0bfcc937369d88817aa31a8d18aa25395b1afe2576cb04495",
|
||||
"zh:6caacc202e83438ff63d5d96733e283f44e349668d96c6b1c5c7df463ebf85cc",
|
||||
"zh:6cabab83a61d5b4ac801c5a5d57556a0e76ec8dc879d28cf777509db5f6a657e",
|
||||
"zh:96c4528bf9c16edb8841b68479ec51c499ed7fa680462fa28caeab3fc168bb43",
|
||||
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||
"zh:cdc0b47ff840d708fbf75abfe86d23dc7f1dffdd233a771822a17b5c637f4769",
|
||||
"zh:d9a9583e82776d1ebb6cf6c3d47acc2b302f8778f470ceffe7579dc794eb1feb",
|
||||
"zh:e9367ca9f6f6418a23cdf8d01f29dd0c4f614e78499f52a767a422e4c334b915",
|
||||
"zh:f6d355a2fb3bcebb597f68bbca4fa2aaa364efd29240236c582375e219d77656",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.4.3"
|
||||
hashes = [
|
||||
"h1:hV66lcagXXRwwCW3Y542bI1JgPo8z/taYKT7K+a2Z5U=",
|
||||
"h1:hXUPrH8igYBhatzatkp80RCeeUJGu9lQFDyKemOlsTo=",
|
||||
"h1:saZR+mhthL0OZl4SyHXZraxyaBNVMxiZzks78nWcZ2o=",
|
||||
"h1:tL3katm68lX+4lAncjQA9AXL4GR/VM+RPwqYf4D2X8Q=",
|
||||
"h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=",
|
||||
"zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752",
|
||||
"zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b",
|
||||
"zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3",
|
||||
"zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5",
|
||||
"zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda",
|
||||
"zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6",
|
||||
"zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1",
|
||||
"zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d",
|
||||
"zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8",
|
||||
"zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93",
|
||||
]
|
||||
}
|
||||
191
cli/internal/terraform/terraform/iam/aws/main.tf
Normal file
191
cli/internal/terraform/terraform/iam/aws/main.tf
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "4.45.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Configure the AWS Provider
|
||||
provider "aws" {
|
||||
region = var.region
|
||||
}
|
||||
|
||||
resource "random_id" "uid" {
|
||||
byte_length = 8
|
||||
}
|
||||
|
||||
resource "aws_iam_instance_profile" "control_plane_instance_profile" {
|
||||
name = "${var.name_prefix}_control_plane_instance_profile"
|
||||
role = aws_iam_role.control_plane_role.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "control_plane_role" {
|
||||
name = "${var.name_prefix}_control_plane_role"
|
||||
path = "/"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "ec2.amazonaws.com"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_policy" "control_plane_policy" {
|
||||
name = "${var.name_prefix}_control_plane_policy"
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"autoscaling:DescribeAutoScalingGroups",
|
||||
"autoscaling:DescribeLaunchConfigurations",
|
||||
"autoscaling:DescribeTags",
|
||||
"ec2:DescribeInstances",
|
||||
"ec2:DescribeRegions",
|
||||
"ec2:DescribeRouteTables",
|
||||
"ec2:DescribeSecurityGroups",
|
||||
"ec2:DescribeSubnets",
|
||||
"ec2:DescribeVolumes",
|
||||
"ec2:CreateSecurityGroup",
|
||||
"ec2:CreateTags",
|
||||
"ec2:CreateVolume",
|
||||
"ec2:ModifyInstanceAttribute",
|
||||
"ec2:ModifyVolume",
|
||||
"ec2:AttachVolume",
|
||||
"ec2:AuthorizeSecurityGroupIngress",
|
||||
"ec2:CreateRoute",
|
||||
"ec2:DeleteRoute",
|
||||
"ec2:DeleteSecurityGroup",
|
||||
"ec2:DeleteVolume",
|
||||
"ec2:DetachVolume",
|
||||
"ec2:RevokeSecurityGroupIngress",
|
||||
"ec2:DescribeVpcs",
|
||||
"elasticloadbalancing:AddTags",
|
||||
"elasticloadbalancing:AttachLoadBalancerToSubnets",
|
||||
"elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
|
||||
"elasticloadbalancing:CreateLoadBalancer",
|
||||
"elasticloadbalancing:CreateLoadBalancerPolicy",
|
||||
"elasticloadbalancing:CreateLoadBalancerListeners",
|
||||
"elasticloadbalancing:ConfigureHealthCheck",
|
||||
"elasticloadbalancing:DeleteLoadBalancer",
|
||||
"elasticloadbalancing:DeleteLoadBalancerListeners",
|
||||
"elasticloadbalancing:DescribeLoadBalancers",
|
||||
"elasticloadbalancing:DescribeLoadBalancerAttributes",
|
||||
"elasticloadbalancing:DetachLoadBalancerFromSubnets",
|
||||
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
|
||||
"elasticloadbalancing:ModifyLoadBalancerAttributes",
|
||||
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
|
||||
"elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer",
|
||||
"elasticloadbalancing:AddTags",
|
||||
"elasticloadbalancing:CreateListener",
|
||||
"elasticloadbalancing:CreateTargetGroup",
|
||||
"elasticloadbalancing:DeleteListener",
|
||||
"elasticloadbalancing:DeleteTargetGroup",
|
||||
"elasticloadbalancing:DescribeListeners",
|
||||
"elasticloadbalancing:DescribeLoadBalancerPolicies",
|
||||
"elasticloadbalancing:DescribeTargetGroups",
|
||||
"elasticloadbalancing:DescribeTargetHealth",
|
||||
"elasticloadbalancing:ModifyListener",
|
||||
"elasticloadbalancing:ModifyTargetGroup",
|
||||
"elasticloadbalancing:RegisterTargets",
|
||||
"elasticloadbalancing:DeregisterTargets",
|
||||
"elasticloadbalancing:SetLoadBalancerPoliciesOfListener",
|
||||
"iam:CreateServiceLinkedRole",
|
||||
"kms:DescribeKey",
|
||||
"logs:DescribeLogGroups",
|
||||
"logs:ListTagsLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents",
|
||||
"tag:GetResources",
|
||||
"ec2:DescribeImages"
|
||||
],
|
||||
"Resource": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "attach_control_plane_policy" {
|
||||
role = aws_iam_role.control_plane_role.name
|
||||
policy_arn = aws_iam_policy.control_plane_policy.arn
|
||||
}
|
||||
|
||||
resource "aws_iam_instance_profile" "worker_node_instance_profile" {
|
||||
name = "${var.name_prefix}_worker_node_instance_profile"
|
||||
role = aws_iam_role.control_plane_role.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "worker_node_role" {
|
||||
name = "${var.name_prefix}_worker_node_role"
|
||||
path = "/"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "ec2.amazonaws.com"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_policy" "worker_node_policy" {
|
||||
name = "${var.name_prefix}_worker_node_policy"
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ec2:DescribeInstances",
|
||||
"ec2:DescribeRegions",
|
||||
"ecr:GetAuthorizationToken",
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:GetRepositoryPolicy",
|
||||
"ecr:DescribeRepositories",
|
||||
"ecr:ListImages",
|
||||
"ecr:BatchGetImage",
|
||||
"logs:DescribeLogGroups",
|
||||
"logs:ListTagsLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents",
|
||||
"tag:GetResources",
|
||||
"ec2:DescribeImages"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "attach_worker_node_policy" {
|
||||
role = aws_iam_role.worker_node_role.name
|
||||
policy_arn = aws_iam_policy.worker_node_policy.arn
|
||||
}
|
||||
7
cli/internal/terraform/terraform/iam/aws/outputs.tf
Normal file
7
cli/internal/terraform/terraform/iam/aws/outputs.tf
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
output "control_plane_instance_profile" {
|
||||
value = aws_iam_instance_profile.control_plane_instance_profile.name
|
||||
}
|
||||
|
||||
output "worker_nodes_instance_profile" {
|
||||
value = aws_iam_instance_profile.worker_node_instance_profile.name
|
||||
}
|
||||
10
cli/internal/terraform/terraform/iam/aws/variables.tf
Normal file
10
cli/internal/terraform/terraform/iam/aws/variables.tf
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
variable "name_prefix" {
|
||||
type = string
|
||||
description = "Prefix for all resources"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = string
|
||||
description = "AWS region"
|
||||
default = "us-east-2"
|
||||
}
|
||||
62
cli/internal/terraform/terraform/iam/azure/.terraform.lock.hcl
generated
Normal file
62
cli/internal/terraform/terraform/iam/azure/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azuread" {
|
||||
version = "2.31.0"
|
||||
constraints = "2.31.0"
|
||||
hashes = [
|
||||
"h1:0D8+cQBlCyA50NiiTJwNDK9QjKfZsjuHgXTFRlhIZyg=",
|
||||
"h1:6bwCuD30Fz9DCkg8aaiod3qVJ72nMJQfmiSMat1K2PQ=",
|
||||
"h1:7vAGKxHE8I17dlZZQ3lnVaySilJH7m6fsOjiFH1yHLk=",
|
||||
"h1:BJrmwBctF1fOk2U2O7YX1OyDPHcBoPn78PRsZRkY6xs=",
|
||||
"h1:BWeCrUwFDA14mJO7UjhA8PfwaNUB/xuxAIJkMnMqjVc=",
|
||||
"h1:Fl5ASgCAamGAcwb0+3C+SrU8JVlWjiThDR9wybvbHjs=",
|
||||
"h1:M5ELmP8Qi/vGanQ5nYaD3AStPUh8xOof1QgqaUM6V1M=",
|
||||
"h1:ONdNfK0goPkMBPVe7D/ne13M3ZiMe+AzhPVv98f2V40=",
|
||||
"h1:kP4Zt6MO9CiQq57Lk1S4SWs11UVdwMSah8liskireLE=",
|
||||
"h1:sUL16Z8OsgIgeVJAXp1IqEs4VYoB9U8Iu/FNISuGj8I=",
|
||||
"h1:tH/R1ZHc+Vt0Kf51BLLsp/KhG/7K4v94LDbrzJZTp+c=",
|
||||
"zh:02a64db03707cc6970ab28a1da00d7fa011cc54e8a7806209f31bd8aad1794e1",
|
||||
"zh:077ffce8135a57544ec3c227bbe0ee5f6ca649223bd1dc0bbbd31d3fdf616830",
|
||||
"zh:0a369de6132edb0f4a69f2aa472b23f9bb5c430a3d539146d1c18d4cc7b12c7f",
|
||||
"zh:14bfc5f2354c1389eb7ed8bf5a5eaadc9940e18c2dd15058eb9b48ea5c37ae66",
|
||||
"zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7",
|
||||
"zh:5629f020ac3409ad34a39e221fb2e63f82948c3eb936508331d5a7f870556e9d",
|
||||
"zh:5b419eb59fa4e0b9c520c5cd5028f236bce6d9ab701c5ccca23cc040d3d690c4",
|
||||
"zh:5e7e6207fd58a3e9ba54b7333169a3e3ea693c25c8f477622536600a8a09a3f1",
|
||||
"zh:a9a552ad36d7a3db4554c6fbc716cf8631328331ea6188eddb4038b4c213ff46",
|
||||
"zh:aee812d33916e5fdfb4d58ce74af0f3b2a7a58dbfb5ec8e0b42b5780ceff5414",
|
||||
"zh:ce46738cd1909675b980bb90b9c3d919a4d1d655b4296082b86b6622ce818f7a",
|
||||
"zh:db02dbe5ce139610688b354b15eb934f9f67ab32d6c5d63690dce6f9b8d90904",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||
version = "3.34.0"
|
||||
constraints = "3.34.0"
|
||||
hashes = [
|
||||
"h1:2FU6urJTxBaqA8KxC3rX1p+0bbJzDSYKPS+yPTF3cZU=",
|
||||
"h1:7W2o3Hr5R6ZfD7J2ECOW4KHuIAY++GBg6aCKEtVSlo0=",
|
||||
"h1:7x4Ov+xzUS4OiHrAhkG2y55VyJLKDZFCuyzfNAgQGoo=",
|
||||
"h1:HA0WJNi5l9ZKN1mJrLfrJmP2Pe21Z0ugwyiCx7lKt8g=",
|
||||
"h1:LR1I99AYQG8H4+RRmqDgqGqycDC7haqOChyMLBorkTA=",
|
||||
"h1:XHe5dgOYCc1YNPGeffx98N/D+L4cjKpZb5tPaljor2M=",
|
||||
"h1:ZiYxI829dERQ0Ytx8fwZNEIti74DsdCNEWHNvAJI+2s=",
|
||||
"h1:pCUVVzQpBNUoPMyy0vwBeHwTL8GawDRfjSpZWVjX7WA=",
|
||||
"h1:tYHnH0a3l3/IEqlYRjhx9NCPBMIZnFzDzVFLlMZw/FE=",
|
||||
"h1:vLxp+DNhF9PsnbG/IFX2Vu3436Biit4s2mo5h2GPWqk=",
|
||||
"h1:yf/fBkEZQU/fTXpkrZLkMtXr9VVrCl8zYxkpEgvHUJ0=",
|
||||
"zh:04a3860959a9626469714a9986561ff04697fb6fe268cac6481ee570c3c20519",
|
||||
"zh:3191647b011cd094c7db1f5709f46e0df7190ab8dad1896e15e763384273931c",
|
||||
"zh:4428e5503fa614dec1ca3ea33d9479835a1c048a03cdec364ad8ad3340a3e137",
|
||||
"zh:576df51dfba37c40983552f98077125c2eb12eb4e105bb805e935c75c73a7181",
|
||||
"zh:5c1f4939a1e9ae96a977058c5056018f6b37220f1d0408531c89ea3295735f81",
|
||||
"zh:644ebea720c22b3f665f9e087ad57122ce5727631b3d437a425fb97a44515a01",
|
||||
"zh:87250563eed16db793ae9c309200f074f3b42acb4a44fdef4b26b9f7e988931e",
|
||||
"zh:b8fff7fb51234eb13a8f3a0107ef6fc8033e28c3b4a1087fc837dfc7706d3274",
|
||||
"zh:e21ecae5989348e9cbf07295f355a05dcae4758019d81c517f55b45e83a3e0e7",
|
||||
"zh:ece35f508eda2edf5d4867a6e5ad2e24904278813cfce70e19063d310e66d790",
|
||||
"zh:f421c6068713237fffce12f504fd5888b668352a22cb1075845fd612954ac3ec",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
84
cli/internal/terraform/terraform/iam/azure/main.tf
Normal file
84
cli/internal/terraform/terraform/iam/azure/main.tf
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "3.34.0"
|
||||
}
|
||||
azuread = {
|
||||
source = "hashicorp/azuread"
|
||||
version = "2.31.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Configure Azure resource management provider
|
||||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
||||
|
||||
# Configure Azure active directory provider
|
||||
provider "azuread" {
|
||||
tenant_id = data.azurerm_subscription.current.tenant_id
|
||||
}
|
||||
|
||||
# Access current subscription (available via Azure CLI)
|
||||
data "azurerm_subscription" "current" {}
|
||||
|
||||
# # Access current AzureAD configuration
|
||||
data "azuread_client_config" "current" {}
|
||||
|
||||
# Create base resource group
|
||||
resource "azurerm_resource_group" "base_resource_group" {
|
||||
name = var.resource_group_name
|
||||
location = var.region
|
||||
}
|
||||
|
||||
# Create identity resource group
|
||||
resource "azurerm_resource_group" "identity_resource_group" {
|
||||
name = "${var.resource_group_name}-identity"
|
||||
location = var.region
|
||||
}
|
||||
|
||||
# Create managed identity
|
||||
resource "azurerm_user_assigned_identity" "identity_uami" {
|
||||
location = var.region
|
||||
name = var.service_principal_name
|
||||
resource_group_name = azurerm_resource_group.identity_resource_group.name
|
||||
}
|
||||
|
||||
# Assign roles to managed identity
|
||||
resource "azurerm_role_assignment" "virtual_machine_contributor_role" {
|
||||
scope = "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}"
|
||||
role_definition_name = "Virtual Machine Contributor"
|
||||
principal_id = azurerm_user_assigned_identity.identity_uami.principal_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "application_insights_component_contributor_role" {
|
||||
scope = "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}"
|
||||
role_definition_name = "Application Insights Component Contributor"
|
||||
principal_id = azurerm_user_assigned_identity.identity_uami.principal_id
|
||||
}
|
||||
|
||||
# Create application registration
|
||||
resource "azuread_application" "base_application" {
|
||||
display_name = "${var.resource_group_name}-application"
|
||||
owners = [data.azuread_client_config.current.object_id]
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "application_principal" {
|
||||
application_id = azuread_application.base_application.application_id
|
||||
app_role_assignment_required = false
|
||||
owners = [data.azuread_client_config.current.object_id]
|
||||
}
|
||||
|
||||
# Set identity as base resource group owner
|
||||
resource "azurerm_role_assignment" "owner_role" {
|
||||
scope = "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}"
|
||||
role_definition_name = "Owner"
|
||||
principal_id = azuread_service_principal.application_principal.object_id
|
||||
}
|
||||
|
||||
# Create application secret (password)
|
||||
resource "azuread_application_password" "base_application_secret" {
|
||||
application_object_id = azuread_application.base_application.object_id
|
||||
}
|
||||
20
cli/internal/terraform/terraform/iam/azure/outputs.tf
Normal file
20
cli/internal/terraform/terraform/iam/azure/outputs.tf
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
output "subscription_id" {
|
||||
value = data.azurerm_subscription.current.subscription_id
|
||||
}
|
||||
|
||||
output "tenant_id" {
|
||||
value = data.azurerm_subscription.current.tenant_id
|
||||
}
|
||||
|
||||
output "application_id" {
|
||||
value = azuread_application.base_application.application_id
|
||||
}
|
||||
|
||||
output "uami_id" {
|
||||
value = azurerm_user_assigned_identity.identity_uami.id
|
||||
}
|
||||
|
||||
output "application_client_secret_value" {
|
||||
value = azuread_application_password.base_application_secret.value
|
||||
sensitive = true
|
||||
}
|
||||
14
cli/internal/terraform/terraform/iam/azure/variables.tf
Normal file
14
cli/internal/terraform/terraform/iam/azure/variables.tf
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
variable "resource_group_name" {
|
||||
type = string
|
||||
description = "Resource group name"
|
||||
}
|
||||
|
||||
variable "service_principal_name" {
|
||||
type = string
|
||||
description = "Service principal name"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = string
|
||||
description = "Azure resource location"
|
||||
}
|
||||
42
cli/internal/terraform/terraform/iam/gcp/.terraform.lock.hcl
generated
Normal file
42
cli/internal/terraform/terraform/iam/gcp/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/google" {
|
||||
version = "4.44.0"
|
||||
constraints = "4.44.0"
|
||||
hashes = [
|
||||
"h1:JpShTtgnxpiIVnr0R2Lccrh84mnrf7Z1/v/yw0UZ1gI=",
|
||||
"h1:JzDVTkBVHTw67N7S9bD/+u7U3aipjutF4MZx0eplONw=",
|
||||
"h1:OTNLlWoTq+SdbbtgLK7uFVAn3aP9QVjIGYU2ndKsz+Q=",
|
||||
"h1:PSIkDVwksHe9oZd+XP369N8U+6/+SPF8Z5wHkcwmWKw=",
|
||||
"h1:d6Ds7aGeW5M8+AgWfkfbh3HTf3tP8ePjYGhoJnOxklU=",
|
||||
"h1:enGPHgPHCbmLU8BIHLHcOwRlbQnPPQzdmXNoFVs1lIg=",
|
||||
"h1:gmUUWhuuY/YRIllvVBRGl1kUHqsNBHQ/4BHdwKQbzXQ=",
|
||||
"h1:hMhGerpfzsbfQ3DFsAGwJYpSIK6an+wMGx2I/lwaNuY=",
|
||||
"h1:iotFu763eGWVC4zfXkNuo3RUeQLDvwVX2E7R/2sNxCg=",
|
||||
"h1:mheXqRMLbMeTr8/E6UakMhWwIL0HqwIHYBE2u2Sbldg=",
|
||||
"zh:0b424cab24856dc47177733145fa61b731f345a6a42a0c0b7910ccfcf4e8c8a2",
|
||||
"zh:0c6b3049957b942e1dbc6f8c38de653a78ff1efe40a7cfc506e60a8da2775591",
|
||||
"zh:1e1d282abd9dbd30602ca52050f875deeb4d79b3b06cda69535db4863f1b98a0",
|
||||
"zh:35b7bc7c4da98e47bc7827fe1c39400811c9af459e03c99217195830f6bb0e78",
|
||||
"zh:5ea45d229afad298bdac80324ec9d6968443d54ed1d1a01fad70b3c1bd16e53b",
|
||||
"zh:652b740a7f75d716daf0fa9b2ef1964944eb4f8b0b26834dd8659a6ac2f3ed52",
|
||||
"zh:75ee47f9a28826de301c3c6d2fb7915414f3841b1d0248cad6b94697fb8ee634",
|
||||
"zh:89222d36d8060beb13df6758d6d9b2d075fa809e90a910a2ce1a867cfa6ff654",
|
||||
"zh:a8c04acc69a65cb68b91ec08aa89c4953840dad33482c9acf4cc0272375b3bf4",
|
||||
"zh:b71c10a8167cb6c7c3ae174c8c181a06dc82564f097f89602c3d74e8a7627e92",
|
||||
"zh:bb9a92b640cf0596edcc510ddd20725637c1ff295054f727277108a4a3c9baec",
|
||||
"zh:bccae696aa84ff7978c6a81b25d61f722fc87261e4b524ec062392916c8494ab",
|
||||
"zh:bcd028cd233287420ecfbe4102e59e351e6fd22a4a14698e6896c45fb0509a1e",
|
||||
"zh:bd9d096abdc42a3cf5849ae8adc9c8ca327c026e6f6f287fd436b6adfc8630dc",
|
||||
"zh:c3577ea597c9f8707b86a3056f59ff28c35c77b17392dd75a5dbe46617f7f7c6",
|
||||
"zh:d44915d60ffb54edf48ff9a1c2661b358497a9ecb900e8a3b3983f083ea198ce",
|
||||
"zh:d5dfcc1949e12fcc2d9ac834296872bded5b4201f2c492eb127872a72080b56b",
|
||||
"zh:d9dc91823cbcd60464d5b168d7bd34a5b5f13d5b37786110226bfe139ea24782",
|
||||
"zh:e8647c8ab63144013446b73c695a01f6bef16712613f1461d1c0bc37e1ba80d6",
|
||||
"zh:ecd0cd61f13d401240301691f3042abca874a5c481a90b4f791c0e4ea10b6448",
|
||||
"zh:ed01ea31e457d6c4e01a5d6dfd6ad3d09a0a58ff7dc4de494bf559fbc34fa936",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
"zh:ffb268a1b2b401175667a7e421100ce8964f6b32cab723766e8eb0b993b59e66",
|
||||
]
|
||||
}
|
||||
69
cli/internal/terraform/terraform/iam/gcp/main.tf
Normal file
69
cli/internal/terraform/terraform/iam/gcp/main.tf
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "4.44.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "google" {
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
zone = var.zone
|
||||
}
|
||||
|
||||
resource "google_service_account" "service_account" {
|
||||
account_id = var.service_account_id
|
||||
display_name = "Constellation service account"
|
||||
description = "Service account used inside Constellation"
|
||||
}
|
||||
|
||||
resource "google_project_iam_binding" "instance_admin_role" {
|
||||
project = var.project_id
|
||||
role = "roles/compute.instanceAdmin.v1"
|
||||
|
||||
members = [
|
||||
"serviceAccount:${google_service_account.service_account.email}",
|
||||
]
|
||||
}
|
||||
|
||||
resource "google_project_iam_binding" "network_admin_role" {
|
||||
project = var.project_id
|
||||
role = "roles/compute.networkAdmin"
|
||||
|
||||
members = [
|
||||
"serviceAccount:${google_service_account.service_account.email}",
|
||||
]
|
||||
}
|
||||
|
||||
resource "google_project_iam_binding" "security_admin_role" {
|
||||
project = var.project_id
|
||||
role = "roles/compute.securityAdmin"
|
||||
|
||||
members = [
|
||||
"serviceAccount:${google_service_account.service_account.email}",
|
||||
]
|
||||
}
|
||||
|
||||
resource "google_project_iam_binding" "storage_admin_role" {
|
||||
project = var.project_id
|
||||
role = "roles/compute.storageAdmin"
|
||||
|
||||
members = [
|
||||
"serviceAccount:${google_service_account.service_account.email}",
|
||||
]
|
||||
}
|
||||
|
||||
resource "google_project_iam_binding" "iam_service_account_user_role" {
|
||||
project = var.project_id
|
||||
role = "roles/iam.serviceAccountUser"
|
||||
|
||||
members = [
|
||||
"serviceAccount:${google_service_account.service_account.email}",
|
||||
]
|
||||
}
|
||||
|
||||
resource "google_service_account_key" "service_account_key" {
|
||||
service_account_id = google_service_account.service_account.name
|
||||
}
|
||||
4
cli/internal/terraform/terraform/iam/gcp/outputs.tf
Normal file
4
cli/internal/terraform/terraform/iam/gcp/outputs.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
output "sa_key" {
|
||||
value = google_service_account_key.service_account_key.private_key
|
||||
sensitive = true
|
||||
}
|
||||
19
cli/internal/terraform/terraform/iam/gcp/variables.tf
Normal file
19
cli/internal/terraform/terraform/iam/gcp/variables.tf
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
variable "project_id" {
|
||||
type = string
|
||||
description = "GCP Project ID"
|
||||
}
|
||||
|
||||
variable "service_account_id" {
|
||||
type = string
|
||||
description = "ID for the service account being created. Must match ^[a-z](?:[-a-z0-9]{4,28}[a-z0-9])$"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = string
|
||||
description = "Region used for constellation clusters. Needs to have the N2D machine type available."
|
||||
}
|
||||
|
||||
variable "zone" {
|
||||
type = string
|
||||
description = "Zone used for constellation clusters. Needs to be within the specified region."
|
||||
}
|
||||
|
|
@ -10,7 +10,9 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
|
|
@ -40,6 +42,7 @@ func TestPrepareCluster(t *testing.T) {
|
|||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
pathBase string
|
||||
provider cloudprovider.Provider
|
||||
vars Variables
|
||||
fs afero.Fs
|
||||
|
|
@ -47,17 +50,20 @@ func TestPrepareCluster(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
"qemu": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: false,
|
||||
},
|
||||
"no vars": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"continue on partially extracted": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
fs: afero.NewMemMapFs(),
|
||||
|
|
@ -65,6 +71,7 @@ func TestPrepareCluster(t *testing.T) {
|
|||
wantErr: false,
|
||||
},
|
||||
"prepare workspace fails": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
fs: afero.NewReadOnlyFs(afero.NewMemMapFs()),
|
||||
|
|
@ -83,12 +90,107 @@ func TestPrepareCluster(t *testing.T) {
|
|||
workingDir: constants.TerraformWorkingDir,
|
||||
}
|
||||
|
||||
err := c.PrepareWorkspace(tc.provider, tc.vars)
|
||||
path := path.Join(tc.pathBase, strings.ToLower(tc.provider.String()))
|
||||
err := c.PrepareWorkspace(path, tc.vars)
|
||||
|
||||
// Test case: Check if we can continue to create on an incomplete workspace.
|
||||
if tc.partiallyExtracted {
|
||||
require.NoError(c.file.Remove(filepath.Join(c.workingDir, "main.tf")))
|
||||
err = c.PrepareWorkspace(tc.provider, tc.vars)
|
||||
err = c.PrepareWorkspace(path, tc.vars)
|
||||
}
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareIAM(t *testing.T) {
|
||||
gcpVars := &GCPIAMVariables{
|
||||
Project: "const-1234",
|
||||
Region: "europe-west1",
|
||||
Zone: "europe-west1-a",
|
||||
ServiceAccountID: "const-test-case",
|
||||
}
|
||||
azureVars := &AzureIAMVariables{
|
||||
Region: "westus",
|
||||
ServicePrincipal: "constell-test-sp",
|
||||
ResourceGroup: "constell-test-rg",
|
||||
}
|
||||
awsVars := &AWSIAMVariables{
|
||||
Region: "eu-east-2a",
|
||||
Prefix: "test",
|
||||
}
|
||||
testCases := map[string]struct {
|
||||
pathBase string
|
||||
provider cloudprovider.Provider
|
||||
vars Variables
|
||||
fs afero.Fs
|
||||
partiallyExtracted bool
|
||||
wantErr bool
|
||||
}{
|
||||
"no vars": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"invalid path": {
|
||||
pathBase: path.Join("abc", "123"),
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"gcp": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: false,
|
||||
},
|
||||
"continue on partially extracted": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
fs: afero.NewMemMapFs(),
|
||||
partiallyExtracted: true,
|
||||
wantErr: false,
|
||||
},
|
||||
"azure": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: false,
|
||||
},
|
||||
"aws": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
c := &Client{
|
||||
tf: &stubTerraform{},
|
||||
file: file.NewHandler(tc.fs),
|
||||
workingDir: constants.TerraformIAMWorkingDir,
|
||||
}
|
||||
|
||||
path := path.Join(tc.pathBase, strings.ToLower(tc.provider.String()))
|
||||
err := c.PrepareWorkspace(path, tc.vars)
|
||||
|
||||
// Test case: Check if we can continue to create on an incomplete workspace.
|
||||
if tc.partiallyExtracted {
|
||||
require.NoError(c.file.Remove(filepath.Join(c.workingDir, "main.tf")))
|
||||
err = c.PrepareWorkspace(path, tc.vars)
|
||||
}
|
||||
|
||||
if tc.wantErr {
|
||||
|
|
@ -132,6 +234,7 @@ func TestCreateCluster(t *testing.T) {
|
|||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
pathBase string
|
||||
provider cloudprovider.Provider
|
||||
vars Variables
|
||||
tf *stubTerraform
|
||||
|
|
@ -139,12 +242,14 @@ func TestCreateCluster(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
"works": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
tf: &stubTerraform{showState: newTestState()},
|
||||
fs: afero.NewMemMapFs(),
|
||||
},
|
||||
"init fails": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
tf: &stubTerraform{initErr: someErr},
|
||||
|
|
@ -152,6 +257,7 @@ func TestCreateCluster(t *testing.T) {
|
|||
wantErr: true,
|
||||
},
|
||||
"apply fails": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
tf: &stubTerraform{applyErr: someErr},
|
||||
|
|
@ -159,6 +265,7 @@ func TestCreateCluster(t *testing.T) {
|
|||
wantErr: true,
|
||||
},
|
||||
"show fails": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
tf: &stubTerraform{showErr: someErr},
|
||||
|
|
@ -166,6 +273,7 @@ func TestCreateCluster(t *testing.T) {
|
|||
wantErr: true,
|
||||
},
|
||||
"no ip": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
tf: &stubTerraform{
|
||||
|
|
@ -179,6 +287,7 @@ func TestCreateCluster(t *testing.T) {
|
|||
wantErr: true,
|
||||
},
|
||||
"ip has wrong type": {
|
||||
pathBase: "terraform",
|
||||
provider: cloudprovider.QEMU,
|
||||
vars: qemuVars,
|
||||
tf: &stubTerraform{
|
||||
|
|
@ -204,7 +313,8 @@ func TestCreateCluster(t *testing.T) {
|
|||
workingDir: constants.TerraformWorkingDir,
|
||||
}
|
||||
|
||||
require.NoError(c.PrepareWorkspace(tc.provider, tc.vars))
|
||||
path := path.Join(tc.pathBase, strings.ToLower(tc.provider.String()))
|
||||
require.NoError(c.PrepareWorkspace(path, tc.vars))
|
||||
ip, initSecret, err := c.CreateCluster(context.Background())
|
||||
|
||||
if tc.wantErr {
|
||||
|
|
@ -218,6 +328,282 @@ func TestCreateCluster(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCreateIAM(t *testing.T) {
|
||||
someErr := errors.New("failed")
|
||||
newTestState := func() *tfjson.State {
|
||||
workingState := tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{
|
||||
"sa_key": {
|
||||
Value: "12345678_abcdefg",
|
||||
},
|
||||
"subscription_id": {
|
||||
Value: "test_subscription_id",
|
||||
},
|
||||
"tenant_id": {
|
||||
Value: "test_tenant_id",
|
||||
},
|
||||
"application_id": {
|
||||
Value: "test_application_id",
|
||||
},
|
||||
"uami_id": {
|
||||
Value: "test_uami_id",
|
||||
},
|
||||
"application_client_secret_value": {
|
||||
Value: "test_application_client_secret_value",
|
||||
},
|
||||
"control_plane_instance_profile": {
|
||||
Value: "test_control_plane_instance_profile",
|
||||
},
|
||||
"worker_nodes_instance_profile": {
|
||||
Value: "test_worker_nodes_instance_profile",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return &workingState
|
||||
}
|
||||
gcpVars := &GCPIAMVariables{
|
||||
Project: "const-1234",
|
||||
Region: "europe-west1",
|
||||
Zone: "europe-west1-a",
|
||||
ServiceAccountID: "const-test-case",
|
||||
}
|
||||
azureVars := &AzureIAMVariables{
|
||||
Region: "westus",
|
||||
ServicePrincipal: "constell-test-sp",
|
||||
ResourceGroup: "constell-test-rg",
|
||||
}
|
||||
awsVars := &AWSIAMVariables{
|
||||
Region: "eu-east-2a",
|
||||
Prefix: "test",
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
pathBase string
|
||||
provider cloudprovider.Provider
|
||||
vars Variables
|
||||
tf *stubTerraform
|
||||
fs afero.Fs
|
||||
wantErr bool
|
||||
want IAMOutput
|
||||
}{
|
||||
"gcp works": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
tf: &stubTerraform{showState: newTestState()},
|
||||
fs: afero.NewMemMapFs(),
|
||||
want: IAMOutput{GCP: GCPIAMOutput{SaKey: "12345678_abcdefg"}},
|
||||
},
|
||||
"gcp init fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
tf: &stubTerraform{initErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"gcp apply fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
tf: &stubTerraform{applyErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"gcp show fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
tf: &stubTerraform{showErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"gcp no sa_key": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
tf: &stubTerraform{
|
||||
showState: &tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{},
|
||||
},
|
||||
},
|
||||
},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"gcp sa_key has wrong type": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.GCP,
|
||||
vars: gcpVars,
|
||||
tf: &stubTerraform{
|
||||
showState: &tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{"sa_key": {Value: 42}},
|
||||
},
|
||||
},
|
||||
},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"azure works": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
tf: &stubTerraform{showState: newTestState()},
|
||||
fs: afero.NewMemMapFs(),
|
||||
want: IAMOutput{Azure: AzureIAMOutput{
|
||||
SubscriptionID: "test_subscription_id",
|
||||
TenantID: "test_tenant_id",
|
||||
ApplicationID: "test_application_id",
|
||||
ApplicationClientSecretValue: "test_application_client_secret_value",
|
||||
UAMIID: "test_uami_id",
|
||||
}},
|
||||
},
|
||||
"azure init fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
tf: &stubTerraform{initErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"azure apply fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
tf: &stubTerraform{applyErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"azure show fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
tf: &stubTerraform{showErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"azure no subscription_id": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
tf: &stubTerraform{
|
||||
showState: &tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{},
|
||||
},
|
||||
},
|
||||
},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"azure subscription_id has wrong type": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.Azure,
|
||||
vars: azureVars,
|
||||
tf: &stubTerraform{
|
||||
showState: &tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{"subscription_id": {Value: 42}},
|
||||
},
|
||||
},
|
||||
},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"aws works": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
tf: &stubTerraform{showState: newTestState()},
|
||||
fs: afero.NewMemMapFs(),
|
||||
want: IAMOutput{AWS: AWSIAMOutput{
|
||||
ControlPlaneInstanceProfile: "test_control_plane_instance_profile",
|
||||
WorkerNodeInstanceProfile: "test_worker_nodes_instance_profile",
|
||||
}},
|
||||
},
|
||||
"aws init fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
tf: &stubTerraform{initErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"aws apply fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
tf: &stubTerraform{applyErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"aws show fails": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
tf: &stubTerraform{showErr: someErr},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"aws no control_plane_instance_profile": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
tf: &stubTerraform{
|
||||
showState: &tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{},
|
||||
},
|
||||
},
|
||||
},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
"azure control_plane_instance_profile has wrong type": {
|
||||
pathBase: path.Join("terraform", "iam"),
|
||||
provider: cloudprovider.AWS,
|
||||
vars: awsVars,
|
||||
tf: &stubTerraform{
|
||||
showState: &tfjson.State{
|
||||
Values: &tfjson.StateValues{
|
||||
Outputs: map[string]*tfjson.StateOutput{"control_plane_instance_profile": {Value: 42}},
|
||||
},
|
||||
},
|
||||
},
|
||||
fs: afero.NewMemMapFs(),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
c := &Client{
|
||||
tf: tc.tf,
|
||||
file: file.NewHandler(tc.fs),
|
||||
workingDir: constants.TerraformIAMWorkingDir,
|
||||
}
|
||||
|
||||
path := path.Join(tc.pathBase, strings.ToLower(tc.provider.String()))
|
||||
require.NoError(c.PrepareWorkspace(path, tc.vars))
|
||||
IAMoutput, err := c.CreateIAMConfig(context.Background(), tc.provider)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.want, IAMoutput)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDestroyInstances(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
tf *stubTerraform
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ func (v *CommonVariables) String() string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
// AWSVariables is user configuration for creating a cluster with Terraform on GCP.
|
||||
type AWSVariables struct {
|
||||
// AWSClusterVariables is user configuration for creating a cluster with Terraform on GCP.
|
||||
type AWSClusterVariables struct {
|
||||
// CommonVariables contains common variables.
|
||||
CommonVariables
|
||||
// Region is the AWS region to use.
|
||||
|
|
@ -61,8 +61,40 @@ type AWSVariables struct {
|
|||
Debug bool
|
||||
}
|
||||
|
||||
// GCPVariables is user configuration for creating a cluster with Terraform on GCP.
|
||||
type GCPVariables struct {
|
||||
func (v *AWSClusterVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
b.WriteString(v.CommonVariables.String())
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
writeLinef(b, "zone = %q", v.Zone)
|
||||
writeLinef(b, "ami = %q", v.AMIImageID)
|
||||
writeLinef(b, "instance_type = %q", v.InstanceType)
|
||||
writeLinef(b, "state_disk_type = %q", v.StateDiskType)
|
||||
writeLinef(b, "iam_instance_profile_control_plane = %q", v.IAMProfileControlPlane)
|
||||
writeLinef(b, "iam_instance_profile_worker_nodes = %q", v.IAMProfileWorkerNodes)
|
||||
writeLinef(b, "debug = %t", v.Debug)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// AWSIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure.
|
||||
type AWSIAMVariables struct {
|
||||
// Region is the AWS location to use. (e.g. us-east-2)
|
||||
Region string
|
||||
// Prefix is the name prefix of the resources to use.
|
||||
Prefix string
|
||||
}
|
||||
|
||||
// String returns a string representation of the IAM-specific variables, formatted as Terraform variables.
|
||||
func (v *AWSIAMVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
writeLinef(b, "name_prefix = %q", v.Prefix)
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// GCPClusterVariables is user configuration for creating resources with Terraform on GCP.
|
||||
type GCPClusterVariables struct {
|
||||
// CommonVariables contains common variables.
|
||||
CommonVariables
|
||||
|
||||
|
|
@ -84,23 +116,8 @@ type GCPVariables struct {
|
|||
Debug bool
|
||||
}
|
||||
|
||||
func (v *AWSVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
b.WriteString(v.CommonVariables.String())
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
writeLinef(b, "zone = %q", v.Zone)
|
||||
writeLinef(b, "ami = %q", v.AMIImageID)
|
||||
writeLinef(b, "instance_type = %q", v.InstanceType)
|
||||
writeLinef(b, "state_disk_type = %q", v.StateDiskType)
|
||||
writeLinef(b, "iam_instance_profile_control_plane = %q", v.IAMProfileControlPlane)
|
||||
writeLinef(b, "iam_instance_profile_worker_nodes = %q", v.IAMProfileWorkerNodes)
|
||||
writeLinef(b, "debug = %t", v.Debug)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// String returns a string representation of the variables, formatted as Terraform variables.
|
||||
func (v *GCPVariables) String() string {
|
||||
func (v *GCPClusterVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
b.WriteString(v.CommonVariables.String())
|
||||
writeLinef(b, "project = %q", v.Project)
|
||||
|
|
@ -114,8 +131,31 @@ func (v *GCPVariables) String() string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
// AzureVariables is user configuration for creating a cluster with Terraform on Azure.
|
||||
type AzureVariables struct {
|
||||
// GCPIAMVariables is user configuration for creating the IAM confioguration with Terraform on GCP.
|
||||
type GCPIAMVariables struct {
|
||||
// Project is the ID of the GCP project to use.
|
||||
Project string
|
||||
// Region is the GCP region to use.
|
||||
Region string
|
||||
// Zone is the GCP zone to use.
|
||||
Zone string
|
||||
// ServiceAccountID is the ID of the service account to use.
|
||||
ServiceAccountID string
|
||||
}
|
||||
|
||||
// String returns a string representation of the IAM-specific variables, formatted as Terraform variables.
|
||||
func (v *GCPIAMVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
writeLinef(b, "project_id = %q", v.Project)
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
writeLinef(b, "zone = %q", v.Zone)
|
||||
writeLinef(b, "service_account_id = %q", v.ServiceAccountID)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// AzureClusterVariables is user configuration for creating a cluster with Terraform on Azure.
|
||||
type AzureClusterVariables struct {
|
||||
// CommonVariables contains common variables.
|
||||
CommonVariables
|
||||
|
||||
|
|
@ -140,7 +180,7 @@ type AzureVariables struct {
|
|||
}
|
||||
|
||||
// String returns a string representation of the variables, formatted as Terraform variables.
|
||||
func (v *AzureVariables) String() string {
|
||||
func (v *AzureClusterVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
b.WriteString(v.CommonVariables.String())
|
||||
writeLinef(b, "resource_group = %q", v.ResourceGroup)
|
||||
|
|
@ -156,6 +196,26 @@ func (v *AzureVariables) String() string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
// AzureIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure.
|
||||
type AzureIAMVariables struct {
|
||||
// Region is the Azure region to use. (e.g. westus)
|
||||
Region string
|
||||
// ServicePrincipal is the name of the service principal to use.
|
||||
ServicePrincipal string
|
||||
// ResourceGroup is the name of the resource group to use.
|
||||
ResourceGroup string
|
||||
}
|
||||
|
||||
// String returns a string representation of the IAM-specific variables, formatted as Terraform variables.
|
||||
func (v *AzureIAMVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
writeLinef(b, "service_principal_name = %q", v.ServicePrincipal)
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
writeLinef(b, "resource_group_name = %q", v.ResourceGroup)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// QEMUVariables is user configuration for creating a QEMU cluster with Terraform.
|
||||
type QEMUVariables struct {
|
||||
// CommonVariables contains common variables.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue