blob: 94fda6cb2eb9ad123dc2cff9b25e102f0e1cb4b5 [file] [log] [blame]
Pratik Mallya5fddb2a2015-09-14 14:04:49 -05001package stacks
2
3import (
4 "errors"
5 "fmt"
6 "strings"
7)
8
9// an interface to represent stack environments
10type Environment struct {
11 TE
12}
13
14// allowed sections in a stack environment file
15var EnvironmentSections = map[string]bool{
16 "parameters": true,
17 "parameter_defaults": true,
18 "resource_registry": true,
19}
20
21func (e *Environment) Validate() error {
22 if e.Parsed == nil {
23 if err := e.Parse(); err != nil {
24 return err
25 }
26 }
27 for key, _ := range e.Parsed {
28 if _, ok := EnvironmentSections[key]; !ok {
29 return errors.New(fmt.Sprintf("Environment has wrong section: %s", key))
30 }
31 }
32 return nil
33}
34
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050035// Parse environment file to resolve the URL's of the resources. This is done by
36// reading from the `Resource Registry` section, which is why the function is
37// named GetRRFileContents.
Pratik Mallyae3086ae2015-09-21 15:25:16 -050038func (e *Environment) GetRRFileContents(ignoreIf igFunc) error {
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050039 // initialize environment if empty
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050040 if e.Files == nil {
41 e.Files = make(map[string]string)
42 }
43 if e.fileMaps == nil {
44 e.fileMaps = make(map[string]string)
45 }
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050046
47 // get the resource registry
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050048 rr := e.Parsed["resource_registry"]
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050049
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050050 // search the resource registry for URLs
51 switch rr.(type) {
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050052 // process further only if the resource registry is a map
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050053 case map[string]interface{}, map[interface{}]interface{}:
54 rr_map, err := toStringKeys(rr)
55 if err != nil {
56 return err
57 }
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050058 // the resource registry might contain a base URL for the resource. If
59 // such a field is present, use it. Otherwise, use the default base URL.
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050060 var baseURL string
61 if val, ok := rr_map["base_url"]; ok {
62 baseURL = val.(string)
63 } else {
64 baseURL = e.baseURL
65 }
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050066
67 // The contents of the resource may be located in a remote file, which
68 // will be a template. Instantiate a temporary template to manage the
69 // contents.
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050070 tempTemplate := new(Template)
71 tempTemplate.baseURL = baseURL
72 tempTemplate.client = e.client
73
Pratik Mallyae3086ae2015-09-21 15:25:16 -050074 // Fetch the contents of remote resource URL's
75 if err = tempTemplate.GetFileContents(rr, ignoreIf, false); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050076 return err
77 }
Pratik Mallyae3086ae2015-09-21 15:25:16 -050078 // check the `resources` section (if it exists) for more URL's. Note that
79 // the previous call to GetFileContents was (deliberately) not recursive
80 // as we want more control over where to look for URL's
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050081 if val, ok := rr_map["resources"]; ok {
82 switch val.(type) {
Pratik Mallyabfc6eda2015-09-21 15:01:18 -050083 // process further only if the contents are a map
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050084 case map[string]interface{}, map[interface{}]interface{}:
85 resources_map, err := toStringKeys(val)
86 if err != nil {
87 return err
88 }
89 for _, v := range resources_map {
90 switch v.(type) {
91 case map[string]interface{}, map[interface{}]interface{}:
92 resource_map, err := toStringKeys(v)
93 if err != nil {
94 return err
95 }
96 var resourceBaseURL string
97 // if base_url for the resource type is defined, use it
98 if val, ok := resource_map["base_url"]; ok {
99 resourceBaseURL = val.(string)
100 } else {
101 resourceBaseURL = baseURL
102 }
103 tempTemplate.baseURL = resourceBaseURL
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500104 if err := tempTemplate.GetFileContents(v, ignoreIf, false); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500105 return err
106 }
107 }
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500108 }
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500109 }
110 }
Pratik Mallyabfc6eda2015-09-21 15:01:18 -0500111 // if the resource registry contained any URL's, store them. This can
112 // then be passed as parameter to api calls to Heat api.
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500113 e.Files = tempTemplate.Files
114 return nil
115 default:
116 return nil
117 }
118}
119
120// function to choose keys whose values are other environment files
121func ignoreIfEnvironment(key string, value interface{}) bool {
122 // base_url and hooks refer to components which cannot have urls
123 if key == "base_url" || key == "hooks" {
124 return true
125 }
126 // if value is not string, it cannot be a URL
127 valueString, ok := value.(string)
128 if !ok {
129 return true
130 }
131 // if value contains `::`, it must be a reference to another resource type
132 // e.g. OS::Nova::Server : Rackspace::Cloud::Server
133 if strings.Contains(valueString, "::") {
134 return true
135 }
136 return false
137}