cli: write infrastructure to new state file (#2321)

Co-authored-by: 3u13r <lc@edgeless.systems>
This commit is contained in:
Adrian Stobbe 2023-09-25 16:19:43 +02:00 committed by GitHub
parent 8f5a2867b4
commit 322c4aad10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 263 additions and 109 deletions

View file

@ -422,7 +422,7 @@ go_library(
deps = [
"//cli/internal/clusterid",
"//cli/internal/helm/imageversion",
"//cli/internal/terraform",
"//cli/internal/state",
"//internal/cloud/azureshared",
"//internal/cloud/cloudprovider",
"//internal/cloud/gcpshared",
@ -463,7 +463,7 @@ go_test(
embed = [":helm"],
deps = [
"//cli/internal/clusterid",
"//cli/internal/terraform",
"//cli/internal/state",
"//internal/attestation/measurements",
"//internal/cloud/azureshared",
"//internal/cloud/cloudprovider",

View file

@ -33,7 +33,7 @@ import (
"fmt"
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
@ -86,10 +86,11 @@ type Options struct {
// PrepareApply loads the charts and returns the executor to apply them.
// TODO(elchead): remove validK8sVersion by putting ValidK8sVersion into config.Config, see AB#3374.
func (h Client) PrepareApply(conf *config.Config, idFile clusterid.File, flags Options, tfOutput terraform.ApplyOutput,
serviceAccURI string, masterSecret uri.MasterSecret,
func (h Client) PrepareApply(
conf *config.Config, idFile clusterid.File,
flags Options, infra state.Infrastructure, serviceAccURI string, masterSecret uri.MasterSecret,
) (Applier, bool, error) {
releases, err := h.loadReleases(conf, masterSecret, idFile, flags, tfOutput, serviceAccURI)
releases, err := h.loadReleases(conf, masterSecret, idFile, flags, infra, serviceAccURI)
if err != nil {
return nil, false, fmt.Errorf("loading Helm releases: %w", err)
}
@ -98,13 +99,14 @@ func (h Client) PrepareApply(conf *config.Config, idFile clusterid.File, flags O
return &ChartApplyExecutor{actions: actions, log: h.log}, includesUpgrades, err
}
func (h Client) loadReleases(conf *config.Config, secret uri.MasterSecret, idFile clusterid.File, flags Options,
tfOutput terraform.ApplyOutput, serviceAccURI string,
func (h Client) loadReleases(
conf *config.Config, secret uri.MasterSecret,
idFile clusterid.File, flags Options, infra state.Infrastructure, serviceAccURI string,
) ([]Release, error) {
helmLoader := newLoader(conf, idFile, h.cliVersion)
h.log.Debugf("Created new Helm loader")
return helmLoader.loadReleases(flags.Conformance, flags.HelmWaitMode, secret,
serviceAccURI, tfOutput)
serviceAccURI, infra)
}
// Applier runs the Helm actions.

View file

@ -11,7 +11,7 @@ import (
"testing"
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility"
"github.com/edgelesssys/constellation/v2/internal/config"
@ -209,7 +209,7 @@ func TestHelmApply(t *testing.T) {
options.AllowDestructive = tc.allowDestructive
ex, includesUpgrade, err := sut.PrepareApply(cfg,
clusterid.File{UID: "testuid", MeasurementSalt: []byte("measurementSalt")}, options,
fakeTerraformOutput(csp), fakeServiceAccURI(csp),
fakeInfraOutput(csp), fakeServiceAccURI(csp),
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")})
var upgradeErr *compatibility.InvalidUpgradeError
if tc.expectError {
@ -225,12 +225,12 @@ func TestHelmApply(t *testing.T) {
}
}
func fakeTerraformOutput(csp cloudprovider.Provider) terraform.ApplyOutput {
func fakeInfraOutput(csp cloudprovider.Provider) state.Infrastructure {
switch csp {
case cloudprovider.AWS:
return terraform.ApplyOutput{}
return state.Infrastructure{}
case cloudprovider.GCP:
return terraform.ApplyOutput{GCP: &terraform.GCPApplyOutput{}}
return state.Infrastructure{GCP: &state.GCP{}}
default:
panic("invalid csp")
}

View file

@ -21,7 +21,7 @@ import (
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/helm/imageversion"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants"
@ -120,13 +120,13 @@ type releaseApplyOrder []Release
// loadReleases loads the embedded helm charts and returns them as a HelmReleases object.
func (i *chartLoader) loadReleases(conformanceMode bool, helmWaitMode WaitMode, masterSecret uri.MasterSecret,
serviceAccURI string, output terraform.ApplyOutput,
serviceAccURI string, infra state.Infrastructure,
) (releaseApplyOrder, error) {
ciliumRelease, err := i.loadRelease(ciliumInfo, helmWaitMode)
if err != nil {
return nil, fmt.Errorf("loading cilium: %w", err)
}
ciliumVals := extraCiliumValues(i.config.GetProvider(), conformanceMode, output)
ciliumVals := extraCiliumValues(i.config.GetProvider(), conformanceMode, infra)
ciliumRelease.Values = mergeMaps(ciliumRelease.Values, ciliumVals)
certManagerRelease, err := i.loadRelease(certManagerInfo, helmWaitMode)
@ -145,7 +145,7 @@ func (i *chartLoader) loadReleases(conformanceMode bool, helmWaitMode WaitMode,
return nil, fmt.Errorf("loading constellation-services: %w", err)
}
svcVals, err := extraConstellationServicesValues(i.config, masterSecret, i.idFile.UID, serviceAccURI, output)
svcVals, err := extraConstellationServicesValues(i.config, masterSecret, i.idFile.UID, serviceAccURI, infra)
if err != nil {
return nil, fmt.Errorf("extending constellation-services values: %w", err)
}

View file

@ -23,7 +23,7 @@ import (
"helm.sh/helm/v3/pkg/engine"
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/azureshared"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
@ -71,7 +71,7 @@ func TestLoadReleases(t *testing.T) {
helmReleases, err := chartLoader.loadReleases(
true, WaitModeAtomic,
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")},
fakeServiceAccURI(cloudprovider.GCP), terraform.ApplyOutput{GCP: &terraform.GCPApplyOutput{}},
fakeServiceAccURI(cloudprovider.GCP), state.Infrastructure{GCP: &state.GCP{}},
)
require.NoError(err)
for _, release := range helmReleases {
@ -175,9 +175,9 @@ func TestConstellationServices(t *testing.T) {
Key: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
Salt: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
},
"uid", serviceAccURI, terraform.ApplyOutput{
Azure: &terraform.AzureApplyOutput{},
GCP: &terraform.GCPApplyOutput{},
"uid", serviceAccURI, state.Infrastructure{
Azure: &state.Azure{},
GCP: &state.GCP{},
})
require.NoError(err)
values = mergeMaps(values, extraVals)

View file

@ -13,7 +13,7 @@ import (
"encoding/json"
"fmt"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/internal/cloud/azureshared"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/cloud/gcpshared"
@ -31,7 +31,7 @@ import (
// reuse user input from the init step. However, we can't rely on reuse-values, because
// during upgrades we all values need to be set locally as they might have changed.
// Also, the charts are not rendered correctly without all of these values.
func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, output terraform.ApplyOutput) map[string]any {
func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, output state.Infrastructure) map[string]any {
extraVals := map[string]any{}
if conformanceMode {
extraVals["kubeProxyReplacementHealthzBindAddr"] = ""
@ -42,7 +42,7 @@ func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, ou
}
}
extraVals["k8sServiceHost"] = output.IP
extraVals["k8sServiceHost"] = output.ClusterEndpoint
extraVals["k8sServicePort"] = constants.KubernetesPort
if provider == cloudprovider.GCP {
extraVals["ipv4NativeRoutingCIDR"] = output.GCP.IPCidrPod
@ -54,7 +54,7 @@ func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, ou
// extraConstellationServicesValues extends the given values map by some values depending on user input.
// Values set inside this function are only applied during init, not during upgrade.
func extraConstellationServicesValues(
cfg *config.Config, masterSecret uri.MasterSecret, uid, serviceAccURI string, output terraform.ApplyOutput,
cfg *config.Config, masterSecret uri.MasterSecret, uid, serviceAccURI string, output state.Infrastructure,
) (map[string]any, error) {
extraVals := map[string]any{}
extraVals["join-service"] = map[string]any{
@ -62,10 +62,10 @@ func extraConstellationServicesValues(
}
extraVals["verification-service"] = map[string]any{
"attestationVariant": cfg.GetAttestationConfig().GetVariant().String(),
"loadBalancerIP": output.IP,
"loadBalancerIP": output.ClusterEndpoint,
}
extraVals["konnectivity"] = map[string]any{
"loadBalancerIP": output.IP,
"loadBalancerIP": output.ClusterEndpoint,
}
extraVals["key-service"] = map[string]any{
@ -147,7 +147,7 @@ type cloudConfig struct {
}
// getCCMConfig returns the configuration needed for the Kubernetes Cloud Controller Manager on Azure.
func getCCMConfig(tfOutput terraform.AzureApplyOutput, serviceAccURI string) ([]byte, error) {
func getCCMConfig(azureState state.Azure, serviceAccURI string) ([]byte, error) {
creds, err := azureshared.ApplicationCredentialsFromURI(serviceAccURI)
if err != nil {
return nil, fmt.Errorf("getting service account key: %w", err)
@ -156,16 +156,16 @@ func getCCMConfig(tfOutput terraform.AzureApplyOutput, serviceAccURI string) ([]
config := cloudConfig{
Cloud: "AzurePublicCloud",
TenantID: creds.TenantID,
SubscriptionID: tfOutput.SubscriptionID,
ResourceGroup: tfOutput.ResourceGroup,
SubscriptionID: azureState.SubscriptionID,
ResourceGroup: azureState.ResourceGroup,
LoadBalancerSku: "standard",
SecurityGroupName: tfOutput.NetworkSecurityGroupName,
LoadBalancerName: tfOutput.LoadBalancerName,
SecurityGroupName: azureState.NetworkSecurityGroupName,
LoadBalancerName: azureState.LoadBalancerName,
UseInstanceMetadata: true,
VMType: "vmss",
Location: creds.Location,
UseManagedIdentityExtension: useManagedIdentityExtension,
UserAssignedIdentityID: tfOutput.UserAssignedIdentity,
UserAssignedIdentityID: azureState.UserAssignedIdentity,
}
return json.Marshal(config)