github.com/jdolitsky/cnab-go@v0.7.1-beta1/action/run_custom_test.go (about) 1 package action 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "testing" 7 8 "github.com/deislabs/cnab-go/bundle" 9 "github.com/deislabs/cnab-go/claim" 10 "github.com/deislabs/cnab-go/driver" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 // makes sure RunCustom implements Action interface 16 var _ Action = &RunCustom{} 17 18 func TestRunCustom(t *testing.T) { 19 out := func(op *driver.Operation) error { 20 op.Out = ioutil.Discard 21 return nil 22 } 23 24 rc := &RunCustom{ 25 Driver: &mockDriver{ 26 shouldHandle: true, 27 Result: driver.OperationResult{ 28 Outputs: map[string]string{ 29 "/tmp/some/path": "SOME CONTENT", 30 }, 31 }, 32 Error: nil, 33 }, 34 Action: "test", 35 } 36 37 t.Run("happy-path", func(t *testing.T) { 38 c := newClaim() 39 err := rc.Run(c, mockSet, out) 40 assert.NoError(t, err) 41 assert.Equal(t, claim.StatusSuccess, c.Result.Status) 42 assert.Equal(t, "test", c.Result.Action) 43 assert.Equal(t, map[string]interface{}{"some-output": "SOME CONTENT"}, c.Outputs) 44 }) 45 46 t.Run("configure operation", func(t *testing.T) { 47 c := newClaim() 48 d := &mockDriver{ 49 shouldHandle: true, 50 Result: driver.OperationResult{ 51 Outputs: map[string]string{ 52 "/tmp/some/path": "SOME CONTENT", 53 }, 54 }, 55 Error: nil, 56 } 57 inst := &RunCustom{Driver: d, Action: "test"} 58 addFile := func(op *driver.Operation) error { 59 op.Files["/tmp/another/path"] = "ANOTHER FILE" 60 return nil 61 } 62 require.NoError(t, inst.Run(c, mockSet, out, addFile)) 63 assert.Contains(t, d.Operation.Files, "/tmp/another/path") 64 }) 65 66 t.Run("error case: configure operation", func(t *testing.T) { 67 c := newClaim() 68 d := &mockDriver{ 69 shouldHandle: true, 70 Result: driver.OperationResult{ 71 Outputs: map[string]string{ 72 "/tmp/some/path": "SOME CONTENT", 73 }, 74 }, 75 Error: nil, 76 } 77 inst := &RunCustom{Driver: d, Action: "test"} 78 sabotage := func(op *driver.Operation) error { 79 return errors.New("oops") 80 } 81 require.EqualError(t, inst.Run(c, mockSet, out, sabotage), "oops") 82 }) 83 84 t.Run("when there are no outputs in the bundle", func(t *testing.T) { 85 c := newClaim() 86 c.Bundle.Outputs = nil 87 rc.Driver = &mockDriver{ 88 shouldHandle: true, 89 Result: driver.OperationResult{}, 90 Error: nil, 91 } 92 err := rc.Run(c, mockSet, out) 93 assert.NoError(t, err) 94 assert.NotEqual(t, c.Created, c.Modified, "Claim was not updated with modified timestamp after custom action") 95 assert.Equal(t, claim.StatusSuccess, c.Result.Status) 96 assert.Equal(t, "test", c.Result.Action) 97 assert.Empty(t, c.Outputs) 98 }) 99 100 t.Run("error case: driver doesn't handle image", func(t *testing.T) { 101 c := newClaim() 102 rc.Driver = &mockDriver{ 103 Error: errors.New("I always fail"), 104 shouldHandle: false, 105 } 106 err := rc.Run(c, mockSet, out) 107 assert.Error(t, err) 108 assert.Empty(t, c.Outputs) 109 }) 110 111 t.Run("error case: driver returns error", func(t *testing.T) { 112 c := newClaim() 113 rc.Driver = &mockDriver{ 114 Result: driver.OperationResult{ 115 Outputs: map[string]string{ 116 "/tmp/some/path": "SOME CONTENT", 117 }, 118 }, 119 Error: errors.New("I always fail"), 120 shouldHandle: true, 121 } 122 err := rc.Run(c, mockSet, out) 123 assert.Error(t, err) 124 assert.NotEqual(t, "", c.Result.Message, "Expected error message in claim result message") 125 assert.Equal(t, "test", c.Result.Action) 126 assert.Equal(t, claim.StatusFailure, c.Result.Status) 127 assert.Equal(t, map[string]interface{}{"some-output": "SOME CONTENT"}, c.Outputs) 128 }) 129 130 t.Run("error case: driver returns an error but the action does not modify", func(t *testing.T) { 131 c := newClaim() 132 action := c.Bundle.Actions["test"] 133 action.Modifies = false 134 c.Bundle.Actions["test"] = action 135 136 rc.Driver = &mockDriver{ 137 Result: driver.OperationResult{ 138 Outputs: map[string]string{ 139 "/tmp/some/path": "SOME CONTENT", 140 }, 141 }, 142 Error: errors.New("I always fail"), 143 shouldHandle: true, 144 } 145 err := rc.Run(c, mockSet, out) 146 assert.Error(t, err) 147 assert.Empty(t, c.Result, "Expected claim results not to be tracked when the action does not modify") 148 assert.Empty(t, c.Outputs, "Expected output results not to be tracked with the action does not modify") 149 }) 150 151 t.Run("error case: forbidden custom actions should fail", func(t *testing.T) { 152 c := newClaim() 153 rc.Action = "install" 154 err := rc.Run(c, mockSet, out) 155 assert.Error(t, err) 156 assert.Empty(t, c.Outputs) 157 }) 158 159 t.Run("error case: unknown actions should fail", func(t *testing.T) { 160 c := newClaim() 161 rc.Action = "test" 162 c.Bundle.Actions = map[string]bundle.Action{} 163 err := rc.Run(c, mockSet, out) 164 assert.Error(t, err, "Unknown action should fail") 165 assert.Empty(t, c.Outputs) 166 }) 167 }