Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli: write infrastructure to new state file #2321

Merged
merged 7 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
/cli/internal/libvirt @daniel-weisse
/cli/internal/terraform @elchead
/cli/internal/upgrade @elchead
/cli/internal/state @elchead
/csi @daniel-weisse
/debugd @malt3
/disk-mapper @daniel-weisse
Expand All @@ -23,7 +24,6 @@
/hack/bazel-deps-mirror @malt3
/hack/cli-k8s-compatibility @derpsteb
/hack/clidocgen @thomasten
/hack/configapi @elchead
/hack/fetch-broken-e2e @katexochen
/hack/gocoverage @katexochen
/hack/oci-pin @malt3
Expand Down
3 changes: 2 additions & 1 deletion cli/internal/cloudcmd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd",
visibility = ["//cli:__subpackages__"],
deps = [
"//cli/internal/clusterid",
"//cli/internal/cmd/pathprefix",
"//cli/internal/libvirt",
"//cli/internal/state",
"//cli/internal/terraform",
"//internal/atls",
"//internal/attestation/choose",
Expand Down Expand Up @@ -60,6 +60,7 @@ go_test(
],
embed = [":cloudcmd"],
deps = [
"//cli/internal/state",
"//cli/internal/terraform",
"//internal/attestation/measurements",
"//internal/attestation/variant",
Expand Down
3 changes: 2 additions & 1 deletion cli/internal/cloudcmd/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"context"
"io"

"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
Expand All @@ -33,7 +34,7 @@ type tfCommonClient interface {
type tfResourceClient interface {
tfCommonClient
ApplyCluster(ctx context.Context, provider cloudprovider.Provider, logLevel terraform.LogLevel) (terraform.ApplyOutput, error)
ShowCluster(ctx context.Context, provider cloudprovider.Provider) (terraform.ApplyOutput, error)
ShowInfrastructure(ctx context.Context, provider cloudprovider.Provider) (state.Infrastructure, error)
}

type tfIAMClient interface {
Expand Down
7 changes: 4 additions & 3 deletions cli/internal/cloudcmd/clients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"testing"

"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
Expand All @@ -31,7 +32,7 @@ type stubTerraformClient struct {
iamOutput terraform.IAMOutput
uid string
attestationURL string
applyOutput terraform.ApplyOutput
infraState state.Infrastructure
cleanUpWorkspaceCalled bool
removeInstallerCalled bool
destroyCalled bool
Expand Down Expand Up @@ -77,9 +78,9 @@ func (c *stubTerraformClient) RemoveInstaller() {
c.removeInstallerCalled = true
}

func (c *stubTerraformClient) ShowCluster(_ context.Context, _ cloudprovider.Provider) (terraform.ApplyOutput, error) {
func (c *stubTerraformClient) ShowInfrastructure(_ context.Context, _ cloudprovider.Provider) (state.Infrastructure, error) {
c.showCalled = true
return c.applyOutput, c.showErr
return c.infraState, c.showErr
}

func (c *stubTerraformClient) ShowIAM(_ context.Context, _ cloudprovider.Provider) (terraform.IAMOutput, error) {
Expand Down
26 changes: 8 additions & 18 deletions cli/internal/cloudcmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (
"runtime"
"strings"

"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/libvirt"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config"
Expand Down Expand Up @@ -64,19 +64,19 @@ type CreateOptions struct {
}

// Create creates the handed amount of instances and all the needed resources.
func (c *Creator) Create(ctx context.Context, opts CreateOptions) (clusterid.File, error) {
func (c *Creator) Create(ctx context.Context, opts CreateOptions) (state.Infrastructure, error) {
provider := opts.Config.GetProvider()
attestationVariant := opts.Config.GetAttestationConfig().GetVariant()
region := opts.Config.GetRegion()
image, err := c.image.FetchReference(ctx, provider, attestationVariant, opts.Config.Image, region)
if err != nil {
return clusterid.File{}, fmt.Errorf("fetching image reference: %w", err)
return state.Infrastructure{}, fmt.Errorf("fetching image reference: %w", err)
}
opts.image = image

cl, err := c.newTerraformClient(ctx, opts.TFWorkspace)
if err != nil {
return clusterid.File{}, err
return state.Infrastructure{}, err
}
defer cl.RemoveInstaller()

Expand All @@ -96,7 +96,7 @@ func (c *Creator) Create(ctx context.Context, opts CreateOptions) (clusterid.Fil
tfOutput, err = c.createOpenStack(ctx, cl, opts)
case cloudprovider.QEMU:
if runtime.GOARCH != "amd64" || runtime.GOOS != "linux" {
return clusterid.File{}, fmt.Errorf("creation of a QEMU based Constellation is not supported for %s/%s", runtime.GOOS, runtime.GOARCH)
return state.Infrastructure{}, fmt.Errorf("creation of a QEMU based Constellation is not supported for %s/%s", runtime.GOOS, runtime.GOARCH)
}
lv := c.newLibvirtRunner()
qemuOpts := qemuCreateOptions{
Expand All @@ -106,23 +106,13 @@ func (c *Creator) Create(ctx context.Context, opts CreateOptions) (clusterid.Fil

tfOutput, err = c.createQEMU(ctx, cl, lv, qemuOpts)
default:
return clusterid.File{}, fmt.Errorf("unsupported cloud provider: %s", opts.Provider)
return state.Infrastructure{}, fmt.Errorf("unsupported cloud provider: %s", opts.Provider)
}

if err != nil {
return clusterid.File{}, fmt.Errorf("creating cluster: %w", err)
return state.Infrastructure{}, fmt.Errorf("creating cluster: %w", err)
}
res := clusterid.File{
CloudProvider: opts.Provider,
IP: tfOutput.IP,
APIServerCertSANs: tfOutput.APIServerCertSANs,
InitSecret: []byte(tfOutput.Secret),
UID: tfOutput.UID,
}
if tfOutput.Azure != nil {
res.AttestationURL = tfOutput.Azure.AttestationURL
}
return res, nil
return terraform.ConvertToInfrastructure(tfOutput), nil
}

func (c *Creator) createAWS(ctx context.Context, cl tfResourceClient, opts CreateOptions) (tfOutput terraform.ApplyOutput, retErr error) {
Expand Down
3 changes: 1 addition & 2 deletions cli/internal/cloudcmd/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ func TestCreator(t *testing.T) {
}
} else {
assert.NoError(err)
assert.Equal(tc.provider, idFile.CloudProvider)
assert.Equal(ip, idFile.IP)
assert.Equal(ip, idFile.ClusterEndpoint)
}
})
}
Expand Down
2 changes: 2 additions & 0 deletions cli/internal/cmd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ go_library(
"//cli/internal/helm",
"//cli/internal/kubecmd",
"//cli/internal/libvirt",
"//cli/internal/state",
"//cli/internal/terraform",
"//disk-mapper/recoverproto",
"//internal/api/attestationconfigapi",
Expand Down Expand Up @@ -137,6 +138,7 @@ go_test(
"//cli/internal/cmd/pathprefix",
"//cli/internal/helm",
"//cli/internal/kubecmd",
"//cli/internal/state",
"//cli/internal/terraform",
"//disk-mapper/recoverproto",
"//internal/api/attestationconfigapi",
Expand Down
4 changes: 2 additions & 2 deletions cli/internal/cmd/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"context"

"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/cloud/gcpshared"
Expand All @@ -20,7 +20,7 @@ type cloudCreator interface {
Create(
ctx context.Context,
opts cloudcmd.CreateOptions,
) (clusterid.File, error)
) (state.Infrastructure, error)
}

type cloudIAMCreator interface {
Expand Down
11 changes: 5 additions & 6 deletions cli/internal/cmd/cloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"testing"

"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/cloud/gcpshared"
Expand All @@ -27,17 +27,16 @@ func TestMain(m *testing.M) {

type stubCloudCreator struct {
createCalled bool
id clusterid.File
state state.Infrastructure
createErr error
}

func (c *stubCloudCreator) Create(
_ context.Context,
opts cloudcmd.CreateOptions,
) (clusterid.File, error) {
_ cloudcmd.CreateOptions,
) (state.Infrastructure, error) {
c.createCalled = true
c.id.CloudProvider = opts.Provider
return c.id, c.createErr
return c.state, c.createErr
}

type stubCloudTerminator struct {
Expand Down
21 changes: 20 additions & 1 deletion cli/internal/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import (
"io/fs"

"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
Expand Down Expand Up @@ -162,21 +165,37 @@ func (c *createCmd) create(cmd *cobra.Command, creator cloudCreator, fileHandler
TFLogLevel: flags.tfLogLevel,
TFWorkspace: constants.TerraformWorkingDir,
}
idFile, err := creator.Create(cmd.Context(), opts)
infraState, err := creator.Create(cmd.Context(), opts)
spinner.Stop()
if err != nil {
return translateCreateErrors(cmd, c.pf, err)
}
c.log.Debugf("Successfully created the cloud resources for the cluster")

idFile := convertToIDFile(infraState, provider)
if err := fileHandler.WriteJSON(constants.ClusterIDsFilename, idFile, file.OptNone); err != nil {
return err
}
state := state.NewState(infraState)

if err := fileHandler.WriteYAML(constants.StateFilename, state, file.OptNone); err != nil {
return err
}

cmd.Println("Your Constellation cluster was created successfully.")
return nil
}

func convertToIDFile(infra state.Infrastructure, provider cloudprovider.Provider) clusterid.File {
var file clusterid.File
file.CloudProvider = provider
file.IP = infra.ClusterEndpoint
file.APIServerCertSANs = infra.APIServerCertSANs
file.InitSecret = []byte(infra.InitSecret) // Convert string to []byte
file.UID = infra.UID
return file
}

// parseCreateFlags parses the flags of the create command.
func (c *createCmd) parseCreateFlags(cmd *cobra.Command) (createFlags, error) {
yes, err := cmd.Flags().GetBool("yes")
Expand Down
19 changes: 15 additions & 4 deletions cli/internal/cmd/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"testing"

"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"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"
Expand All @@ -30,7 +31,7 @@ func TestCreate(t *testing.T) {
require.NoError(file.WriteYAML(constants.ConfigFilename, defaultConfigWithExpectedMeasurements(t, config.Default(), provider)))
return fs
}
idFile := clusterid.File{IP: "192.0.2.1"}
infraState := state.Infrastructure{ClusterEndpoint: "192.0.2.1"}
someErr := errors.New("failed")

testCases := map[string]struct {
Expand All @@ -46,13 +47,13 @@ func TestCreate(t *testing.T) {
}{
"create": {
setupFs: fsWithDefaultConfig,
creator: &stubCloudCreator{id: idFile},
creator: &stubCloudCreator{state: infraState},
provider: cloudprovider.GCP,
yesFlag: true,
},
"interactive": {
setupFs: fsWithDefaultConfig,
creator: &stubCloudCreator{id: idFile},
creator: &stubCloudCreator{state: infraState},
provider: cloudprovider.Azure,
stdin: "yes\n",
},
Expand Down Expand Up @@ -156,9 +157,19 @@ func TestCreate(t *testing.T) {
var gotIDFile clusterid.File
require.NoError(fileHandler.ReadJSON(constants.ClusterIDsFilename, &gotIDFile))
assert.Equal(gotIDFile, clusterid.File{
IP: idFile.IP,
IP: infraState.ClusterEndpoint,
CloudProvider: tc.provider,
})

var gotState state.State
expectedState := state.Infrastructure{
ClusterEndpoint: "192.0.2.1",
APIServerCertSANs: []string{},
}
require.NoError(fileHandler.ReadYAML(constants.StateFilename, &gotState))
assert.Equal("v1", gotState.Version)
assert.Equal(expectedState, gotState.Infrastructure)

}
}
})
Expand Down
19 changes: 11 additions & 8 deletions cli/internal/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix"
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/cli/internal/kubecmd"
"github.com/edgelesssys/constellation/v2/cli/internal/state"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config"
Expand Down Expand Up @@ -75,12 +76,12 @@ type initCmd struct {
merger configMerger
spinner spinnerInterf
fileHandler file.Handler
clusterShower clusterShower
clusterShower infrastructureShower
pf pathprefix.PathPrefixer
}

func newInitCmd(
clusterShower clusterShower, fileHandler file.Handler,
clusterShower infrastructureShower, fileHandler file.Handler,
spinner spinnerInterf, merger configMerger, log debugLog,
) *initCmd {
return &initCmd{
Expand Down Expand Up @@ -261,9 +262,9 @@ func (i *initCmd) initialize(
return fmt.Errorf("applying attestation config: %w", err)
}

output, err := i.clusterShower.ShowCluster(cmd.Context(), conf.GetProvider())
infraState, err := i.clusterShower.ShowInfrastructure(cmd.Context(), conf.GetProvider())
if err != nil {
return fmt.Errorf("getting Terraform output: %w", err)
return fmt.Errorf("getting infrastructure state: %w", err)
}

i.spinner.Start("Installing Kubernetes components ", false)
Expand All @@ -277,7 +278,7 @@ func (i *initCmd) initialize(
if err != nil {
return fmt.Errorf("creating Helm client: %w", err)
}
executor, includesUpgrades, err := helmApplier.PrepareApply(conf, idFile, options, output,
executor, includesUpgrades, err := helmApplier.PrepareApply(conf, idFile, options, infraState,
serviceAccURI, masterSecret)
if err != nil {
return fmt.Errorf("getting Helm chart executor: %w", err)
Expand Down Expand Up @@ -671,9 +672,11 @@ type attestationConfigApplier interface {
}

type helmApplier interface {
PrepareApply(conf *config.Config, idFile clusterid.File, flags helm.Options, tfOutput terraform.ApplyOutput, serviceAccURI string, masterSecret uri.MasterSecret) (helm.Applier, bool, error)
PrepareApply(conf *config.Config, idFile clusterid.File,
flags helm.Options, infra state.Infrastructure, serviceAccURI string, masterSecret uri.MasterSecret) (
helm.Applier, bool, error)
}

type clusterShower interface {
ShowCluster(ctx context.Context, provider cloudprovider.Provider) (terraform.ApplyOutput, error)
type infrastructureShower interface {
ShowInfrastructure(ctx context.Context, provider cloudprovider.Provider) (state.Infrastructure, error)
}
Loading