github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/kubernetes/structures.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strings"
     7  
     8  	"encoding/base64"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"k8s.io/kubernetes/pkg/api/resource"
    11  	api "k8s.io/kubernetes/pkg/api/v1"
    12  )
    13  
    14  func idParts(id string) (string, string) {
    15  	parts := strings.Split(id, "/")
    16  	return parts[0], parts[1]
    17  }
    18  
    19  func buildId(meta api.ObjectMeta) string {
    20  	return meta.Namespace + "/" + meta.Name
    21  }
    22  
    23  func expandMetadata(in []interface{}) api.ObjectMeta {
    24  	meta := api.ObjectMeta{}
    25  	if len(in) < 1 {
    26  		return meta
    27  	}
    28  	m := in[0].(map[string]interface{})
    29  
    30  	meta.Annotations = expandStringMap(m["annotations"].(map[string]interface{}))
    31  	meta.Labels = expandStringMap(m["labels"].(map[string]interface{}))
    32  
    33  	if v, ok := m["generate_name"]; ok {
    34  		meta.GenerateName = v.(string)
    35  	}
    36  	if v, ok := m["name"]; ok {
    37  		meta.Name = v.(string)
    38  	}
    39  	if v, ok := m["namespace"]; ok {
    40  		meta.Namespace = v.(string)
    41  	}
    42  
    43  	return meta
    44  }
    45  
    46  func patchMetadata(keyPrefix, pathPrefix string, d *schema.ResourceData) PatchOperations {
    47  	ops := make([]PatchOperation, 0, 0)
    48  	if d.HasChange(keyPrefix + "annotations") {
    49  		oldV, newV := d.GetChange(keyPrefix + "annotations")
    50  		diffOps := diffStringMap(pathPrefix+"annotations", oldV.(map[string]interface{}), newV.(map[string]interface{}))
    51  		ops = append(ops, diffOps...)
    52  	}
    53  	if d.HasChange(keyPrefix + "labels") {
    54  		oldV, newV := d.GetChange(keyPrefix + "labels")
    55  		diffOps := diffStringMap(pathPrefix+"labels", oldV.(map[string]interface{}), newV.(map[string]interface{}))
    56  		ops = append(ops, diffOps...)
    57  	}
    58  	return ops
    59  }
    60  
    61  func expandStringMap(m map[string]interface{}) map[string]string {
    62  	result := make(map[string]string)
    63  	for k, v := range m {
    64  		result[k] = v.(string)
    65  	}
    66  	return result
    67  }
    68  
    69  func expandStringSlice(s []interface{}) []string {
    70  	result := make([]string, len(s), len(s))
    71  	for k, v := range s {
    72  		result[k] = v.(string)
    73  	}
    74  	return result
    75  }
    76  
    77  func flattenMetadata(meta api.ObjectMeta) []map[string]interface{} {
    78  	m := make(map[string]interface{})
    79  	m["annotations"] = filterAnnotations(meta.Annotations)
    80  	if meta.GenerateName != "" {
    81  		m["generate_name"] = meta.GenerateName
    82  	}
    83  	m["labels"] = meta.Labels
    84  	m["name"] = meta.Name
    85  	m["resource_version"] = meta.ResourceVersion
    86  	m["self_link"] = meta.SelfLink
    87  	m["uid"] = fmt.Sprintf("%v", meta.UID)
    88  	m["generation"] = meta.Generation
    89  
    90  	if meta.Namespace != "" {
    91  		m["namespace"] = meta.Namespace
    92  	}
    93  
    94  	return []map[string]interface{}{m}
    95  }
    96  
    97  func filterAnnotations(m map[string]string) map[string]string {
    98  	for k, _ := range m {
    99  		if isInternalAnnotationKey(k) {
   100  			delete(m, k)
   101  		}
   102  	}
   103  	return m
   104  }
   105  
   106  func isInternalAnnotationKey(annotationKey string) bool {
   107  	u, err := url.Parse("//" + annotationKey)
   108  	if err == nil && strings.HasSuffix(u.Hostname(), "kubernetes.io") {
   109  		return true
   110  	}
   111  
   112  	return false
   113  }
   114  
   115  func byteMapToStringMap(m map[string][]byte) map[string]string {
   116  	result := make(map[string]string)
   117  	for k, v := range m {
   118  		result[k] = string(v)
   119  	}
   120  	return result
   121  }
   122  
   123  func ptrToString(s string) *string {
   124  	return &s
   125  }
   126  
   127  func ptrToInt(i int) *int {
   128  	return &i
   129  }
   130  
   131  func ptrToBool(b bool) *bool {
   132  	return &b
   133  }
   134  
   135  func ptrToInt32(i int32) *int32 {
   136  	return &i
   137  }
   138  
   139  func sliceOfString(slice []interface{}) []string {
   140  	result := make([]string, len(slice), len(slice))
   141  	for i, s := range slice {
   142  		result[i] = s.(string)
   143  	}
   144  	return result
   145  }
   146  
   147  func base64EncodeStringMap(m map[string]interface{}) map[string]interface{} {
   148  	result := make(map[string]interface{})
   149  	for k, v := range m {
   150  		value := v.(string)
   151  		result[k] = (base64.StdEncoding.EncodeToString([]byte(value)))
   152  	}
   153  	return result
   154  }
   155  
   156  func flattenResourceList(l api.ResourceList) map[string]string {
   157  	m := make(map[string]string)
   158  	for k, v := range l {
   159  		m[string(k)] = v.String()
   160  	}
   161  	return m
   162  }
   163  
   164  func expandMapToResourceList(m map[string]interface{}) (api.ResourceList, error) {
   165  	out := make(map[api.ResourceName]resource.Quantity)
   166  	for stringKey, origValue := range m {
   167  		key := api.ResourceName(stringKey)
   168  		var value resource.Quantity
   169  
   170  		if v, ok := origValue.(int); ok {
   171  			q := resource.NewQuantity(int64(v), resource.DecimalExponent)
   172  			value = *q
   173  		} else if v, ok := origValue.(string); ok {
   174  			var err error
   175  			value, err = resource.ParseQuantity(v)
   176  			if err != nil {
   177  				return out, err
   178  			}
   179  		} else {
   180  			return out, fmt.Errorf("Unexpected value type: %#v", origValue)
   181  		}
   182  
   183  		out[key] = value
   184  	}
   185  	return out, nil
   186  }
   187  
   188  func flattenPersistentVolumeAccessModes(in []api.PersistentVolumeAccessMode) *schema.Set {
   189  	var out = make([]interface{}, len(in), len(in))
   190  	for i, v := range in {
   191  		out[i] = string(v)
   192  	}
   193  	return schema.NewSet(schema.HashString, out)
   194  }
   195  
   196  func expandPersistentVolumeAccessModes(s []interface{}) []api.PersistentVolumeAccessMode {
   197  	out := make([]api.PersistentVolumeAccessMode, len(s), len(s))
   198  	for i, v := range s {
   199  		out[i] = api.PersistentVolumeAccessMode(v.(string))
   200  	}
   201  	return out
   202  }
   203  
   204  func flattenResourceQuotaSpec(in api.ResourceQuotaSpec) []interface{} {
   205  	out := make([]interface{}, 1)
   206  
   207  	m := make(map[string]interface{}, 0)
   208  	m["hard"] = flattenResourceList(in.Hard)
   209  	m["scopes"] = flattenResourceQuotaScopes(in.Scopes)
   210  
   211  	out[0] = m
   212  	return out
   213  }
   214  
   215  func expandResourceQuotaSpec(s []interface{}) (api.ResourceQuotaSpec, error) {
   216  	out := api.ResourceQuotaSpec{}
   217  	if len(s) < 1 {
   218  		return out, nil
   219  	}
   220  	m := s[0].(map[string]interface{})
   221  
   222  	if v, ok := m["hard"]; ok {
   223  		list, err := expandMapToResourceList(v.(map[string]interface{}))
   224  		if err != nil {
   225  			return out, err
   226  		}
   227  		out.Hard = list
   228  	}
   229  
   230  	if v, ok := m["scopes"]; ok {
   231  		out.Scopes = expandResourceQuotaScopes(v.(*schema.Set).List())
   232  	}
   233  
   234  	return out, nil
   235  }
   236  
   237  func flattenResourceQuotaScopes(in []api.ResourceQuotaScope) *schema.Set {
   238  	out := make([]string, len(in), len(in))
   239  	for i, scope := range in {
   240  		out[i] = string(scope)
   241  	}
   242  	return newStringSet(schema.HashString, out)
   243  }
   244  
   245  func expandResourceQuotaScopes(s []interface{}) []api.ResourceQuotaScope {
   246  	out := make([]api.ResourceQuotaScope, len(s), len(s))
   247  	for i, scope := range s {
   248  		out[i] = api.ResourceQuotaScope(scope.(string))
   249  	}
   250  	return out
   251  }
   252  
   253  func newStringSet(f schema.SchemaSetFunc, in []string) *schema.Set {
   254  	var out = make([]interface{}, len(in), len(in))
   255  	for i, v := range in {
   256  		out[i] = v
   257  	}
   258  	return schema.NewSet(f, out)
   259  }
   260  
   261  func resourceListEquals(x, y api.ResourceList) bool {
   262  	for k, v := range x {
   263  		yValue, ok := y[k]
   264  		if !ok {
   265  			return false
   266  		}
   267  		if v.Cmp(yValue) != 0 {
   268  			return false
   269  		}
   270  	}
   271  	for k, v := range y {
   272  		xValue, ok := x[k]
   273  		if !ok {
   274  			return false
   275  		}
   276  		if v.Cmp(xValue) != 0 {
   277  			return false
   278  		}
   279  	}
   280  	return true
   281  }
   282  
   283  func expandLimitRangeSpec(s []interface{}, isNew bool) (api.LimitRangeSpec, error) {
   284  	out := api.LimitRangeSpec{}
   285  	if len(s) < 1 || s[0] == nil {
   286  		return out, nil
   287  	}
   288  	m := s[0].(map[string]interface{})
   289  
   290  	if limits, ok := m["limit"].([]interface{}); ok {
   291  		newLimits := make([]api.LimitRangeItem, len(limits), len(limits))
   292  
   293  		for i, l := range limits {
   294  			lrItem := api.LimitRangeItem{}
   295  			limit := l.(map[string]interface{})
   296  
   297  			if v, ok := limit["type"]; ok {
   298  				lrItem.Type = api.LimitType(v.(string))
   299  			}
   300  
   301  			// defaultRequest is forbidden for Pod limits, even though it's set & returned by API
   302  			// this is how we avoid sending it back
   303  			if v, ok := limit["default_request"]; ok {
   304  				drm := v.(map[string]interface{})
   305  				if lrItem.Type == api.LimitTypePod && len(drm) > 0 {
   306  					if isNew {
   307  						return out, fmt.Errorf("limit.%d.default_request cannot be set for Pod limit", i)
   308  					}
   309  				} else {
   310  					el, err := expandMapToResourceList(drm)
   311  					if err != nil {
   312  						return out, err
   313  					}
   314  					lrItem.DefaultRequest = el
   315  				}
   316  			}
   317  
   318  			if v, ok := limit["default"]; ok {
   319  				el, err := expandMapToResourceList(v.(map[string]interface{}))
   320  				if err != nil {
   321  					return out, err
   322  				}
   323  				lrItem.Default = el
   324  			}
   325  			if v, ok := limit["max"]; ok {
   326  				el, err := expandMapToResourceList(v.(map[string]interface{}))
   327  				if err != nil {
   328  					return out, err
   329  				}
   330  				lrItem.Max = el
   331  			}
   332  			if v, ok := limit["max_limit_request_ratio"]; ok {
   333  				el, err := expandMapToResourceList(v.(map[string]interface{}))
   334  				if err != nil {
   335  					return out, err
   336  				}
   337  				lrItem.MaxLimitRequestRatio = el
   338  			}
   339  			if v, ok := limit["min"]; ok {
   340  				el, err := expandMapToResourceList(v.(map[string]interface{}))
   341  				if err != nil {
   342  					return out, err
   343  				}
   344  				lrItem.Min = el
   345  			}
   346  
   347  			newLimits[i] = lrItem
   348  		}
   349  
   350  		out.Limits = newLimits
   351  	}
   352  
   353  	return out, nil
   354  }
   355  
   356  func flattenLimitRangeSpec(in api.LimitRangeSpec) []interface{} {
   357  	out := make([]interface{}, 1)
   358  	limits := make([]interface{}, len(in.Limits), len(in.Limits))
   359  
   360  	for i, l := range in.Limits {
   361  		m := make(map[string]interface{}, 0)
   362  		m["default"] = flattenResourceList(l.Default)
   363  		m["default_request"] = flattenResourceList(l.DefaultRequest)
   364  		m["max"] = flattenResourceList(l.Max)
   365  		m["max_limit_request_ratio"] = flattenResourceList(l.MaxLimitRequestRatio)
   366  		m["min"] = flattenResourceList(l.Min)
   367  		m["type"] = string(l.Type)
   368  
   369  		limits[i] = m
   370  	}
   371  	out[0] = map[string]interface{}{
   372  		"limit": limits,
   373  	}
   374  	return out
   375  }