github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/helper/schema/provisioner_test.go (about) 1 package schema 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/hashicorp/terraform/config" 10 "github.com/hashicorp/terraform/terraform" 11 ) 12 13 func TestProvisioner_impl(t *testing.T) { 14 var _ terraform.ResourceProvisioner = new(Provisioner) 15 } 16 17 func TestProvisionerValidate(t *testing.T) { 18 cases := []struct { 19 Name string 20 P *Provisioner 21 Config map[string]interface{} 22 Err bool 23 }{ 24 { 25 "Basic required field", 26 &Provisioner{ 27 Schema: map[string]*Schema{ 28 "foo": &Schema{ 29 Required: true, 30 Type: TypeString, 31 }, 32 }, 33 }, 34 nil, 35 true, 36 }, 37 38 { 39 "Basic required field set", 40 &Provisioner{ 41 Schema: map[string]*Schema{ 42 "foo": &Schema{ 43 Required: true, 44 Type: TypeString, 45 }, 46 }, 47 }, 48 map[string]interface{}{ 49 "foo": "bar", 50 }, 51 false, 52 }, 53 } 54 55 for i, tc := range cases { 56 t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { 57 c, err := config.NewRawConfig(tc.Config) 58 if err != nil { 59 t.Fatalf("err: %s", err) 60 } 61 62 _, es := tc.P.Validate(terraform.NewResourceConfig(c)) 63 if len(es) > 0 != tc.Err { 64 t.Fatalf("%d: %#v", i, es) 65 } 66 }) 67 } 68 } 69 70 func TestProvisionerApply(t *testing.T) { 71 cases := []struct { 72 Name string 73 P *Provisioner 74 Conn map[string]string 75 Config map[string]interface{} 76 Err bool 77 }{ 78 { 79 "Basic config", 80 &Provisioner{ 81 ConnSchema: map[string]*Schema{ 82 "foo": &Schema{ 83 Type: TypeString, 84 Optional: true, 85 }, 86 }, 87 88 Schema: map[string]*Schema{ 89 "foo": &Schema{ 90 Type: TypeInt, 91 Optional: true, 92 }, 93 }, 94 95 ApplyFunc: func(ctx context.Context) error { 96 cd := ctx.Value(ProvConnDataKey).(*ResourceData) 97 d := ctx.Value(ProvConfigDataKey).(*ResourceData) 98 if d.Get("foo").(int) != 42 { 99 return fmt.Errorf("bad config data") 100 } 101 if cd.Get("foo").(string) != "bar" { 102 return fmt.Errorf("bad conn data") 103 } 104 105 return nil 106 }, 107 }, 108 map[string]string{ 109 "foo": "bar", 110 }, 111 map[string]interface{}{ 112 "foo": 42, 113 }, 114 false, 115 }, 116 } 117 118 for i, tc := range cases { 119 t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { 120 c, err := config.NewRawConfig(tc.Config) 121 if err != nil { 122 t.Fatalf("err: %s", err) 123 } 124 125 state := &terraform.InstanceState{ 126 Ephemeral: terraform.EphemeralState{ 127 ConnInfo: tc.Conn, 128 }, 129 } 130 131 err = tc.P.Apply( 132 nil, state, terraform.NewResourceConfig(c)) 133 if err != nil != tc.Err { 134 t.Fatalf("%d: %s", i, err) 135 } 136 }) 137 } 138 } 139 140 func TestProvisionerApply_nilState(t *testing.T) { 141 p := &Provisioner{ 142 ConnSchema: map[string]*Schema{ 143 "foo": &Schema{ 144 Type: TypeString, 145 Optional: true, 146 }, 147 }, 148 149 Schema: map[string]*Schema{ 150 "foo": &Schema{ 151 Type: TypeInt, 152 Optional: true, 153 }, 154 }, 155 156 ApplyFunc: func(ctx context.Context) error { 157 return nil 158 }, 159 } 160 161 conf := map[string]interface{}{ 162 "foo": 42, 163 } 164 165 c, err := config.NewRawConfig(conf) 166 if err != nil { 167 t.Fatalf("err: %s", err) 168 } 169 170 err = p.Apply(nil, nil, terraform.NewResourceConfig(c)) 171 if err != nil { 172 t.Fatalf("err: %s", err) 173 } 174 } 175 176 func TestProvisionerStop(t *testing.T) { 177 var p Provisioner 178 179 // Verify stopch blocks 180 ch := p.StopContext().Done() 181 select { 182 case <-ch: 183 t.Fatal("should not be stopped") 184 case <-time.After(10 * time.Millisecond): 185 } 186 187 // Stop it 188 if err := p.Stop(); err != nil { 189 t.Fatalf("err: %s", err) 190 } 191 192 select { 193 case <-ch: 194 case <-time.After(10 * time.Millisecond): 195 t.Fatal("should be stopped") 196 } 197 } 198 199 func TestProvisionerStop_apply(t *testing.T) { 200 p := &Provisioner{ 201 ConnSchema: map[string]*Schema{ 202 "foo": &Schema{ 203 Type: TypeString, 204 Optional: true, 205 }, 206 }, 207 208 Schema: map[string]*Schema{ 209 "foo": &Schema{ 210 Type: TypeInt, 211 Optional: true, 212 }, 213 }, 214 215 ApplyFunc: func(ctx context.Context) error { 216 <-ctx.Done() 217 return nil 218 }, 219 } 220 221 conn := map[string]string{ 222 "foo": "bar", 223 } 224 225 conf := map[string]interface{}{ 226 "foo": 42, 227 } 228 229 c, err := config.NewRawConfig(conf) 230 if err != nil { 231 t.Fatalf("err: %s", err) 232 } 233 234 state := &terraform.InstanceState{ 235 Ephemeral: terraform.EphemeralState{ 236 ConnInfo: conn, 237 }, 238 } 239 240 // Run the apply in a goroutine 241 doneCh := make(chan struct{}) 242 go func() { 243 p.Apply(nil, state, terraform.NewResourceConfig(c)) 244 close(doneCh) 245 }() 246 247 // Should block 248 select { 249 case <-doneCh: 250 t.Fatal("should not be done") 251 case <-time.After(10 * time.Millisecond): 252 } 253 254 // Stop! 255 p.Stop() 256 257 select { 258 case <-doneCh: 259 case <-time.After(10 * time.Millisecond): 260 t.Fatal("should be done") 261 } 262 } 263 264 func TestProvisionerStop_stopFirst(t *testing.T) { 265 var p Provisioner 266 267 // Stop it 268 if err := p.Stop(); err != nil { 269 t.Fatalf("err: %s", err) 270 } 271 272 select { 273 case <-p.StopContext().Done(): 274 case <-time.After(10 * time.Millisecond): 275 t.Fatal("should be stopped") 276 } 277 }