cli: remove TF ApplyOutput dependency in CLI (#2323)

This commit is contained in:
Adrian Stobbe 2023-09-25 17:10:23 +02:00 committed by GitHub
parent 322c4aad10
commit 4680882708
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 174 deletions

View file

@ -173,96 +173,58 @@ func (c *Client) ShowIAM(ctx context.Context, provider cloudprovider.Provider) (
// ShowInfrastructure reads the state of Constellation cluster resources from Terraform.
func (c *Client) ShowInfrastructure(ctx context.Context, provider cloudprovider.Provider) (state.Infrastructure, error) {
tfOutput, err := c.ShowCluster(ctx, provider)
if err != nil {
return state.Infrastructure{}, err
}
return ConvertToInfrastructure(tfOutput), nil
}
// ConvertToInfrastructure converts the Terraform output of a cluster creation or apply operation to a state.Infrastructure.
func ConvertToInfrastructure(applyOutput ApplyOutput) state.Infrastructure {
var infra state.Infrastructure
infra.UID = applyOutput.UID
infra.ClusterEndpoint = applyOutput.IP
infra.InitSecret = applyOutput.Secret
infra.APIServerCertSANs = applyOutput.APIServerCertSANs
if applyOutput.Azure != nil {
infra.Azure = &state.Azure{
ResourceGroup: applyOutput.Azure.ResourceGroup,
SubscriptionID: applyOutput.Azure.SubscriptionID,
UserAssignedIdentity: applyOutput.Azure.UserAssignedIdentity,
NetworkSecurityGroupName: applyOutput.Azure.NetworkSecurityGroupName,
LoadBalancerName: applyOutput.Azure.LoadBalancerName,
AttestationURL: applyOutput.Azure.AttestationURL,
}
}
if applyOutput.GCP != nil {
infra.GCP = &state.GCP{
ProjectID: applyOutput.GCP.ProjectID,
IPCidrNode: applyOutput.GCP.IPCidrNode,
IPCidrPod: applyOutput.GCP.IPCidrPod,
}
}
return infra
}
// ShowCluster reads the state of Constellation cluster resources from Terraform.
func (c *Client) ShowCluster(ctx context.Context, provider cloudprovider.Provider) (ApplyOutput, error) {
tfState, err := c.tf.Show(ctx)
if err != nil {
return ApplyOutput{}, fmt.Errorf("terraform show: %w", err)
return state.Infrastructure{}, fmt.Errorf("terraform show: %w", err)
}
if tfState.Values == nil {
return ApplyOutput{}, errors.New("terraform show: no values returned")
return state.Infrastructure{}, errors.New("terraform show: no values returned")
}
ipOutput, ok := tfState.Values.Outputs["ip"]
if !ok {
return ApplyOutput{}, errors.New("no IP output found")
return state.Infrastructure{}, errors.New("no IP output found")
}
ip, ok := ipOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in IP output: not a string")
return state.Infrastructure{}, errors.New("invalid type in IP output: not a string")
}
apiServerCertSANsOutput, ok := tfState.Values.Outputs["api_server_cert_sans"]
if !ok {
return ApplyOutput{}, errors.New("no api_server_cert_sans output found")
return state.Infrastructure{}, errors.New("no api_server_cert_sans output found")
}
apiServerCertSANsUntyped, ok := apiServerCertSANsOutput.Value.([]any)
if !ok {
return ApplyOutput{}, fmt.Errorf("invalid type in api_server_cert_sans output: %s is not a list of elements", apiServerCertSANsOutput.Type.FriendlyName())
return state.Infrastructure{}, fmt.Errorf("invalid type in api_server_cert_sans output: %s is not a list of elements", apiServerCertSANsOutput.Type.FriendlyName())
}
apiServerCertSANs, err := toStringSlice(apiServerCertSANsUntyped)
if err != nil {
return ApplyOutput{}, fmt.Errorf("convert api_server_cert_sans output: %w", err)
return state.Infrastructure{}, fmt.Errorf("convert api_server_cert_sans output: %w", err)
}
secretOutput, ok := tfState.Values.Outputs["initSecret"]
if !ok {
return ApplyOutput{}, errors.New("no initSecret output found")
return state.Infrastructure{}, errors.New("no initSecret output found")
}
secret, ok := secretOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in initSecret output: not a string")
return state.Infrastructure{}, errors.New("invalid type in initSecret output: not a string")
}
uidOutput, ok := tfState.Values.Outputs["uid"]
if !ok {
return ApplyOutput{}, errors.New("no uid output found")
return state.Infrastructure{}, errors.New("no uid output found")
}
uid, ok := uidOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in uid output: not a string")
return state.Infrastructure{}, errors.New("invalid type in uid output: not a string")
}
res := ApplyOutput{
IP: ip,
res := state.Infrastructure{
ClusterEndpoint: ip,
APIServerCertSANs: apiServerCertSANs,
Secret: secret,
InitSecret: secret,
UID: uid,
}
@ -270,32 +232,32 @@ func (c *Client) ShowCluster(ctx context.Context, provider cloudprovider.Provide
case cloudprovider.GCP:
gcpProjectOutput, ok := tfState.Values.Outputs["project"]
if !ok {
return ApplyOutput{}, errors.New("no project output found")
return state.Infrastructure{}, errors.New("no project output found")
}
gcpProject, ok := gcpProjectOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in project output: not a string")
return state.Infrastructure{}, errors.New("invalid type in project output: not a string")
}
cidrNodesOutput, ok := tfState.Values.Outputs["ip_cidr_nodes"]
if !ok {
return ApplyOutput{}, errors.New("no ip_cidr_nodes output found")
return state.Infrastructure{}, errors.New("no ip_cidr_nodes output found")
}
cidrNodes, ok := cidrNodesOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in ip_cidr_nodes output: not a string")
return state.Infrastructure{}, errors.New("invalid type in ip_cidr_nodes output: not a string")
}
cidrPodsOutput, ok := tfState.Values.Outputs["ip_cidr_pods"]
if !ok {
return ApplyOutput{}, errors.New("no ip_cidr_pods output found")
return state.Infrastructure{}, errors.New("no ip_cidr_pods output found")
}
cidrPods, ok := cidrPodsOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in ip_cidr_pods output: not a string")
return state.Infrastructure{}, errors.New("invalid type in ip_cidr_pods output: not a string")
}
res.GCP = &GCPApplyOutput{
res.GCP = &state.GCP{
ProjectID: gcpProject,
IPCidrNode: cidrNodes,
IPCidrPod: cidrPods,
@ -303,57 +265,57 @@ func (c *Client) ShowCluster(ctx context.Context, provider cloudprovider.Provide
case cloudprovider.Azure:
attestationURLOutput, ok := tfState.Values.Outputs["attestationURL"]
if !ok {
return ApplyOutput{}, errors.New("no attestationURL output found")
return state.Infrastructure{}, errors.New("no attestationURL output found")
}
attestationURL, ok := attestationURLOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in attestationURL output: not a string")
return state.Infrastructure{}, errors.New("invalid type in attestationURL output: not a string")
}
azureUAMIOutput, ok := tfState.Values.Outputs["user_assigned_identity_client_id"]
if !ok {
return ApplyOutput{}, errors.New("no user_assigned_identity_client_id output found")
return state.Infrastructure{}, errors.New("no user_assigned_identity_client_id output found")
}
azureUAMI, ok := azureUAMIOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in user_assigned_identity_client_id output: not a string")
return state.Infrastructure{}, errors.New("invalid type in user_assigned_identity_client_id output: not a string")
}
rgOutput, ok := tfState.Values.Outputs["resource_group"]
if !ok {
return ApplyOutput{}, errors.New("no resource_group output found")
return state.Infrastructure{}, errors.New("no resource_group output found")
}
rg, ok := rgOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in resource_group output: not a string")
return state.Infrastructure{}, errors.New("invalid type in resource_group output: not a string")
}
subscriptionOutput, ok := tfState.Values.Outputs["subscription_id"]
if !ok {
return ApplyOutput{}, errors.New("no subscription_id output found")
return state.Infrastructure{}, errors.New("no subscription_id output found")
}
subscriptionID, ok := subscriptionOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in subscription_id output: not a string")
return state.Infrastructure{}, errors.New("invalid type in subscription_id output: not a string")
}
networkSGNameOutput, ok := tfState.Values.Outputs["network_security_group_name"]
if !ok {
return ApplyOutput{}, errors.New("no network_security_group_name output found")
return state.Infrastructure{}, errors.New("no network_security_group_name output found")
}
networkSGName, ok := networkSGNameOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in network_security_group_name output: not a string")
return state.Infrastructure{}, errors.New("invalid type in network_security_group_name output: not a string")
}
loadBalancerNameOutput, ok := tfState.Values.Outputs["loadbalancer_name"]
if !ok {
return ApplyOutput{}, errors.New("no loadbalancer_name output found")
return state.Infrastructure{}, errors.New("no loadbalancer_name output found")
}
loadBalancerName, ok := loadBalancerNameOutput.Value.(string)
if !ok {
return ApplyOutput{}, errors.New("invalid type in loadbalancer_name output: not a string")
return state.Infrastructure{}, errors.New("invalid type in loadbalancer_name output: not a string")
}
res.Azure = &AzureApplyOutput{
res.Azure = &state.Azure{
ResourceGroup: rg,
SubscriptionID: subscriptionID,
UserAssignedIdentity: azureUAMI,
@ -386,11 +348,11 @@ func (c *Client) PrepareUpgradeWorkspace(path, backupDir string, vars Variables)
}
// ApplyCluster applies the Terraform configuration of the workspace to create or upgrade a Constellation cluster.
func (c *Client) ApplyCluster(ctx context.Context, provider cloudprovider.Provider, logLevel LogLevel) (ApplyOutput, error) {
func (c *Client) ApplyCluster(ctx context.Context, provider cloudprovider.Provider, logLevel LogLevel) (state.Infrastructure, error) {
if err := c.apply(ctx, logLevel); err != nil {
return ApplyOutput{}, err
return state.Infrastructure{}, err
}
return c.ShowCluster(ctx, provider)
return c.ShowInfrastructure(ctx, provider)
}
// ApplyIAM applies the Terraform configuration of the workspace to create or upgrade an IAM configuration.
@ -547,35 +509,6 @@ type StateMigration struct {
Hook func(ctx context.Context, tfClient TFMigrator) error
}
// ApplyOutput contains the Terraform output values of a cluster creation
// or apply operation.
type ApplyOutput struct {
IP string
APIServerCertSANs []string
Secret string
UID string
GCP *GCPApplyOutput
Azure *AzureApplyOutput
}
// AzureApplyOutput contains the Terraform output values of a terraform apply operation on Microsoft Azure.
type AzureApplyOutput struct {
ResourceGroup string
SubscriptionID string
NetworkSecurityGroupName string
LoadBalancerName string
UserAssignedIdentity string
// AttestationURL is the URL of the attestation provider.
AttestationURL string
}
// GCPApplyOutput contains the Terraform output values of a terraform apply operation on GCP.
type GCPApplyOutput struct {
ProjectID string
IPCidrNode string
IPCidrPod string
}
// IAMOutput contains the output information of the Terraform IAM operations.
type IAMOutput struct {
GCP GCPIAMOutput