diff --git a/cmd/command/crypto/crypto.go b/cmd/command/crypto/crypto.go index c57c973aa..2e844df82 100644 --- a/cmd/command/crypto/crypto.go +++ b/cmd/command/crypto/crypto.go @@ -148,7 +148,7 @@ func (p *Plural) backupCommands() []cli.Command { { Name: "create", Usage: "creates a backup for your current key", - Action: common.Affirmed(p.createBackup, common.BackupMsg, "PLURAL_BACKUPS_CREATE"), + Action: common.Affirmed(p.createBackup, "Would you like to back up your repo encryption key to plural? If you chose to manage it yourself, you can find it at ~/.plural/key", "PLURAL_BACKUPS_CREATE"), }, { Name: "restore", @@ -159,7 +159,7 @@ func (p *Plural) backupCommands() []cli.Command { } } -func handleEncrypt(c *cli.Context) error { +func handleEncrypt(_ *cli.Context) error { data, err := io.ReadAll(os.Stdin) if bytes.HasPrefix(data, prefix) { _, err := os.Stdout.Write(data) @@ -237,27 +237,6 @@ func handleDecrypt(c *cli.Context) error { return nil } -// CheckGitCrypt method checks if the .gitattributes and .gitignore files exist and have desired content. -// Some old repos can have fewer files to encrypt and must be updated. -func CheckGitCrypt(c *cli.Context) error { - if !utils.Exists(common.GitAttributesFile) || !utils.Exists(common.GitIgnoreFile) { - return common.CryptoInit(c) - } - toCompare := map[string]string{common.GitAttributesFile: common.Gitattributes, common.GitIgnoreFile: common.Gitignore} - - for file, content := range toCompare { - equal, err := utils.CompareFileContent(file, content) - if err != nil { - return err - } - if !equal { - return common.CryptoInit(c) - } - } - - return nil -} - func (p *Plural) handleCryptoShare(c *cli.Context) error { p.InitPluralClient() emails := c.StringSlice("email") @@ -284,7 +263,7 @@ func (p *Plural) handleSetupKeys(c *cli.Context) error { return nil } -func exportKey(c *cli.Context) error { +func exportKey(_ *cli.Context) error { key, err := crypto.Materialize() if err != nil { return err @@ -300,7 +279,7 @@ func exportKey(c *cli.Context) error { return nil } -func importKey(c *cli.Context) error { +func importKey(_ *cli.Context) error { data, err := io.ReadAll(os.Stdin) if err != nil { return err @@ -331,7 +310,7 @@ func randString(c *cli.Context) error { return nil } -func handleKeygen(c *cli.Context) error { +func handleKeygen(_ *cli.Context) error { path, err := homedir.Expand("~/.ssh") if err != nil { return err @@ -369,7 +348,7 @@ func handleKeygen(c *cli.Context) error { return nil } -func (p *Plural) handleRecover(c *cli.Context) error { +func (p *Plural) handleRecover(_ *cli.Context) error { if err := p.InitKube(); err != nil { return err } @@ -398,7 +377,7 @@ func (p *Plural) handleRecover(c *cli.Context) error { return nil } -func (p *Plural) listBackups(c *cli.Context) error { +func (p *Plural) listBackups(_ *cli.Context) error { p.InitPluralClient() backups, err := p.ListKeyBackups() @@ -412,7 +391,7 @@ func (p *Plural) listBackups(c *cli.Context) error { }) } -func (p *Plural) createBackup(c *cli.Context) error { +func (p *Plural) createBackup(_ *cli.Context) error { p.InitPluralClient() return crypto.BackupKey(p.Client) } diff --git a/cmd/command/crypto/crypto_test.go b/cmd/command/crypto/crypto_test.go index 057994273..c94d99dbf 100644 --- a/cmd/command/crypto/crypto_test.go +++ b/cmd/command/crypto/crypto_test.go @@ -6,7 +6,6 @@ import ( "path" "testing" - "github.com/pluralsh/plural-cli/cmd/command/crypto" pluralclient "github.com/pluralsh/plural-cli/pkg/client" "github.com/pluralsh/plural-cli/pkg/common" @@ -15,11 +14,9 @@ import ( "github.com/pluralsh/plural-cli/pkg/config" pluraltest "github.com/pluralsh/plural-cli/pkg/test" "github.com/pluralsh/plural-cli/pkg/test/mocks" - "github.com/pluralsh/plural-cli/pkg/utils" "github.com/pluralsh/plural-cli/pkg/utils/git" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "github.com/urfave/cli" v1 "k8s.io/api/core/v1" ) @@ -261,76 +258,6 @@ func TestRecover(t *testing.T) { } } -func TestCheckGitCrypt(t *testing.T) { - tests := []struct { - name string - createFiles bool - }{ - { - name: "test when .gitattributes and .gitignore don't exist", - }, - { - name: "test when .gitattributes and .gitignore exist with the wrong content", - createFiles: true, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - // create temp environment - currentDir, err := os.Getwd() - assert.NoError(t, err) - dir, err := os.MkdirTemp("", "config") - assert.NoError(t, err) - defer func(path, currentDir string) { - _ = os.RemoveAll(path) - _ = os.Chdir(currentDir) - }(dir, currentDir) - os.Setenv("HOME", dir) - defer os.Unsetenv("HOME") - defaultConfig := pluraltest.GenDefaultConfig() - err = defaultConfig.Save(config.ConfigName) - assert.NoError(t, err) - err = os.WriteFile(path.Join(dir, ".plural", "key"), []byte("key: abc"), 0644) - assert.NoError(t, err) - - err = os.Chdir(dir) - assert.NoError(t, err) - _, err = git.Init() - assert.NoError(t, err) - - gitAttributes := path.Join(dir, common.GitAttributesFile) - gitIgnore := path.Join(dir, common.GitIgnoreFile) - - if test.createFiles { - err = utils.WriteFile(gitIgnore, []byte(common.Gitignore+"some extra")) - assert.NoError(t, err) - err = utils.WriteFile(gitAttributes, []byte(common.Gitattributes+"abc")) - assert.NoError(t, err) - } - - // test CheckGitCrypt - err = crypto.CheckGitCrypt(&cli.Context{}) - assert.NoError(t, err) - - // the files should exist - assert.True(t, utils.Exists(gitAttributes), ".gitattributes should exist") - assert.True(t, utils.Exists(gitIgnore), ".gitignore should exist") - - attributes, err := utils.ReadFile(gitAttributes) - assert.NoError(t, err) - if !test.createFiles { - assert.Equal(t, attributes, common.Gitattributes) - } - - ignore, err := utils.ReadFile(gitIgnore) - assert.NoError(t, err) - if !test.createFiles { - assert.Equal(t, ignore, common.Gitignore) - } - }) - } -} - func TestCheckKeyFingerprint(t *testing.T) { tests := []struct { name string diff --git a/cmd/command/up/backfill.go b/cmd/command/up/backfill.go index 9dde0c7a2..697bba407 100644 --- a/cmd/command/up/backfill.go +++ b/cmd/command/up/backfill.go @@ -1,17 +1,13 @@ package up import ( - "encoding/base64" "fmt" "strings" - "github.com/pluralsh/gqlclient" "github.com/pluralsh/plural-cli/pkg/console" - "github.com/pluralsh/plural-cli/pkg/crypto" - "github.com/samber/lo" ) -func (p *Plural) backfillEncryption() error { +func (p *Plural) ValidateConsoleConfig() error { instances, err := p.GetConsoleInstances() if err != nil { return err @@ -29,25 +25,10 @@ func (p *Plural) backfillEncryption() error { id = inst.ID } } + if id == "" { return fmt.Errorf("your configuration doesn't match to any existing Plural Console") } - prov, err := crypto.Build() - if err != nil { - return err - } - - raw, err := prov.SymmetricKey() - if err != nil { - return err - } - - encoded := base64.StdEncoding.EncodeToString(raw) - - return p.UpdateConsoleInstance(id, gqlclient.ConsoleInstanceUpdateAttributes{ - Configuration: &gqlclient.ConsoleConfigurationUpdateAttributes{ - EncryptionKey: lo.ToPtr(encoded), - }, - }) + return nil } diff --git a/cmd/command/up/up.go b/cmd/command/up/up.go index 0026458d0..a333dd11b 100644 --- a/cmd/command/up/up.go +++ b/cmd/command/up/up.go @@ -99,7 +99,7 @@ func (p *Plural) handleUp(c *cli.Context) error { return err } - if err := p.backfillEncryption(); err != nil { + if err := p.ValidateConsoleConfig(); err != nil { return err } } diff --git a/hack/e2e/setup-plural.sh b/hack/e2e/setup-plural.sh index b24ff24cc..dcb9aa038 100755 --- a/hack/e2e/setup-plural.sh +++ b/hack/e2e/setup-plural.sh @@ -108,7 +108,6 @@ export PLURAL_REPOS_RESET_CONFIRM=true export PLURAL_LOGIN_AFFIRM_CURRENT_USER=true export PLURAL_INIT_AFFIRM_CURRENT_REPO=true -export PLURAL_INIT_AFFIRM_BACKUP_KEY=false export PLURAL_DISABLE_MP_TABLE_VIEW=true diff --git a/pkg/client/plural.go b/pkg/client/plural.go index 8ac8d4855..584ad0b17 100644 --- a/pkg/client/plural.go +++ b/pkg/client/plural.go @@ -15,7 +15,6 @@ import ( "github.com/urfave/cli" "github.com/pluralsh/plural-cli/pkg/common" - "github.com/pluralsh/plural-cli/pkg/crypto" "github.com/pluralsh/plural-cli/pkg/scm" "github.com/pluralsh/plural-cli/pkg/wkspace" @@ -118,11 +117,7 @@ func (p *Plural) HandleInitWithProject(c *cli.Context) (*manifest.ProjectManifes } if utils.Exists("./workspace.yaml") { - project, err := p.ensureWorkspace(c) - if err != nil { - return nil, err - } - return project, nil + return p.ensureWorkspace() } if err := common.HandleLogin(c); err != nil { @@ -152,21 +147,12 @@ func (p *Plural) HandleInitWithProject(c *cli.Context) (*manifest.ProjectManifes return nil, fmt.Errorf("you're not in a git repository, either clone one directly or let us set it up for you") } - // create workspace.yaml when git repository is ready + // Create workspace.yaml when the Git repository is ready. if err := prov.Flush(); err != nil { return nil, err } - if err := common.CryptoInit(c); err != nil { - return nil, err - } - if common.Affirm(common.BackupMsg, "PLURAL_INIT_AFFIRM_BACKUP_KEY") { - if err := crypto.BackupKey(p.Client); err != nil { - return nil, api.GetErrorResponse(err, "BackupKey") - } - } - - if err := crypto.CreateKeyFingerprintFile(); err != nil { + if err = common.EnsureGitIgnore(); err != nil { return nil, err } @@ -179,10 +165,11 @@ func (p *Plural) HandleInitWithProject(c *cli.Context) (*manifest.ProjectManifes if gitCreated { utils.Highlight("Be sure to `cd %s` to use your configured git repo\n", repo) } + return project, nil } -func (p *Plural) ensureWorkspace(c *cli.Context) (*manifest.ProjectManifest, error) { +func (p *Plural) ensureWorkspace() (*manifest.ProjectManifest, error) { utils.Highlight("Found workspace.yaml, skipping init as this repo has already been initialized\n") utils.Highlight("Checking domain...\n") proj, err := manifest.FetchProject() @@ -210,9 +197,10 @@ func (p *Plural) ensureWorkspace(c *cli.Context) (*manifest.ProjectManifest, err return nil, err } - if err := common.CryptoInit(c); err != nil { + if err = common.EnsureGitIgnore(); err != nil { return nil, err } + return proj, nil } diff --git a/pkg/common/constants.go b/pkg/common/constants.go index 08ac54b7b..3f7c1b37d 100644 --- a/pkg/common/constants.go +++ b/pkg/common/constants.go @@ -2,8 +2,6 @@ package common import "fmt" -const BackupMsg = "Would you like to back up your repo encryption key to plural? If you chose to manage it yourself, you can find it at ~/.plural/key" - const ( AffirmUp = "Are you ready to set up your initial management cluster? You can check the generated terraform/helm to confirm everything looks good first" AffirmDown = "Are you ready to destroy your plural infrastructure? This wil destroy your management cluster, and any data stored within" diff --git a/pkg/common/crypto.go b/pkg/common/crypto.go index 3f102ff25..d14dd53da 100644 --- a/pkg/common/crypto.go +++ b/pkg/common/crypto.go @@ -23,6 +23,14 @@ helm-values/*.yaml filter=plural-crypt diff=plural-crypt .gitattributes !filter !diff ` +func EnsureGitAttributes() error { + if utils.Exists(GitAttributesFile) { + return nil + } + + return utils.WriteFile(GitAttributesFile, []byte(Gitattributes)) +} + const Gitignore = `/**/.terraform /**/.terraform* /**/terraform.tfstate* @@ -34,9 +42,18 @@ const Gitignore = `/**/.terraform .DS_STORE .vscode context.yaml* +temp ` -func CryptoInit(c *cli.Context) error { +func EnsureGitIgnore() error { + if utils.Exists(GitIgnoreFile) { + return nil + } + + return utils.WriteFile(GitIgnoreFile, []byte(Gitignore)) +} + +func CryptoInit(_ *cli.Context) error { encryptConfig := [][]string{ {"filter.plural-crypt.smudge", "plural crypto decrypt"}, {"filter.plural-crypt.clean", "plural crypto encrypt"}, @@ -51,16 +68,12 @@ func CryptoInit(c *cli.Context) error { } } - if !utils.Exists(GitAttributesFile) { - if err := utils.WriteFile(GitAttributesFile, []byte(Gitattributes)); err != nil { - return err - } + if err := EnsureGitAttributes(); err != nil { + return err } - if !utils.Exists(GitIgnoreFile) { - if err := utils.WriteFile(GitIgnoreFile, []byte(Gitignore)); err != nil { - return err - } + if err := EnsureGitIgnore(); err != nil { + return err } _, err := crypto.Build() diff --git a/pkg/crypto/config.go b/pkg/crypto/config.go index 5f2c532aa..097893297 100644 --- a/pkg/crypto/config.go +++ b/pkg/crypto/config.go @@ -29,7 +29,7 @@ func configPath() string { return pathing.SanitizeFilepath(filepath.Join(root, "crypto.yml")) } -func ReadConfig() (conf *Config, err error) { +func readConfig() (conf *Config, err error) { conf = &Config{} contents, err := os.ReadFile(configPath()) if err != nil { @@ -56,7 +56,7 @@ func Build() (prov Provider, err error) { } if utils.Exists(configPath()) { var conf *Config - conf, err = ReadConfig() + conf, err = readConfig() if err != nil { return fallbackProvider(key) } diff --git a/pkg/scm/github.go b/pkg/scm/github.go index a857a8ed7..bd78ad1d3 100644 --- a/pkg/scm/github.go +++ b/pkg/scm/github.go @@ -110,7 +110,7 @@ func (gh *Github) Setup() (con Context, err error) { } utils.Highlight("encountered an error generating, retrying...") - time.Sleep(time.Duration(time.Second)) + time.Sleep(time.Second) } if err != nil { diff --git a/pkg/scm/provider.go b/pkg/scm/provider.go index 71cfe7d45..1805a2f56 100644 --- a/pkg/scm/provider.go +++ b/pkg/scm/provider.go @@ -50,7 +50,7 @@ func Setup() (string, error) { } time.Sleep(3 * time.Second) - utils.Highlight("Cloning the repo locally (be sure you have git ssh auth set up, you can use `plural crypto ssh-keygen` to create your first ssh keys then upload the public key to your git provider)\n") + utils.Highlight("Cloning the repo locally...\n") auth, _ := git.SSHAuth("git", ctx.priv, "") if _, err := git.Clone(auth, ctx.url, ctx.repoName); err != nil { return "", err diff --git a/pkg/up/generate.go b/pkg/up/generate.go index a7e3ac144..5a8248967 100644 --- a/pkg/up/generate.go +++ b/pkg/up/generate.go @@ -10,6 +10,8 @@ import ( "github.com/pluralsh/plural-cli/pkg/utils/git" ) +const consoleValuesTemplateURL = "https://raw.githubusercontent.com/pluralsh/console/refs/heads/master/templates/values.yaml.liquid" + type templatePair struct { from string to string @@ -36,12 +38,12 @@ func (ctx *Context) Generate(gitRef string) (dir string, err error) { prov := ctx.Provider.Name() tpls := []templatePair{ - {from: ctx.path("charts/runtime/values.yaml.tpl"), to: "./helm-values/runtime.yaml", overwrite: true}, - {from: ctx.path("helm/certmanager.yaml"), to: "./helm-values/certmanager.yaml", overwrite: true}, - {from: ctx.path("helm/flux.yaml"), to: "./helm-values/flux.yaml", overwrite: true}, + {from: ctx.path("charts/runtime/values.yaml.tpl"), to: "./temp/helm/runtime.yaml", overwrite: true}, + {from: ctx.path("charts/runtime/values.yaml.liquid.tpl"), to: "./helm/runtime.yaml.liquid", overwrite: true}, {from: ctx.path(fmt.Sprintf("templates/providers/bootstrap/%s.tf", prov)), to: "terraform/mgmt/provider.tf"}, {from: ctx.path(fmt.Sprintf("templates/setup/providers/%s.tf", prov)), to: "terraform/mgmt/mgmt.tf"}, {from: ctx.path("templates/setup/console.tf"), to: "terraform/mgmt/console.tf", cloudless: true}, + {from: ctx.path("templates/setup/config-secrets.tf"), to: "terraform/mgmt/config-secrets.tf", cloudless: true}, {from: ctx.path(fmt.Sprintf("templates/providers/apps/%s.tf", prov)), to: "terraform/apps/provider.tf", cloudless: true}, {from: ctx.path("templates/providers/apps/cloud.tf"), to: "terraform/apps/provider.tf", cloud: true}, {from: ctx.path("templates/setup/cd.tf"), to: "terraform/apps/cd.tf"}, @@ -96,6 +98,10 @@ func (ctx *Context) Generate(gitRef string) (dir string, err error) { } } + if err = utils.DownloadFile(filepath.Join("helm", "console.yaml.liquid"), consoleValuesTemplateURL); err != nil { + return "", fmt.Errorf("fetch console values template: %w", err) + } + postTemplates := []templatePair{ {from: "terraform/core-infra/network.tf", to: "terraform/core-infra/network.tf"}, } diff --git a/pkg/up/prune.go b/pkg/up/prune.go index 91dd66c4d..2330e2605 100644 --- a/pkg/up/prune.go +++ b/pkg/up/prune.go @@ -29,6 +29,9 @@ func (ctx *Context) Prune() error { "helm_release.flux", "helm_release.runtime", "helm_release.console", + "kubernetes_namespace.infra", + "kubernetes_secret.runtime_config", + "kubernetes_secret.console_config", } for _, field := range toRemove { @@ -42,6 +45,8 @@ func (ctx *Context) Prune() error { } _ = os.Remove("./terraform/mgmt/console.tf") + _ = os.Remove("./terraform/mgmt/config-secrets.tf") + _ = os.RemoveAll("./temp") _ = os.RemoveAll("./terraform/apps") _ = os.Remove("./context.yaml") diff --git a/pkg/up/template.go b/pkg/up/template.go index 6980c01ab..775ca3e91 100644 --- a/pkg/up/template.go +++ b/pkg/up/template.go @@ -2,6 +2,7 @@ package up import ( "bytes" + "fmt" "regexp" "text/template" "time" @@ -46,16 +47,22 @@ func (ctx *Context) templateFrom(file, to string) error { func (ctx *Context) template(tmplate string) (string, error) { cluster, provider := ctx.Provider.Cluster(), ctx.Provider.Name() + client := api.NewClient() + + me, err := client.Me() + if err != nil { + return "", fmt.Errorf("you must run `plural login` before installing") + } + retrier := retry.NewConstant(15*time.Millisecond, 3) - eabCredential, err := retry.Retry(retrier, func() (*api.EabCredential, error) { - return client.GetEabCredential(cluster, provider) - }) + eabCredential, err := retry.Retry(retrier, func() (*api.EabCredential, error) { return client.GetEabCredential(cluster, provider) }) if err != nil { return "", err } values := map[string]interface{}{ + "UserEmail": me.Email, "Cluster": cluster, "Provider": provider, "Bucket": ctx.Provider.Bucket(),