get.porter.sh/porter@v1.3.0/tests/smoke/desiredstate_test.go (about)

     1  //go:build smoke
     2  
     3  package smoke
     4  
     5  import (
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"get.porter.sh/porter/pkg/yaml"
    10  	"get.porter.sh/porter/tests"
    11  	"get.porter.sh/porter/tests/tester"
    12  	"github.com/stretchr/testify/require"
    13  	"github.com/uwu-tools/magex/mgx"
    14  	"github.com/uwu-tools/magex/shx"
    15  )
    16  
    17  // Test desired state workflows used by the porter operator
    18  func TestDesiredState(t *testing.T) {
    19  	// I am always using require, so that we stop immediately upon an error
    20  	// A long test is hard to debug when it fails in the middle and keeps going
    21  	test, err := tester.NewTest(t)
    22  	defer test.Close()
    23  	require.NoError(t, err, "test setup failed")
    24  
    25  	test.PrepareTestBundle()
    26  	test.Chdir(test.TestDir)
    27  
    28  	// Try to import an installation with an invalid schema
    29  	_, _, err = test.RunPorter("installation", "apply", filepath.Join(test.RepoRoot, "tests/testdata/installations/invalid-schema.yaml"))
    30  	require.Error(t, err, "apply should have failed because the schema of the imported document is incorrect")
    31  	require.Contains(t, err.Error(), "invalid installation")
    32  
    33  	// Try to import a credential set with an invalid schema
    34  	_, _, err = test.RunPorter("credentials", "apply", filepath.Join(test.RepoRoot, "tests/testdata/creds/invalid-schema.yaml"))
    35  	require.Error(t, err, "apply should have failed because the schema of the imported document is incorrect")
    36  	require.Contains(t, err.Error(), "invalid credential set")
    37  
    38  	// Try to import a parameter set with an invalid schema
    39  	_, _, err = test.RunPorter("parameters", "apply", filepath.Join(test.RepoRoot, "tests/testdata/params/invalid-schema.yaml"))
    40  	require.Error(t, err, "apply should have failed because the schema of the imported document is incorrect")
    41  	require.Contains(t, err.Error(), "invalid parameter set")
    42  
    43  	// Import some creds and params for mybuns
    44  	test.RequirePorter("parameters", "apply", filepath.Join(test.RepoRoot, "tests/testdata/params/mybuns.yaml"), "--namespace=")
    45  	test.RequirePorter("credentials", "apply", filepath.Join(test.RepoRoot, "tests/testdata/creds/mybuns.yaml"), "--namespace=")
    46  	test.RequirePorter("credentials", "apply", filepath.Join(test.RepoRoot, "tests/testdata/creds/alt-mybuns.yaml"), "--namespace=")
    47  
    48  	mgx.Must(shx.Copy(filepath.Join(test.RepoRoot, "tests/testdata/installations/mybuns.yaml"), "mybuns.yaml"))
    49  
    50  	// Import an installation with uninstalled=true, should do nothing
    51  	test.EditYaml("mybuns.yaml", func(yq *yaml.Editor) error {
    52  		return yq.SetValue("uninstalled", "true")
    53  	})
    54  	_, stderr, err := test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
    55  	require.NoError(t, err)
    56  	require.Contains(t, stderr, "Ignoring because installation.uninstalled is true but the installation doesn't exist yet")
    57  
    58  	// Now set uninstalled = false so that it's installed for the first time
    59  	test.EditYaml("mybuns.yaml", func(yq *yaml.Editor) error {
    60  		return yq.SetValue("uninstalled", "false")
    61  	})
    62  
    63  	// Import an installation, since the file is missing a namespace, it should use the --namespace flag value
    64  	// This also tests out that --allow-docker-host-access is being defaulted properly from the Porter config file
    65  	output, stderr, err := test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
    66  	require.NoError(t, err)
    67  	require.Contains(t, output, "The installation is out-of-sync, running the install action")
    68  	require.Contains(t, output, "Triggering because the installation has not completed successfully yet")
    69  	installation := test.RequireInstallationExists("operator", "mybuns")
    70  	require.Equal(t, "succeeded", installation.Status.ResultStatus)
    71  
    72  	// Repeat the apply command, this should result in an upgrade because mybuns has different parameters for install and upgrade
    73  	// so porter will detect different params and run again.
    74  	_, stderr = test.RequirePorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
    75  	tests.RequireOutputContains(t, stderr, "The installation is out-of-sync, running the upgrade action...")
    76  
    77  	// Repeat the apply command, there should be no changes detected now that it's two upgrades in a row.
    78  	// Using dry run because we just want to know if it _would_ be re-executed.
    79  	_, output, err = test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator", "--dry-run")
    80  	require.NoError(t, err)
    81  	tests.RequireOutputContains(t, output, "The installation is already up-to-date")
    82  
    83  	// Repeat the apply command with --force, even though there are no changes, this should trigger an upgrade.
    84  	_, output, err = test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator", "--dry-run", "--force")
    85  	require.NoError(t, err)
    86  	tests.RequireOutputContains(t, output, "The installation is up-to-date but will be re-applied because --force was specified")
    87  
    88  	// Edit the installation file with a minor change that shouldn't trigger reconciliation
    89  	test.EditYaml("mybuns.yaml", func(yq *yaml.Editor) error {
    90  		return yq.SetValue("labels.thing", "2")
    91  	})
    92  	_, output, err = test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
    93  	require.NoError(t, err)
    94  	tests.RequireOutputContains(t, output, "The installation is already up-to-date")
    95  
    96  	// Change a bundle parameter and trigger an upgrade
    97  	test.EditYaml("mybuns.yaml", func(yq *yaml.Editor) error {
    98  		return yq.SetValue("parameters.log_level", "3")
    99  	})
   100  	_, output, err = test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
   101  	require.NoError(t, err)
   102  	tests.RequireOutputContains(t, output, "The installation is out-of-sync, running the upgrade action")
   103  
   104  	displayInstallation, err := test.ShowInstallation("operator", "mybuns")
   105  	require.NoError(t, err)
   106  	require.Equal(t, float64(3), displayInstallation.Parameters["log_level"])
   107  
   108  	// Switch credentials and trigger an upgrade
   109  	test.EditYaml("mybuns.yaml", func(yq *yaml.Editor) error {
   110  		return yq.SetValue("credentialSets[0]", "alt-mybuns")
   111  	})
   112  	_, output, err = test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
   113  	require.NoError(t, err)
   114  	tests.RequireOutputContains(t, output, "The installation is out-of-sync, running the upgrade action")
   115  
   116  	// Uninstall by setting uninstalled: true
   117  	test.EditYaml("mybuns.yaml", func(yq *yaml.Editor) error {
   118  		return yq.SetValue("uninstalled", "true")
   119  	})
   120  	_, output, err = test.RunPorter("installation", "apply", "mybuns.yaml", "--namespace", "operator")
   121  	require.NoError(t, err)
   122  	tests.RequireOutputContains(t, output, "The installation is out-of-sync, running the uninstall action")
   123  }