github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/rts/v1/stacks/environment.go (about)

     1  package stacks
     2  
     3  import "strings"
     4  
     5  // Environment is a structure that represents stack environments
     6  type Environment struct {
     7  	TE
     8  }
     9  
    10  // EnvironmentSections is a map containing allowed sections in a stack environment file
    11  var EnvironmentSections = map[string]bool{
    12  	"parameters":         true,
    13  	"parameter_defaults": true,
    14  	"resource_registry":  true,
    15  }
    16  
    17  // Validate validates the contents of the Environment
    18  func (e *Environment) Validate() error {
    19  	if e.Parsed == nil {
    20  		if err := e.Parse(); err != nil {
    21  			return err
    22  		}
    23  	}
    24  	for key := range e.Parsed {
    25  		if _, ok := EnvironmentSections[key]; !ok {
    26  			return ErrInvalidEnvironment{Section: key}
    27  		}
    28  	}
    29  	return nil
    30  }
    31  
    32  // Parse environment file to resolve the URL's of the resources. This is done by
    33  // reading from the `Resource Registry` section, which is why the function is
    34  // named GetRRFileContents.
    35  func (e *Environment) getRRFileContents(ignoreIf igFunc) error {
    36  	// initialize environment if empty
    37  	if e.Files == nil {
    38  		e.Files = make(map[string]string)
    39  	}
    40  	if e.fileMaps == nil {
    41  		e.fileMaps = make(map[string]string)
    42  	}
    43  
    44  	// get the resource registry
    45  	rr := e.Parsed["resource_registry"]
    46  
    47  	// search the resource registry for URLs
    48  	switch rr.(type) {
    49  	// process further only if the resource registry is a map
    50  	case map[string]interface{}, map[interface{}]interface{}:
    51  		rrMap, err := toStringKeys(rr)
    52  		if err != nil {
    53  			return err
    54  		}
    55  		// the resource registry might contain a base URL for the resource. If
    56  		// such a field is present, use it. Otherwise, use the default base URL.
    57  		var baseURL string
    58  		if val, ok := rrMap["base_url"]; ok {
    59  			baseURL = val.(string)
    60  		} else {
    61  			baseURL = e.baseURL
    62  		}
    63  
    64  		// The contents of the resource may be located in a remote file, which
    65  		// will be a template. Instantiate a temporary template to manage the
    66  		// contents.
    67  		tempTemplate := new(Template)
    68  		tempTemplate.baseURL = baseURL
    69  		tempTemplate.client = e.client
    70  
    71  		// Fetch the contents of remote resource URL's
    72  		if err = tempTemplate.getFileContents(rr, ignoreIf, false); err != nil {
    73  			return err
    74  		}
    75  		// check the `resources` section (if it exists) for more URL's. Note that
    76  		// the previous call to GetFileContents was (deliberately) not recursive
    77  		// as we want more control over where to look for URL's
    78  		if val, ok := rrMap["resources"]; ok {
    79  			switch val.(type) {
    80  			// process further only if the contents are a map
    81  			case map[string]interface{}, map[interface{}]interface{}:
    82  				resourcesMap, err := toStringKeys(val)
    83  				if err != nil {
    84  					return err
    85  				}
    86  				for _, v := range resourcesMap {
    87  					switch v.(type) {
    88  					case map[string]interface{}, map[interface{}]interface{}:
    89  						resourceMap, err := toStringKeys(v)
    90  						if err != nil {
    91  							return err
    92  						}
    93  						var resourceBaseURL string
    94  						// if base_url for the resource type is defined, use it
    95  						if val, ok := resourceMap["base_url"]; ok {
    96  							resourceBaseURL = val.(string)
    97  						} else {
    98  							resourceBaseURL = baseURL
    99  						}
   100  						tempTemplate.baseURL = resourceBaseURL
   101  						if err := tempTemplate.getFileContents(v, ignoreIf, false); err != nil {
   102  							return err
   103  						}
   104  					}
   105  				}
   106  			}
   107  		}
   108  		// if the resource registry contained any URL's, store them. This can
   109  		// then be passed as parameter to api calls to Heat api.
   110  		e.Files = tempTemplate.Files
   111  		return nil
   112  	default:
   113  		return nil
   114  	}
   115  }
   116  
   117  // function to choose keys whose values are other environment files
   118  func ignoreIfEnvironment(key string, value interface{}) bool {
   119  	// base_url and hooks refer to components which cannot have urls
   120  	if key == "base_url" || key == "hooks" {
   121  		return true
   122  	}
   123  	// if value is not string, it cannot be a URL
   124  	valueString, ok := value.(string)
   125  	if !ok {
   126  		return true
   127  	}
   128  	// if value contains `::`, it must be a reference to another resource type
   129  	// e.g. OS::Nova::Server : Rackspace::Cloud::Server
   130  	if strings.Contains(valueString, "::") {
   131  		return true
   132  	}
   133  	return false
   134  }