cord-776 create build / runtime containers for autmation uservices
Change-Id: I246973192adef56a250ffe93a5f65fff488840c1
diff --git a/automation/vendor/github.com/juju/gomaasapi/interface.go b/automation/vendor/github.com/juju/gomaasapi/interface.go
new file mode 100644
index 0000000..f30a9a8
--- /dev/null
+++ b/automation/vendor/github.com/juju/gomaasapi/interface.go
@@ -0,0 +1,440 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package gomaasapi
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/juju/errors"
+ "github.com/juju/schema"
+ "github.com/juju/version"
+)
+
+// Can't use interface as a type, so add an underscore. Yay.
+type interface_ struct {
+ controller *controller
+
+ resourceURI string
+
+ id int
+ name string
+ type_ string
+ enabled bool
+ tags []string
+
+ vlan *vlan
+ links []*link
+
+ macAddress string
+ effectiveMTU int
+
+ parents []string
+ children []string
+}
+
+func (i *interface_) updateFrom(other *interface_) {
+ i.resourceURI = other.resourceURI
+ i.id = other.id
+ i.name = other.name
+ i.type_ = other.type_
+ i.enabled = other.enabled
+ i.tags = other.tags
+ i.vlan = other.vlan
+ i.links = other.links
+ i.macAddress = other.macAddress
+ i.effectiveMTU = other.effectiveMTU
+ i.parents = other.parents
+ i.children = other.children
+}
+
+// ID implements Interface.
+func (i *interface_) ID() int {
+ return i.id
+}
+
+// Name implements Interface.
+func (i *interface_) Name() string {
+ return i.name
+}
+
+// Parents implements Interface.
+func (i *interface_) Parents() []string {
+ return i.parents
+}
+
+// Children implements Interface.
+func (i *interface_) Children() []string {
+ return i.children
+}
+
+// Type implements Interface.
+func (i *interface_) Type() string {
+ return i.type_
+}
+
+// Enabled implements Interface.
+func (i *interface_) Enabled() bool {
+ return i.enabled
+}
+
+// Tags implements Interface.
+func (i *interface_) Tags() []string {
+ return i.tags
+}
+
+// VLAN implements Interface.
+func (i *interface_) VLAN() VLAN {
+ if i.vlan == nil {
+ return nil
+ }
+ return i.vlan
+}
+
+// Links implements Interface.
+func (i *interface_) Links() []Link {
+ result := make([]Link, len(i.links))
+ for i, link := range i.links {
+ result[i] = link
+ }
+ return result
+}
+
+// MACAddress implements Interface.
+func (i *interface_) MACAddress() string {
+ return i.macAddress
+}
+
+// EffectiveMTU implements Interface.
+func (i *interface_) EffectiveMTU() int {
+ return i.effectiveMTU
+}
+
+// UpdateInterfaceArgs is an argument struct for calling Interface.Update.
+type UpdateInterfaceArgs struct {
+ Name string
+ MACAddress string
+ VLAN VLAN
+}
+
+func (a *UpdateInterfaceArgs) vlanID() int {
+ if a.VLAN == nil {
+ return 0
+ }
+ return a.VLAN.ID()
+}
+
+// Update implements Interface.
+func (i *interface_) Update(args UpdateInterfaceArgs) error {
+ var empty UpdateInterfaceArgs
+ if args == empty {
+ return nil
+ }
+ params := NewURLParams()
+ params.MaybeAdd("name", args.Name)
+ params.MaybeAdd("mac_address", args.MACAddress)
+ params.MaybeAddInt("vlan", args.vlanID())
+ source, err := i.controller.put(i.resourceURI, params.Values)
+ if err != nil {
+ if svrErr, ok := errors.Cause(err).(ServerError); ok {
+ switch svrErr.StatusCode {
+ case http.StatusNotFound:
+ return errors.Wrap(err, NewNoMatchError(svrErr.BodyMessage))
+ case http.StatusForbidden:
+ return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage))
+ }
+ }
+ return NewUnexpectedError(err)
+ }
+
+ response, err := readInterface(i.controller.apiVersion, source)
+ if err != nil {
+ return errors.Trace(err)
+ }
+ i.updateFrom(response)
+ return nil
+}
+
+// Delete implements Interface.
+func (i *interface_) Delete() error {
+ err := i.controller.delete(i.resourceURI)
+ if err != nil {
+ if svrErr, ok := errors.Cause(err).(ServerError); ok {
+ switch svrErr.StatusCode {
+ case http.StatusNotFound:
+ return errors.Wrap(err, NewNoMatchError(svrErr.BodyMessage))
+ case http.StatusForbidden:
+ return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage))
+ }
+ }
+ return NewUnexpectedError(err)
+ }
+ return nil
+}
+
+// InterfaceLinkMode is the type of the various link mode constants used for
+// LinkSubnetArgs.
+type InterfaceLinkMode string
+
+const (
+ // LinkModeDHCP - Bring the interface up with DHCP on the given subnet. Only
+ // one subnet can be set to DHCP. If the subnet is managed this interface
+ // will pull from the dynamic IP range.
+ LinkModeDHCP InterfaceLinkMode = "DHCP"
+
+ // LinkModeStatic - Bring the interface up with a STATIC IP address on the
+ // given subnet. Any number of STATIC links can exist on an interface.
+ LinkModeStatic InterfaceLinkMode = "STATIC"
+
+ // LinkModeLinkUp - Bring the interface up only on the given subnet. No IP
+ // address will be assigned to this interface. The interface cannot have any
+ // current DHCP or STATIC links.
+ LinkModeLinkUp InterfaceLinkMode = "LINK_UP"
+)
+
+// LinkSubnetArgs is an argument struct for passing parameters to
+// the Interface.LinkSubnet method.
+type LinkSubnetArgs struct {
+ // Mode is used to describe how the address is provided for the Link.
+ // Required field.
+ Mode InterfaceLinkMode
+ // Subnet is the subnet to link to. Required field.
+ Subnet Subnet
+ // IPAddress is only valid when the Mode is set to LinkModeStatic. If
+ // not specified with a Mode of LinkModeStatic, an IP address from the
+ // subnet will be auto selected.
+ IPAddress string
+ // DefaultGateway will set the gateway IP address for the Subnet as the
+ // default gateway for the machine or device the interface belongs to.
+ // Option can only be used with mode LinkModeStatic.
+ DefaultGateway bool
+}
+
+// Validate ensures that the Mode and Subnet are set, and that the other options
+// are consistent with the Mode.
+func (a *LinkSubnetArgs) Validate() error {
+ switch a.Mode {
+ case LinkModeDHCP, LinkModeLinkUp, LinkModeStatic:
+ case "":
+ return errors.NotValidf("missing Mode")
+ default:
+ return errors.NotValidf("unknown Mode value (%q)", a.Mode)
+ }
+ if a.Subnet == nil {
+ return errors.NotValidf("missing Subnet")
+ }
+ if a.IPAddress != "" && a.Mode != LinkModeStatic {
+ return errors.NotValidf("setting IP Address when Mode is not LinkModeStatic")
+ }
+ if a.DefaultGateway && a.Mode != LinkModeStatic {
+ return errors.NotValidf("specifying DefaultGateway for Mode %q", a.Mode)
+ }
+ return nil
+}
+
+// LinkSubnet implements Interface.
+func (i *interface_) LinkSubnet(args LinkSubnetArgs) error {
+ if err := args.Validate(); err != nil {
+ return errors.Trace(err)
+ }
+ params := NewURLParams()
+ params.Values.Add("mode", string(args.Mode))
+ params.Values.Add("subnet", fmt.Sprint(args.Subnet.ID()))
+ params.MaybeAdd("ip_address", args.IPAddress)
+ params.MaybeAddBool("default_gateway", args.DefaultGateway)
+ source, err := i.controller.post(i.resourceURI, "link_subnet", params.Values)
+ if err != nil {
+ if svrErr, ok := errors.Cause(err).(ServerError); ok {
+ switch svrErr.StatusCode {
+ case http.StatusNotFound, http.StatusBadRequest:
+ return errors.Wrap(err, NewBadRequestError(svrErr.BodyMessage))
+ case http.StatusForbidden:
+ return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage))
+ case http.StatusServiceUnavailable:
+ return errors.Wrap(err, NewCannotCompleteError(svrErr.BodyMessage))
+ }
+ }
+ return NewUnexpectedError(err)
+ }
+
+ response, err := readInterface(i.controller.apiVersion, source)
+ if err != nil {
+ return errors.Trace(err)
+ }
+ i.updateFrom(response)
+ return nil
+}
+
+func (i *interface_) linkForSubnet(subnet Subnet) *link {
+ for _, link := range i.links {
+ if s := link.Subnet(); s != nil && s.ID() == subnet.ID() {
+ return link
+ }
+ }
+ return nil
+}
+
+// LinkSubnet implements Interface.
+func (i *interface_) UnlinkSubnet(subnet Subnet) error {
+ if subnet == nil {
+ return errors.NotValidf("missing Subnet")
+ }
+ link := i.linkForSubnet(subnet)
+ if link == nil {
+ return errors.NotValidf("unlinked Subnet")
+ }
+ params := NewURLParams()
+ params.Values.Add("id", fmt.Sprint(link.ID()))
+ source, err := i.controller.post(i.resourceURI, "unlink_subnet", params.Values)
+ if err != nil {
+ if svrErr, ok := errors.Cause(err).(ServerError); ok {
+ switch svrErr.StatusCode {
+ case http.StatusNotFound, http.StatusBadRequest:
+ return errors.Wrap(err, NewBadRequestError(svrErr.BodyMessage))
+ case http.StatusForbidden:
+ return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage))
+ }
+ }
+ return NewUnexpectedError(err)
+ }
+
+ response, err := readInterface(i.controller.apiVersion, source)
+ if err != nil {
+ return errors.Trace(err)
+ }
+ i.updateFrom(response)
+
+ return nil
+}
+
+func readInterface(controllerVersion version.Number, source interface{}) (*interface_, error) {
+ readFunc, err := getInterfaceDeserializationFunc(controllerVersion)
+ if err != nil {
+ return nil, errors.Trace(err)
+ }
+
+ checker := schema.StringMap(schema.Any())
+ coerced, err := checker.Coerce(source, nil)
+ if err != nil {
+ return nil, WrapWithDeserializationError(err, "interface base schema check failed")
+ }
+ valid := coerced.(map[string]interface{})
+ return readFunc(valid)
+}
+
+func readInterfaces(controllerVersion version.Number, source interface{}) ([]*interface_, error) {
+ readFunc, err := getInterfaceDeserializationFunc(controllerVersion)
+ if err != nil {
+ return nil, errors.Trace(err)
+ }
+
+ checker := schema.List(schema.StringMap(schema.Any()))
+ coerced, err := checker.Coerce(source, nil)
+ if err != nil {
+ return nil, WrapWithDeserializationError(err, "interface base schema check failed")
+ }
+ valid := coerced.([]interface{})
+ return readInterfaceList(valid, readFunc)
+}
+
+func getInterfaceDeserializationFunc(controllerVersion version.Number) (interfaceDeserializationFunc, error) {
+ var deserialisationVersion version.Number
+ for v := range interfaceDeserializationFuncs {
+ if v.Compare(deserialisationVersion) > 0 && v.Compare(controllerVersion) <= 0 {
+ deserialisationVersion = v
+ }
+ }
+ if deserialisationVersion == version.Zero {
+ return nil, NewUnsupportedVersionError("no interface read func for version %s", controllerVersion)
+ }
+ return interfaceDeserializationFuncs[deserialisationVersion], nil
+}
+
+func readInterfaceList(sourceList []interface{}, readFunc interfaceDeserializationFunc) ([]*interface_, error) {
+ result := make([]*interface_, 0, len(sourceList))
+ for i, value := range sourceList {
+ source, ok := value.(map[string]interface{})
+ if !ok {
+ return nil, NewDeserializationError("unexpected value for interface %d, %T", i, value)
+ }
+ read, err := readFunc(source)
+ if err != nil {
+ return nil, errors.Annotatef(err, "interface %d", i)
+ }
+ result = append(result, read)
+ }
+ return result, nil
+}
+
+type interfaceDeserializationFunc func(map[string]interface{}) (*interface_, error)
+
+var interfaceDeserializationFuncs = map[version.Number]interfaceDeserializationFunc{
+ twoDotOh: interface_2_0,
+}
+
+func interface_2_0(source map[string]interface{}) (*interface_, error) {
+ fields := schema.Fields{
+ "resource_uri": schema.String(),
+
+ "id": schema.ForceInt(),
+ "name": schema.String(),
+ "type": schema.String(),
+ "enabled": schema.Bool(),
+ "tags": schema.OneOf(schema.Nil(""), schema.List(schema.String())),
+
+ "vlan": schema.OneOf(schema.Nil(""), schema.StringMap(schema.Any())),
+ "links": schema.List(schema.StringMap(schema.Any())),
+
+ "mac_address": schema.OneOf(schema.Nil(""), schema.String()),
+ "effective_mtu": schema.ForceInt(),
+
+ "parents": schema.List(schema.String()),
+ "children": schema.List(schema.String()),
+ }
+ defaults := schema.Defaults{
+ "mac_address": "",
+ }
+ checker := schema.FieldMap(fields, defaults)
+ coerced, err := checker.Coerce(source, nil)
+ if err != nil {
+ return nil, WrapWithDeserializationError(err, "interface 2.0 schema check failed")
+ }
+ valid := coerced.(map[string]interface{})
+ // From here we know that the map returned from the schema coercion
+ // contains fields of the right type.
+
+ var vlan *vlan
+ // If it's not an attribute map then we know it's nil from the schema check.
+ if vlanMap, ok := valid["vlan"].(map[string]interface{}); ok {
+ vlan, err = vlan_2_0(vlanMap)
+ if err != nil {
+ return nil, errors.Trace(err)
+ }
+ }
+
+ links, err := readLinkList(valid["links"].([]interface{}), link_2_0)
+ if err != nil {
+ return nil, errors.Trace(err)
+ }
+ macAddress, _ := valid["mac_address"].(string)
+ result := &interface_{
+ resourceURI: valid["resource_uri"].(string),
+
+ id: valid["id"].(int),
+ name: valid["name"].(string),
+ type_: valid["type"].(string),
+ enabled: valid["enabled"].(bool),
+ tags: convertToStringSlice(valid["tags"]),
+
+ vlan: vlan,
+ links: links,
+
+ macAddress: macAddress,
+ effectiveMTU: valid["effective_mtu"].(int),
+
+ parents: convertToStringSlice(valid["parents"]),
+ children: convertToStringSlice(valid["children"]),
+ }
+ return result, nil
+}