github.com/handlerbot/terraform@v0.10.0-beta1.0.20180726153736-26b68d98f9cb/builtin/provisioners/remote-exec/resource_provisioner_test.go (about) 1 package remoteexec 2 3 import ( 4 "bytes" 5 "context" 6 "io" 7 "testing" 8 "time" 9 10 "strings" 11 12 "github.com/hashicorp/terraform/communicator" 13 "github.com/hashicorp/terraform/communicator/remote" 14 "github.com/hashicorp/terraform/config" 15 "github.com/hashicorp/terraform/helper/schema" 16 "github.com/hashicorp/terraform/terraform" 17 ) 18 19 func TestResourceProvisioner_impl(t *testing.T) { 20 var _ terraform.ResourceProvisioner = Provisioner() 21 } 22 23 func TestProvisioner(t *testing.T) { 24 if err := Provisioner().(*schema.Provisioner).InternalValidate(); err != nil { 25 t.Fatalf("err: %s", err) 26 } 27 } 28 29 func TestResourceProvider_Validate_good(t *testing.T) { 30 c := testConfig(t, map[string]interface{}{ 31 "inline": "echo foo", 32 }) 33 34 warn, errs := Provisioner().Validate(c) 35 if len(warn) > 0 { 36 t.Fatalf("Warnings: %v", warn) 37 } 38 if len(errs) > 0 { 39 t.Fatalf("Errors: %v", errs) 40 } 41 } 42 43 func TestResourceProvider_Validate_bad(t *testing.T) { 44 c := testConfig(t, map[string]interface{}{ 45 "invalid": "nope", 46 }) 47 48 warn, errs := Provisioner().Validate(c) 49 if len(warn) > 0 { 50 t.Fatalf("Warnings: %v", warn) 51 } 52 if len(errs) == 0 { 53 t.Fatalf("Should have errors") 54 } 55 } 56 57 var expectedScriptOut = `cd /tmp 58 wget http://foobar 59 exit 0 60 ` 61 62 func TestResourceProvider_generateScript(t *testing.T) { 63 conf := map[string]interface{}{ 64 "inline": []interface{}{ 65 "cd /tmp", 66 "wget http://foobar", 67 "exit 0", 68 }, 69 } 70 71 out, err := generateScripts( 72 schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf), 73 ) 74 if err != nil { 75 t.Fatalf("err: %v", err) 76 } 77 78 if len(out) != 1 { 79 t.Fatal("expected 1 out") 80 } 81 82 if out[0] != expectedScriptOut { 83 t.Fatalf("bad: %v", out) 84 } 85 } 86 87 func TestResourceProvider_generateScriptEmptyInline(t *testing.T) { 88 p := Provisioner().(*schema.Provisioner) 89 conf := map[string]interface{}{ 90 "inline": []interface{}{""}, 91 } 92 93 _, err := generateScripts(schema.TestResourceDataRaw( 94 t, p.Schema, conf)) 95 if err == nil { 96 t.Fatal("expected error, got none") 97 } 98 99 if !strings.Contains(err.Error(), "Error parsing") { 100 t.Fatalf("expected parsing error, got: %s", err) 101 } 102 } 103 104 func TestResourceProvider_CollectScripts_inline(t *testing.T) { 105 conf := map[string]interface{}{ 106 "inline": []interface{}{ 107 "cd /tmp", 108 "wget http://foobar", 109 "exit 0", 110 }, 111 } 112 113 scripts, err := collectScripts( 114 schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf), 115 ) 116 if err != nil { 117 t.Fatalf("err: %v", err) 118 } 119 120 if len(scripts) != 1 { 121 t.Fatalf("bad: %v", scripts) 122 } 123 124 var out bytes.Buffer 125 _, err = io.Copy(&out, scripts[0]) 126 if err != nil { 127 t.Fatalf("err: %v", err) 128 } 129 130 if out.String() != expectedScriptOut { 131 t.Fatalf("bad: %v", out.String()) 132 } 133 } 134 135 func TestResourceProvider_CollectScripts_script(t *testing.T) { 136 conf := map[string]interface{}{ 137 "script": "test-fixtures/script1.sh", 138 } 139 140 scripts, err := collectScripts( 141 schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf), 142 ) 143 if err != nil { 144 t.Fatalf("err: %v", err) 145 } 146 147 if len(scripts) != 1 { 148 t.Fatalf("bad: %v", scripts) 149 } 150 151 var out bytes.Buffer 152 _, err = io.Copy(&out, scripts[0]) 153 if err != nil { 154 t.Fatalf("err: %v", err) 155 } 156 157 if out.String() != expectedScriptOut { 158 t.Fatalf("bad: %v", out.String()) 159 } 160 } 161 162 func TestResourceProvider_CollectScripts_scripts(t *testing.T) { 163 conf := map[string]interface{}{ 164 "scripts": []interface{}{ 165 "test-fixtures/script1.sh", 166 "test-fixtures/script1.sh", 167 "test-fixtures/script1.sh", 168 }, 169 } 170 171 scripts, err := collectScripts( 172 schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf), 173 ) 174 if err != nil { 175 t.Fatalf("err: %v", err) 176 } 177 178 if len(scripts) != 3 { 179 t.Fatalf("bad: %v", scripts) 180 } 181 182 for idx := range scripts { 183 var out bytes.Buffer 184 _, err = io.Copy(&out, scripts[idx]) 185 if err != nil { 186 t.Fatalf("err: %v", err) 187 } 188 189 if out.String() != expectedScriptOut { 190 t.Fatalf("bad: %v", out.String()) 191 } 192 } 193 } 194 195 func TestResourceProvider_CollectScripts_scriptsEmpty(t *testing.T) { 196 p := Provisioner().(*schema.Provisioner) 197 conf := map[string]interface{}{ 198 "scripts": []interface{}{""}, 199 } 200 201 _, err := collectScripts(schema.TestResourceDataRaw( 202 t, p.Schema, conf)) 203 204 if err == nil { 205 t.Fatal("expected error") 206 } 207 208 if !strings.Contains(err.Error(), "Error parsing") { 209 t.Fatalf("Expected parsing error, got: %s", err) 210 } 211 } 212 213 func TestProvisionerTimeout(t *testing.T) { 214 o := new(terraform.MockUIOutput) 215 c := new(communicator.MockCommunicator) 216 217 disconnected := make(chan struct{}) 218 c.DisconnectFunc = func() error { 219 close(disconnected) 220 return nil 221 } 222 223 completed := make(chan struct{}) 224 c.CommandFunc = func(cmd *remote.Cmd) error { 225 defer close(completed) 226 cmd.Init() 227 time.Sleep(2 * time.Second) 228 cmd.SetExitStatus(0, nil) 229 return nil 230 } 231 c.ConnTimeout = time.Second 232 c.UploadScripts = map[string]string{"hello": "echo hello"} 233 c.RemoteScriptPath = "hello" 234 235 p := Provisioner().(*schema.Provisioner) 236 conf := map[string]interface{}{ 237 "inline": []interface{}{"echo hello"}, 238 } 239 240 scripts, err := collectScripts(schema.TestResourceDataRaw( 241 t, p.Schema, conf)) 242 if err != nil { 243 t.Fatal(err) 244 } 245 246 ctx := context.Background() 247 248 done := make(chan struct{}) 249 250 go func() { 251 defer close(done) 252 if err := runScripts(ctx, o, c, scripts); err != nil { 253 t.Fatal(err) 254 } 255 }() 256 257 select { 258 case <-disconnected: 259 t.Fatal("communicator disconnected before command completed") 260 case <-completed: 261 } 262 263 <-done 264 } 265 266 func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig { 267 r, err := config.NewRawConfig(c) 268 if err != nil { 269 t.Fatalf("bad: %s", err) 270 } 271 272 return terraform.NewResourceConfig(r) 273 }