Jon Perritt | a065da1 | 2015-02-06 10:20:16 -0700 | [diff] [blame] | 1 | package stackresources |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "net/http" |
| 6 | "testing" |
| 7 | "time" |
| 8 | |
| 9 | "github.com/rackspace/gophercloud" |
| 10 | th "github.com/rackspace/gophercloud/testhelper" |
| 11 | fake "github.com/rackspace/gophercloud/testhelper/client" |
| 12 | ) |
| 13 | |
| 14 | var FindExpected = []Resource{ |
| 15 | Resource{ |
| 16 | Name: "hello_world", |
| 17 | Links: []gophercloud.Link{ |
| 18 | gophercloud.Link{ |
| 19 | Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", |
| 20 | Rel: "self", |
| 21 | }, |
| 22 | gophercloud.Link{ |
| 23 | Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", |
| 24 | Rel: "stack", |
| 25 | }, |
| 26 | }, |
| 27 | LogicalID: "hello_world", |
| 28 | StatusReason: "state changed", |
| 29 | UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), |
| 30 | RequiredBy: []interface{}{}, |
| 31 | Status: "CREATE_IN_PROGRESS", |
| 32 | PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf", |
| 33 | Type: "OS::Nova::Server", |
| 34 | }, |
| 35 | } |
| 36 | |
| 37 | const FindOutput = ` |
| 38 | { |
| 39 | "resources": [ |
| 40 | { |
| 41 | "resource_name": "hello_world", |
| 42 | "links": [ |
| 43 | { |
| 44 | "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", |
| 45 | "rel": "self" |
| 46 | }, |
| 47 | { |
| 48 | "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", |
| 49 | "rel": "stack" |
| 50 | } |
| 51 | ], |
| 52 | "logical_resource_id": "hello_world", |
| 53 | "resource_status_reason": "state changed", |
| 54 | "updated_time": "2015-02-05T21:33:11Z", |
| 55 | "required_by": [], |
| 56 | "resource_status": "CREATE_IN_PROGRESS", |
| 57 | "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", |
| 58 | "resource_type": "OS::Nova::Server" |
| 59 | } |
| 60 | ] |
| 61 | }` |
| 62 | |
| 63 | // HandleFindSuccessfully creates an HTTP handler at `/stacks/hello_world/resources` |
| 64 | // on the test handler mux that responds with a `Find` response. |
| 65 | func HandleFindSuccessfully(t *testing.T, output string) { |
| 66 | th.Mux.HandleFunc("/stacks/hello_world/resources", func(w http.ResponseWriter, r *http.Request) { |
| 67 | th.TestMethod(t, r, "GET") |
| 68 | th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) |
| 69 | th.TestHeader(t, r, "Accept", "application/json") |
| 70 | |
| 71 | w.Header().Set("Content-Type", "application/json") |
| 72 | w.WriteHeader(http.StatusOK) |
| 73 | fmt.Fprintf(w, output) |
| 74 | }) |
| 75 | } |
| 76 | |
| 77 | var ListExpected = []Resource{ |
| 78 | Resource{ |
| 79 | Name: "hello_world", |
| 80 | Links: []gophercloud.Link{ |
| 81 | gophercloud.Link{ |
| 82 | Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", |
| 83 | Rel: "self", |
| 84 | }, |
| 85 | gophercloud.Link{ |
| 86 | Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", |
| 87 | Rel: "stack", |
| 88 | }, |
| 89 | }, |
| 90 | LogicalID: "hello_world", |
| 91 | StatusReason: "state changed", |
| 92 | UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC), |
| 93 | RequiredBy: []interface{}{}, |
| 94 | Status: "CREATE_IN_PROGRESS", |
| 95 | PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf", |
| 96 | Type: "OS::Nova::Server", |
| 97 | }, |
| 98 | } |
| 99 | |
| 100 | const ListOutput = `{ |
| 101 | "resources": [ |
| 102 | { |
| 103 | "resource_name": "hello_world", |
| 104 | "links": [ |
| 105 | { |
| 106 | "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world", |
| 107 | "rel": "self" |
| 108 | }, |
| 109 | { |
| 110 | "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b", |
| 111 | "rel": "stack" |
| 112 | } |
| 113 | ], |
| 114 | "logical_resource_id": "hello_world", |
| 115 | "resource_status_reason": "state changed", |
| 116 | "updated_time": "2015-02-05T21:33:11Z", |
| 117 | "required_by": [], |
| 118 | "resource_status": "CREATE_IN_PROGRESS", |
| 119 | "physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf", |
| 120 | "resource_type": "OS::Nova::Server" |
| 121 | } |
| 122 | ] |
| 123 | }` |
| 124 | |
| 125 | // HandleListSuccessfully creates an HTTP handler at `/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources` |
| 126 | // on the test handler mux that responds with a `List` response. |
| 127 | func HandleListSuccessfully(t *testing.T, output string) { |
| 128 | th.Mux.HandleFunc("/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/resources", func(w http.ResponseWriter, r *http.Request) { |
| 129 | th.TestMethod(t, r, "GET") |
| 130 | th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) |
| 131 | th.TestHeader(t, r, "Accept", "application/json") |
| 132 | |
| 133 | w.Header().Set("Content-Type", "application/json") |
| 134 | r.ParseForm() |
| 135 | marker := r.Form.Get("marker") |
| 136 | switch marker { |
| 137 | case "": |
| 138 | fmt.Fprintf(w, output) |
| 139 | default: |
| 140 | t.Fatalf("Unexpected marker: [%s]", marker) |
| 141 | } |
| 142 | }) |
| 143 | } |
| 144 | |
| 145 | var GetExpected = &Resource{ |
| 146 | Name: "wordpress_instance", |
| 147 | Links: []gophercloud.Link{ |
| 148 | gophercloud.Link{ |
| 149 | Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance", |
| 150 | Rel: "self", |
| 151 | }, |
| 152 | gophercloud.Link{ |
| 153 | Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e", |
| 154 | Rel: "stack", |
| 155 | }, |
| 156 | }, |
| 157 | LogicalID: "wordpress_instance", |
| 158 | StatusReason: "state changed", |
| 159 | UpdatedTime: time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC), |
| 160 | RequiredBy: []interface{}{}, |
| 161 | Status: "CREATE_COMPLETE", |
| 162 | PhysicalID: "00e3a2fe-c65d-403c-9483-4db9930dd194", |
| 163 | Type: "OS::Nova::Server", |
| 164 | } |
| 165 | |
| 166 | const GetOutput = ` |
| 167 | { |
| 168 | "resource": { |
| 169 | "resource_name": "wordpress_instance", |
| 170 | "description": "", |
| 171 | "links": [ |
| 172 | { |
| 173 | "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance", |
| 174 | "rel": "self" |
| 175 | }, |
| 176 | { |
| 177 | "href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e", |
| 178 | "rel": "stack" |
| 179 | } |
| 180 | ], |
| 181 | "logical_resource_id": "wordpress_instance", |
| 182 | "resource_status": "CREATE_COMPLETE", |
| 183 | "updated_time": "2014-12-10T18:34:35Z", |
| 184 | "required_by": [], |
| 185 | "resource_status_reason": "state changed", |
| 186 | "physical_resource_id": "00e3a2fe-c65d-403c-9483-4db9930dd194", |
| 187 | "resource_type": "OS::Nova::Server" |
| 188 | } |
| 189 | }` |
| 190 | |
| 191 | // HandleGetSuccessfully creates an HTTP handler at `/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance` |
| 192 | // on the test handler mux that responds with a `Get` response. |
| 193 | func HandleGetSuccessfully(t *testing.T, output string) { |
| 194 | th.Mux.HandleFunc("/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance", func(w http.ResponseWriter, r *http.Request) { |
| 195 | th.TestMethod(t, r, "GET") |
| 196 | th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) |
| 197 | th.TestHeader(t, r, "Accept", "application/json") |
| 198 | |
| 199 | w.Header().Set("Content-Type", "application/json") |
| 200 | w.WriteHeader(http.StatusOK) |
| 201 | fmt.Fprintf(w, output) |
| 202 | }) |
| 203 | } |
| 204 | |
| 205 | var MetadataExpected = map[string]string{ |
| 206 | "number": "7", |
| 207 | "animal": "auk", |
| 208 | } |
| 209 | |
| 210 | const MetadataOutput = ` |
| 211 | { |
| 212 | "metadata": { |
| 213 | "number": "7", |
| 214 | "animal": "auk" |
| 215 | } |
| 216 | }` |
| 217 | |
| 218 | // HandleMetadataSuccessfully creates an HTTP handler at `/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance/metadata` |
| 219 | // on the test handler mux that responds with a `Metadata` response. |
| 220 | func HandleMetadataSuccessfully(t *testing.T, output string) { |
| 221 | th.Mux.HandleFunc("/stacks/teststack/0b1771bd-9336-4f2b-ae86-a80f971faf1e/resources/wordpress_instance/metadata", func(w http.ResponseWriter, r *http.Request) { |
| 222 | th.TestMethod(t, r, "GET") |
| 223 | th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) |
| 224 | th.TestHeader(t, r, "Accept", "application/json") |
| 225 | |
| 226 | w.Header().Set("Content-Type", "application/json") |
| 227 | w.WriteHeader(http.StatusOK) |
| 228 | fmt.Fprintf(w, output) |
| 229 | }) |
| 230 | } |
| 231 | |
| 232 | var ListTypesExpected = []string{ |
| 233 | "OS::Nova::Server", |
| 234 | "OS::Heat::RandomString", |
| 235 | "OS::Swift::Container", |
| 236 | "OS::Trove::Instance", |
| 237 | "OS::Nova::FloatingIPAssociation", |
| 238 | "OS::Cinder::VolumeAttachment", |
| 239 | "OS::Nova::FloatingIP", |
| 240 | "OS::Nova::KeyPair", |
| 241 | } |
| 242 | |
| 243 | const ListTypesOutput = ` |
| 244 | { |
| 245 | "resource_types": [ |
| 246 | "OS::Nova::Server", |
| 247 | "OS::Heat::RandomString", |
| 248 | "OS::Swift::Container", |
| 249 | "OS::Trove::Instance", |
| 250 | "OS::Nova::FloatingIPAssociation", |
| 251 | "OS::Cinder::VolumeAttachment", |
| 252 | "OS::Nova::FloatingIP", |
| 253 | "OS::Nova::KeyPair" |
| 254 | ] |
| 255 | }` |
| 256 | |
| 257 | // HandleListTypesSuccessfully creates an HTTP handler at `/resource_types` |
| 258 | // on the test handler mux that responds with a `ListTypes` response. |
| 259 | func HandleListTypesSuccessfully(t *testing.T, output string) { |
| 260 | th.Mux.HandleFunc("/resource_types", func(w http.ResponseWriter, r *http.Request) { |
| 261 | th.TestMethod(t, r, "GET") |
| 262 | th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) |
| 263 | th.TestHeader(t, r, "Accept", "application/json") |
| 264 | |
| 265 | w.Header().Set("Content-Type", "application/json") |
| 266 | w.WriteHeader(http.StatusOK) |
| 267 | fmt.Fprintf(w, output) |
| 268 | }) |
| 269 | } |
Jon Perritt | 1d4aca0 | 2015-02-06 12:29:16 -0700 | [diff] [blame^] | 270 | |
| 271 | var GetSchemaExpected = &TypeSchema{ |
| 272 | Attributes: map[string]interface{}{ |
| 273 | "an_attribute": map[string]interface{}{ |
| 274 | "description": "An attribute description .", |
| 275 | }, |
| 276 | }, |
| 277 | Properties: map[string]interface{}{ |
| 278 | "a_property": map[string]interface{}{ |
| 279 | "update_allowed": false, |
| 280 | "required": true, |
| 281 | "type": "string", |
| 282 | "description": "A resource description.", |
| 283 | }, |
| 284 | }, |
| 285 | ResourceType: "OS::Heat::AResourceName", |
| 286 | } |
| 287 | |
| 288 | const GetSchemaOutput = ` |
| 289 | { |
| 290 | "attributes": { |
| 291 | "an_attribute": { |
| 292 | "description": "An attribute description ." |
| 293 | } |
| 294 | }, |
| 295 | "properties": { |
| 296 | "a_property": { |
| 297 | "update_allowed": false, |
| 298 | "required": true, |
| 299 | "type": "string", |
| 300 | "description": "A resource description." |
| 301 | } |
| 302 | }, |
| 303 | "resource_type": "OS::Heat::AResourceName" |
| 304 | }` |
| 305 | |
| 306 | // HandleGetSchemaSuccessfully creates an HTTP handler at `/resource_types/OS::Heat::AResourceName` |
| 307 | // on the test handler mux that responds with a `Schema` response. |
| 308 | func HandleGetSchemaSuccessfully(t *testing.T, output string) { |
| 309 | th.Mux.HandleFunc("/resource_types/OS::Heat::AResourceName", func(w http.ResponseWriter, r *http.Request) { |
| 310 | th.TestMethod(t, r, "GET") |
| 311 | th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) |
| 312 | th.TestHeader(t, r, "Accept", "application/json") |
| 313 | |
| 314 | w.Header().Set("Content-Type", "application/json") |
| 315 | w.WriteHeader(http.StatusOK) |
| 316 | fmt.Fprintf(w, output) |
| 317 | }) |
| 318 | } |
| 319 | |
| 320 | const GetTemplateOutput = ` |
| 321 | { |
| 322 | "Outputs": { |
| 323 | "addresses": { |
| 324 | "Description": "A dict of all network addresses with correspondingport_id.", |
| 325 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"addresses\"]}" |
| 326 | }, |
| 327 | "first_address": { |
| 328 | "Description": "Convenience attribute to fetch the first assigned network address, or an empty string if nothing has been assigned at this time. Result may not be predictable if the server has addresses from more than one network.", |
| 329 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"first_address\"]}" |
| 330 | }, |
| 331 | "show": { |
| 332 | "Description": "A dict of all server details as returned by the API.", |
| 333 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"show\"]}" |
| 334 | }, |
| 335 | "instance_name": { |
| 336 | "Description": "AWS compatible instance name.", |
| 337 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"instance_name\"]}" |
| 338 | }, |
| 339 | "accessIPv4": { |
| 340 | "Description": "The manually assigned alternative public IPv4 address of the server.", |
| 341 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"accessIPv4\"]}" |
| 342 | }, |
| 343 | "accessIPv6": { |
| 344 | "Description": "The manually assigned alternative public IPv6 address of the server.", |
| 345 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"accessIPv6\"]}" |
| 346 | }, |
| 347 | "networks": { |
| 348 | "Description": "A dict of assigned network addresses of the form: {\"public\": [ip1, ip2...], \"private\": [ip3, ip4]}.", |
| 349 | "Value": "{\"Fn::GetAtt\": [\"Server\", \"networks\"]}" |
| 350 | } |
| 351 | }, |
| 352 | "HeatTemplateFormatVersion": "2012-12-12", |
| 353 | "Parameters": { |
| 354 | "scheduler_hints": { |
| 355 | "Type": "Json", |
| 356 | "Description": "Arbitrary key-value pairs specified by the client to help boot a server." |
| 357 | }, |
| 358 | "admin_pass": { |
| 359 | "Type": "String", |
| 360 | "Description": "The administrator password for the server." |
| 361 | }, |
| 362 | "user_data_format": { |
| 363 | "Default": "HEAT_CFNTOOLS", |
| 364 | "Type": "String", |
| 365 | "Description": "How the user_data should be formatted for the server. For HEAT_CFNTOOLS, the user_data is bundled as part of the heat-cfntools cloud-init boot configuration data. For RAW the user_data is passed to Nova unmodified. For SOFTWARE_CONFIG user_data is bundled as part of the software config data, and metadata is derived from any associated SoftwareDeployment resources.", |
| 366 | "AllowedValues": [ |
| 367 | "HEAT_CFNTOOLS", |
| 368 | "RAW", |
| 369 | "SOFTWARE_CONFIG" |
| 370 | ] |
| 371 | }, |
| 372 | "admin_user": { |
| 373 | "Type": "String", |
| 374 | "Description": "Name of the administrative user to use on the server. This property will be removed from Juno in favor of the default cloud-init user set up for each image (e.g. \"ubuntu\" for Ubuntu 12.04+, \"fedora\" for Fedora 19+ and \"cloud-user\" for CentOS/RHEL 6.5)." |
| 375 | }, |
| 376 | "name": { |
| 377 | "Type": "String", |
| 378 | "Description": "Server name." |
| 379 | }, |
| 380 | "block_device_mapping": { |
| 381 | "Type": "CommaDelimitedList", |
| 382 | "Description": "Block device mappings for this server." |
| 383 | }, |
| 384 | "key_name": { |
| 385 | "Type": "String", |
| 386 | "Description": "Name of keypair to inject into the server." |
| 387 | }, |
| 388 | "image": { |
| 389 | "Type": "String", |
| 390 | "Description": "The ID or name of the image to boot with." |
| 391 | }, |
| 392 | "availability_zone": { |
| 393 | "Type": "String", |
| 394 | "Description": "Name of the availability zone for server placement." |
| 395 | }, |
| 396 | "image_update_policy": { |
| 397 | "Default": "REPLACE", |
| 398 | "Type": "String", |
| 399 | "Description": "Policy on how to apply an image-id update; either by requesting a server rebuild or by replacing the entire server", |
| 400 | "AllowedValues": [ |
| 401 | "REBUILD", |
| 402 | "REPLACE", |
| 403 | "REBUILD_PRESERVE_EPHEMERAL" |
| 404 | ] |
| 405 | }, |
| 406 | "software_config_transport": { |
| 407 | "Default": "POLL_SERVER_CFN", |
| 408 | "Type": "String", |
| 409 | "Description": "How the server should receive the metadata required for software configuration. POLL_SERVER_CFN will allow calls to the cfn API action DescribeStackResource authenticated with the provided keypair. POLL_SERVER_HEAT will allow calls to the Heat API resource-show using the provided keystone credentials.", |
| 410 | "AllowedValues": [ |
| 411 | "POLL_SERVER_CFN", |
| 412 | "POLL_SERVER_HEAT" |
| 413 | ] |
| 414 | }, |
| 415 | "metadata": { |
| 416 | "Type": "Json", |
| 417 | "Description": "Arbitrary key/value metadata to store for this server. Both keys and values must be 255 characters or less. Non-string values will be serialized to JSON (and the serialized string must be 255 characters or less)." |
| 418 | }, |
| 419 | "personality": { |
| 420 | "Default": {}, |
| 421 | "Type": "Json", |
| 422 | "Description": "A map of files to create/overwrite on the server upon boot. Keys are file names and values are the file contents." |
| 423 | }, |
| 424 | "user_data": { |
| 425 | "Default": "", |
| 426 | "Type": "String", |
| 427 | "Description": "User data script to be executed by cloud-init." |
| 428 | }, |
| 429 | "flavor_update_policy": { |
| 430 | "Default": "RESIZE", |
| 431 | "Type": "String", |
| 432 | "Description": "Policy on how to apply a flavor update; either by requesting a server resize or by replacing the entire server.", |
| 433 | "AllowedValues": [ |
| 434 | "RESIZE", |
| 435 | "REPLACE" |
| 436 | ] |
| 437 | }, |
| 438 | "flavor": { |
| 439 | "Type": "String", |
| 440 | "Description": "The ID or name of the flavor to boot onto." |
| 441 | }, |
| 442 | "diskConfig": { |
| 443 | "Type": "String", |
| 444 | "Description": "Control how the disk is partitioned when the server is created.", |
| 445 | "AllowedValues": [ |
| 446 | "AUTO", |
| 447 | "MANUAL" |
| 448 | ] |
| 449 | }, |
| 450 | "reservation_id": { |
| 451 | "Type": "String", |
| 452 | "Description": "A UUID for the set of servers being requested." |
| 453 | }, |
| 454 | "networks": { |
| 455 | "Type": "CommaDelimitedList", |
| 456 | "Description": "An ordered list of nics to be added to this server, with information about connected networks, fixed ips, port etc." |
| 457 | }, |
| 458 | "security_groups": { |
| 459 | "Default": [], |
| 460 | "Type": "CommaDelimitedList", |
| 461 | "Description": "List of security group names or IDs. Cannot be used if neutron ports are associated with this server; assign security groups to the ports instead." |
| 462 | }, |
| 463 | "config_drive": { |
| 464 | "Type": "String", |
| 465 | "Description": "value for config drive either boolean, or volume-id." |
| 466 | } |
| 467 | }, |
| 468 | "Resources": { |
| 469 | "Server": { |
| 470 | "Type": "OS::Nova::Server", |
| 471 | "Properties": { |
| 472 | "scheduler_hints": { |
| 473 | "Ref": "scheduler_hints" |
| 474 | }, |
| 475 | "admin_pass": { |
| 476 | "Ref": "admin_pass" |
| 477 | }, |
| 478 | "user_data_format": { |
| 479 | "Ref": "user_data_format" |
| 480 | }, |
| 481 | "admin_user": { |
| 482 | "Ref": "admin_user" |
| 483 | }, |
| 484 | "name": { |
| 485 | "Ref": "name" |
| 486 | }, |
| 487 | "block_device_mapping": { |
| 488 | "Fn::Split": [ |
| 489 | ",", |
| 490 | { |
| 491 | "Ref": "block_device_mapping" |
| 492 | } |
| 493 | ] |
| 494 | }, |
| 495 | "key_name": { |
| 496 | "Ref": "key_name" |
| 497 | }, |
| 498 | "image": { |
| 499 | "Ref": "image" |
| 500 | }, |
| 501 | "availability_zone": { |
| 502 | "Ref": "availability_zone" |
| 503 | }, |
| 504 | "image_update_policy": { |
| 505 | "Ref": "image_update_policy" |
| 506 | }, |
| 507 | "software_config_transport": { |
| 508 | "Ref": "software_config_transport" |
| 509 | }, |
| 510 | "metadata": { |
| 511 | "Ref": "metadata" |
| 512 | }, |
| 513 | "personality": { |
| 514 | "Ref": "personality" |
| 515 | }, |
| 516 | "user_data": { |
| 517 | "Ref": "user_data" |
| 518 | }, |
| 519 | "flavor_update_policy": { |
| 520 | "Ref": "flavor_update_policy" |
| 521 | }, |
| 522 | "flavor": { |
| 523 | "Ref": "flavor" |
| 524 | }, |
| 525 | "diskConfig": { |
| 526 | "Ref": "diskConfig" |
| 527 | }, |
| 528 | "reservation_id": { |
| 529 | "Ref": "reservation_id" |
| 530 | }, |
| 531 | "networks": { |
| 532 | "Fn::Split": [ |
| 533 | ",", |
| 534 | { |
| 535 | "Ref": "networks" |
| 536 | } |
| 537 | ] |
| 538 | }, |
| 539 | "security_groups": { |
| 540 | "Fn::Split": [ |
| 541 | ",", |
| 542 | { |
| 543 | "Ref": "security_groups" |
| 544 | } |
| 545 | ] |
| 546 | }, |
| 547 | "config_drive": { |
| 548 | "Ref": "config_drive" |
| 549 | } |
| 550 | } |
| 551 | } |
| 552 | } |
| 553 | }` |