get.porter.sh/porter@v1.3.0/pkg/storage/run_test.go (about)

     1  package storage
     2  
     3  import (
     4  	"encoding/json"
     5  	"testing"
     6  	"time"
     7  
     8  	"get.porter.sh/porter/pkg/cnab"
     9  	"get.porter.sh/porter/pkg/secrets"
    10  	"get.porter.sh/porter/pkg/test"
    11  	"github.com/cnabio/cnab-go/bundle"
    12  	"github.com/cnabio/cnab-go/bundle/definition"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestRun_NewResultFrom(t *testing.T) {
    18  	run := NewRun("dev", "mybuns")
    19  	cnabResult := cnab.Result{
    20  		ID:             "resultID",
    21  		ClaimID:        "claimID",
    22  		Created:        time.Now(),
    23  		Message:        "message",
    24  		Status:         "status",
    25  		OutputMetadata: cnab.OutputMetadata{"myoutput": map[string]string{}},
    26  		Custom:         map[string]interface{}{"custom": true},
    27  	}
    28  
    29  	result := run.NewResultFrom(cnabResult)
    30  	assert.Equal(t, cnabResult.ID, result.ID)
    31  	assert.Equal(t, run.Namespace, result.Namespace)
    32  	assert.Equal(t, run.Installation, result.Installation)
    33  	assert.Equal(t, run.ID, result.RunID)
    34  	assert.Equal(t, cnabResult.Created, result.Created)
    35  	assert.Equal(t, cnabResult.Status, result.Status)
    36  	assert.Equal(t, cnabResult.Message, result.Message)
    37  	assert.Equal(t, cnabResult.OutputMetadata, result.OutputMetadata)
    38  	assert.Equal(t, cnabResult.Custom, result.Custom)
    39  }
    40  
    41  func TestRun_ShouldRecord(t *testing.T) {
    42  	t.Run("stateless, not modifies", func(t *testing.T) {
    43  		b := bundle.Bundle{
    44  			Actions: map[string]bundle.Action{
    45  				"dry-run": {
    46  					Modifies:  false,
    47  					Stateless: true,
    48  				},
    49  			},
    50  		}
    51  
    52  		r := Run{Bundle: b, Action: "dry-run"}
    53  		assert.False(t, r.ShouldRecord())
    54  	})
    55  
    56  	t.Run("stateful, not modifies", func(t *testing.T) {
    57  		b := bundle.Bundle{
    58  			Actions: map[string]bundle.Action{
    59  				"audit": {
    60  					Modifies:  false,
    61  					Stateless: false,
    62  				},
    63  			},
    64  		}
    65  
    66  		r := Run{Bundle: b, Action: "audit"}
    67  		assert.True(t, r.ShouldRecord())
    68  	})
    69  
    70  	t.Run("modifies", func(t *testing.T) {
    71  		b := bundle.Bundle{
    72  			Actions: map[string]bundle.Action{
    73  				"editstuff": {
    74  					Modifies:  true,
    75  					Stateless: false,
    76  				},
    77  			},
    78  		}
    79  
    80  		r := Run{Bundle: b, Action: "editstuff"}
    81  		assert.True(t, r.ShouldRecord())
    82  	})
    83  
    84  	t.Run("missing definition", func(t *testing.T) {
    85  		b := bundle.Bundle{}
    86  
    87  		r := Run{Bundle: b, Action: "missing"}
    88  		assert.True(t, r.ShouldRecord())
    89  	})
    90  
    91  	t.Run("has user defined output", func(t *testing.T) {
    92  		b := bundle.Bundle{
    93  			Actions: map[string]bundle.Action{
    94  				"editstuff": {
    95  					Modifies:  false,
    96  					Stateless: true,
    97  				},
    98  			},
    99  			Outputs: map[string]bundle.Output{
   100  				"testdata": {
   101  					ApplyTo: []string{"editstuff"},
   102  				},
   103  			},
   104  		}
   105  
   106  		r := Run{Bundle: b, Action: "editstuff"}
   107  		assert.True(t, r.ShouldRecord())
   108  	})
   109  
   110  	t.Run("has only internal bundle level output", func(t *testing.T) {
   111  		b := bundle.Bundle{
   112  			Definitions: definition.Definitions{
   113  				"porter-state": &definition.Schema{
   114  					Type:            "string",
   115  					ContentEncoding: "base64",
   116  					Comment:         cnab.PorterInternal,
   117  				},
   118  			},
   119  			Actions: map[string]bundle.Action{
   120  				"editstuff": {
   121  					Modifies:  false,
   122  					Stateless: true,
   123  				},
   124  			},
   125  			Outputs: map[string]bundle.Output{
   126  				"porter-state": {Definition: "porter-state"},
   127  			},
   128  		}
   129  
   130  		r := Run{Bundle: b, Action: "editstuff"}
   131  		assert.False(t, r.ShouldRecord())
   132  	})
   133  
   134  }
   135  
   136  func TestRun_TypedParameterValues(t *testing.T) {
   137  	sensitive := true
   138  	bun := bundle.Bundle{
   139  		Definitions: definition.Definitions{
   140  			"foo": &definition.Schema{
   141  				Type:      "integer",
   142  				WriteOnly: &sensitive,
   143  			},
   144  			"baz": &definition.Schema{
   145  				Type: "string",
   146  			},
   147  			"porter-state": &definition.Schema{
   148  				Type:            "string",
   149  				ContentEncoding: "base64",
   150  				Comment:         cnab.PorterInternal,
   151  			},
   152  		},
   153  		Parameters: map[string]bundle.Parameter{
   154  			"foo": {
   155  				Definition: "foo",
   156  			},
   157  			"baz": {
   158  				Definition: "baz",
   159  			},
   160  			"name": {
   161  				Definition: "name",
   162  			},
   163  			"porter-state": {
   164  				Definition: "porter-state",
   165  			},
   166  		},
   167  		RequiredExtensions: []string{
   168  			cnab.FileParameterExtensionKey,
   169  		},
   170  	}
   171  
   172  	run := NewRun("dev", "mybuns")
   173  	run.Bundle = bun
   174  	run.Parameters = NewParameterSet(run.Namespace, run.Bundle.Name,
   175  		ValueStrategy("baz", "baz-test"),
   176  		ValueStrategy("name", "porter-test"),
   177  		ValueStrategy("porter-state", ""),
   178  		secrets.SourceMap{Name: "foo", Source: secrets.Source{Strategy: secrets.SourceSecret, Hint: "runID"}, ResolvedValue: "5"})
   179  
   180  	expected := map[string]interface{}{
   181  		"baz":          "baz-test",
   182  		"name":         "porter-test",
   183  		"porter-state": nil,
   184  		"foo":          5,
   185  	}
   186  
   187  	typed := run.TypedParameterValues()
   188  	require.Equal(t, len(run.Parameters.Parameters), len(typed))
   189  	require.Equal(t, len(expected), len(typed))
   190  
   191  	for name, value := range typed {
   192  		v, ok := expected[name]
   193  		require.True(t, ok)
   194  		require.Equal(t, v, value)
   195  	}
   196  }
   197  
   198  func TestRun_MarshalJSON(t *testing.T) {
   199  	// Verify that when a run is marshaled that the bundle field is saved as an escaped json string
   200  	r1 := Run{ID: "foo", Bundle: exampleBundle}
   201  
   202  	data, err := json.Marshal(r1)
   203  	require.NoError(t, err, "Marshal failed")
   204  
   205  	test.CompareGoldenFile(t, "testdata/marshaled_run.json", string(data))
   206  
   207  	var r2 Run
   208  	err = json.Unmarshal(data, &r2)
   209  	require.NoError(t, err, "Unmarshal failed")
   210  
   211  	assert.Equal(t, r1, r2, "The run did not survive the round trip")
   212  }