cord-776 create build / runtime containers for autmation uservices
Change-Id: I246973192adef56a250ffe93a5f65fff488840c1
diff --git a/automation/vendor/github.com/juju/gomaasapi/jsonobject.go b/automation/vendor/github.com/juju/gomaasapi/jsonobject.go
new file mode 100644
index 0000000..cdd3dc1
--- /dev/null
+++ b/automation/vendor/github.com/juju/gomaasapi/jsonobject.go
@@ -0,0 +1,215 @@
+// Copyright 2012-2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package gomaasapi
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+)
+
+// JSONObject is a wrapper around a JSON structure which provides
+// methods to extract data from that structure.
+// A JSONObject provides a simple structure consisting of the data types
+// defined in JSON: string, number, object, list, and bool. To get the
+// value you want out of a JSONObject, you must know (or figure out) which
+// kind of value you have, and then call the appropriate Get*() method to
+// get at it. Reading an item as the wrong type will return an error.
+// For instance, if your JSONObject consists of a number, call GetFloat64()
+// to get the value as a float64. If it's a list, call GetArray() to get
+// a slice of JSONObjects. To read any given item from the slice, you'll
+// need to "Get" that as the right type as well.
+// There is one exception: a MAASObject is really a special kind of map,
+// so you can read it as either.
+// Reading a null item is also an error. So before you try obj.Get*(),
+// first check obj.IsNil().
+type JSONObject struct {
+ // Parsed value. May actually be any of the types a JSONObject can
+ // wrap, except raw bytes. If the object can only be interpreted
+ // as raw bytes, this will be nil.
+ value interface{}
+ // Raw bytes, if this object was parsed directly from an API response.
+ // Is nil for sub-objects found within other objects. An object that
+ // was parsed directly from a response can be both raw bytes and some
+ // other value at the same time.
+ // For example, "[]" looks like a JSON list, so you can read it as an
+ // array. But it may also be the raw contents of a file that just
+ // happens to look like JSON, and so you can read it as raw bytes as
+ // well.
+ bytes []byte
+ // Client for further communication with the API.
+ client Client
+ // Is this a JSON null?
+ isNull bool
+}
+
+// Our JSON processor distinguishes a MAASObject from a jsonMap by the fact
+// that it contains a key "resource_uri". (A regular map might contain the
+// same key through sheer coincide, but never mind: you can still treat it
+// as a jsonMap and never notice the difference.)
+const resourceURI = "resource_uri"
+
+// maasify turns a completely untyped json.Unmarshal result into a JSONObject
+// (with the appropriate implementation of course). This function is
+// recursive. Maps and arrays are deep-copied, with each individual value
+// being converted to a JSONObject type.
+func maasify(client Client, value interface{}) JSONObject {
+ if value == nil {
+ return JSONObject{isNull: true}
+ }
+ switch value.(type) {
+ case string, float64, bool:
+ return JSONObject{value: value}
+ case map[string]interface{}:
+ original := value.(map[string]interface{})
+ result := make(map[string]JSONObject, len(original))
+ for key, value := range original {
+ result[key] = maasify(client, value)
+ }
+ return JSONObject{value: result, client: client}
+ case []interface{}:
+ original := value.([]interface{})
+ result := make([]JSONObject, len(original))
+ for index, value := range original {
+ result[index] = maasify(client, value)
+ }
+ return JSONObject{value: result}
+ }
+ msg := fmt.Sprintf("Unknown JSON type, can't be converted to JSONObject: %v", value)
+ panic(msg)
+}
+
+// Parse a JSON blob into a JSONObject.
+func Parse(client Client, input []byte) (JSONObject, error) {
+ var obj JSONObject
+ if input == nil {
+ panic(errors.New("Parse() called with nil input"))
+ }
+ var parsed interface{}
+ err := json.Unmarshal(input, &parsed)
+ if err == nil {
+ obj = maasify(client, parsed)
+ obj.bytes = input
+ } else {
+ switch err.(type) {
+ case *json.InvalidUTF8Error:
+ case *json.SyntaxError:
+ // This isn't JSON. Treat it as raw binary data.
+ default:
+ return obj, err
+ }
+ obj = JSONObject{value: nil, client: client, bytes: input}
+ }
+ return obj, nil
+}
+
+// JSONObjectFromStruct takes a struct and converts it to a JSONObject
+func JSONObjectFromStruct(client Client, input interface{}) (JSONObject, error) {
+ j, err := json.MarshalIndent(input, "", " ")
+ if err != nil {
+ return JSONObject{}, err
+ }
+ return Parse(client, j)
+}
+
+// Return error value for failed type conversion.
+func failConversion(wantedType string, obj JSONObject) error {
+ msg := fmt.Sprintf("Requested %v, got %T.", wantedType, obj.value)
+ return errors.New(msg)
+}
+
+// MarshalJSON tells the standard json package how to serialize a JSONObject
+// back to JSON.
+func (obj JSONObject) MarshalJSON() ([]byte, error) {
+ if obj.IsNil() {
+ return json.Marshal(nil)
+ }
+ return json.MarshalIndent(obj.value, "", " ")
+}
+
+// With MarshalJSON, JSONObject implements json.Marshaler.
+var _ json.Marshaler = (*JSONObject)(nil)
+
+// IsNil tells you whether a JSONObject is a JSON "null."
+// There is one irregularity. If the original JSON blob was actually raw
+// data, not JSON, then its IsNil will return false because the object
+// contains the binary data as a non-nil value. But, if the original JSON
+// blob consisted of a null, then IsNil returns true even though you can
+// still retrieve binary data from it.
+func (obj JSONObject) IsNil() bool {
+ if obj.value != nil {
+ return false
+ }
+ if obj.bytes == nil {
+ return true
+ }
+ // This may be a JSON null. We can't expect every JSON null to look
+ // the same; there may be leading or trailing space.
+ return obj.isNull
+}
+
+// GetString retrieves the object's value as a string. If the value wasn't
+// a JSON string, that's an error.
+func (obj JSONObject) GetString() (value string, err error) {
+ value, ok := obj.value.(string)
+ if !ok {
+ err = failConversion("string", obj)
+ }
+ return
+}
+
+// GetFloat64 retrieves the object's value as a float64. If the value wasn't
+// a JSON number, that's an error.
+func (obj JSONObject) GetFloat64() (value float64, err error) {
+ value, ok := obj.value.(float64)
+ if !ok {
+ err = failConversion("float64", obj)
+ }
+ return
+}
+
+// GetMap retrieves the object's value as a map. If the value wasn't a JSON
+// object, that's an error.
+func (obj JSONObject) GetMap() (value map[string]JSONObject, err error) {
+ value, ok := obj.value.(map[string]JSONObject)
+ if !ok {
+ err = failConversion("map", obj)
+ }
+ return
+}
+
+// GetArray retrieves the object's value as an array. If the value wasn't a
+// JSON list, that's an error.
+func (obj JSONObject) GetArray() (value []JSONObject, err error) {
+ value, ok := obj.value.([]JSONObject)
+ if !ok {
+ err = failConversion("array", obj)
+ }
+ return
+}
+
+// GetBool retrieves the object's value as a bool. If the value wasn't a JSON
+// bool, that's an error.
+func (obj JSONObject) GetBool() (value bool, err error) {
+ value, ok := obj.value.(bool)
+ if !ok {
+ err = failConversion("bool", obj)
+ }
+ return
+}
+
+// GetBytes retrieves the object's value as raw bytes. A JSONObject that was
+// parsed from the original input (as opposed to one that's embedded in
+// another JSONObject) can contain both the raw bytes and the parsed JSON
+// value, but either can be the case without the other.
+// If this object wasn't parsed directly from the original input, that's an
+// error.
+// If the object was parsed from an original input that just said "null", then
+// IsNil will return true but the raw bytes are still available from GetBytes.
+func (obj JSONObject) GetBytes() ([]byte, error) {
+ if obj.bytes == nil {
+ return nil, failConversion("bytes", obj)
+ }
+ return obj.bytes, nil
+}