func parseAllocateConstraintsResponse(source interface{}, machine *machine) (ConstraintMatches, error) { var empty ConstraintMatches matchFields := schema.Fields{ "storage": schema.StringMap(schema.ForceInt()), "interfaces": schema.StringMap(schema.ForceInt()), } matchDefaults := schema.Defaults{ "storage": schema.Omit, "interfaces": schema.Omit, } fields := schema.Fields{ "constraints_by_type": schema.FieldMap(matchFields, matchDefaults), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return empty, WrapWithDeserializationError(err, "allocation constraints response schema check failed") } valid := coerced.(map[string]interface{}) constraintsMap := valid["constraints_by_type"].(map[string]interface{}) result := ConstraintMatches{ Interfaces: make(map[string]Interface), Storage: make(map[string]BlockDevice), } if interfaceMatches, found := constraintsMap["interfaces"]; found { for label, value := range interfaceMatches.(map[string]interface{}) { id := value.(int) iface := machine.Interface(id) if iface == nil { return empty, NewDeserializationError("constraint match interface %q: %d does not match an interface for the machine", label, id) } result.Interfaces[label] = iface } } if storageMatches, found := constraintsMap["storage"]; found { for label, value := range storageMatches.(map[string]interface{}) { id := value.(int) blockDevice := machine.PhysicalBlockDevice(id) if blockDevice == nil { return empty, NewDeserializationError("constraint match storage %q: %d does not match a physical block device for the machine", label, id) } result.Storage[label] = blockDevice } } return result, nil }
func importActionV1(source map[string]interface{}) (*action, error) { fields := schema.Fields{ "receiver": schema.String(), "name": schema.String(), "parameters": schema.StringMap(schema.Any()), "enqueued": schema.Time(), "started": schema.Time(), "completed": schema.Time(), "status": schema.String(), "message": schema.String(), "results": schema.StringMap(schema.Any()), "id": schema.String(), } // Some values don't have to be there. defaults := schema.Defaults{ "started": time.Time{}, "completed": time.Time{}, } checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "action v1 schema check failed") } valid := coerced.(map[string]interface{}) action := &action{ Id_: valid["id"].(string), Receiver_: valid["receiver"].(string), Name_: valid["name"].(string), Status_: valid["status"].(string), Message_: valid["message"].(string), Parameters_: valid["parameters"].(map[string]interface{}), Enqueued_: valid["enqueued"].(time.Time).UTC(), Results_: valid["results"].(map[string]interface{}), } started := valid["started"].(time.Time) if !started.IsZero() { started = started.UTC() action.Started_ = &started } completed := valid["completed"].(time.Time) if !started.IsZero() { completed = completed.UTC() action.Completed_ = &completed } return action, nil }
func importStatusV1(source map[string]interface{}) (StatusPoint_, error) { fields := schema.Fields{ "value": schema.String(), "message": schema.String(), "data": schema.StringMap(schema.Any()), "updated": schema.Time(), } // Some values don't have to be there. defaults := schema.Defaults{ "message": "", "data": schema.Omit, } checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return StatusPoint_{}, errors.Annotatef(err, "status v1 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 data map[string]interface{} if sourceData, set := valid["data"]; set { data = sourceData.(map[string]interface{}) } return StatusPoint_{ Value_: valid["value"].(string), Message_: valid["message"].(string), Data_: data, Updated_: valid["updated"].(time.Time), }, nil }
func (s *S) TestStringified(c *gc.C) { s.sch = schema.Stringified() out, err := s.sch.Coerce(true, aPath) c.Assert(err, gc.IsNil) c.Check(out, gc.Equals, "true") out, err = s.sch.Coerce(10, aPath) c.Assert(err, gc.IsNil) c.Check(out, gc.Equals, "10") out, err = s.sch.Coerce(1.1, aPath) c.Assert(err, gc.IsNil) c.Check(out, gc.Equals, "1.1") out, err = s.sch.Coerce("spam", aPath) c.Assert(err, gc.IsNil) c.Check(out, gc.Equals, "spam") _, err = s.sch.Coerce(map[string]string{}, aPath) c.Check(err, gc.ErrorMatches, ".* unexpected value .*") _, err = s.sch.Coerce([]string{}, aPath) c.Check(err, gc.ErrorMatches, ".* unexpected value .*") s.sch = schema.Stringified(schema.StringMap(schema.String())) out, err = s.sch.Coerce(map[string]string{"a": "b"}, aPath) c.Assert(err, gc.IsNil) c.Check(out, gc.Equals, `map[string]string{"a":"b"}`) }
func importOpenedPortsV1(source map[string]interface{}) (*openedPorts, error) { fields := schema.Fields{ "subnet-id": schema.String(), "opened-ports": schema.StringMap(schema.Any()), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "opened-ports v1 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. ports, err := importPortRanges(valid["opened-ports"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result := &openedPorts{ SubnetID_: valid["subnet-id"].(string), } result.setOpenedPorts(ports) return result, nil }
func versionedEmbeddedChecker(name string) schema.Checker { fields := schema.Fields{ "version": schema.Int(), } fields[name] = schema.StringMap(schema.Any()) return schema.FieldMap(fields, nil) // no defaults }
func space_2_0(source map[string]interface{}) (*space, error) { fields := schema.Fields{ "resource_uri": schema.String(), "id": schema.ForceInt(), "name": schema.String(), "subnets": schema.List(schema.StringMap(schema.Any())), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "space 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. subnets, err := readSubnetList(valid["subnets"].([]interface{}), subnet_2_0) if err != nil { return nil, errors.Trace(err) } result := &space{ resourceURI: valid["resource_uri"].(string), id: valid["id"].(int), name: valid["name"].(string), subnets: subnets, } return result, nil }
func importRelationV1(source map[string]interface{}) (*relation, error) { fields := schema.Fields{ "id": schema.Int(), "key": schema.String(), "endpoints": schema.StringMap(schema.Any()), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "relation v1 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. result := &relation{ Id_: int(valid["id"].(int64)), Key_: valid["key"].(string), } endpoints, err := importEndpoints(valid["endpoints"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.setEndpoints(endpoints) return result, nil }
func (s *S) TestStringMap(c *gc.C) { s.sch = schema.StringMap(schema.Int()) out, err := s.sch.Coerce(map[string]interface{}{"a": 1, "b": int8(2)}, aPath) c.Assert(err, gc.IsNil) c.Assert(out, gc.DeepEquals, map[string]interface{}{"a": int64(1), "b": int64(2)}) out, err = s.sch.Coerce(42, aPath) c.Assert(out, gc.IsNil) c.Assert(err, gc.ErrorMatches, "<path>: expected map, got int\\(42\\)") out, err = s.sch.Coerce(nil, aPath) c.Assert(out, gc.IsNil) c.Assert(err, gc.ErrorMatches, "<path>: expected map, got nothing") out, err = s.sch.Coerce(map[int]int{1: 1}, aPath) c.Assert(out, gc.IsNil) c.Assert(err, gc.ErrorMatches, "<path>: expected string, got int\\(1\\)") out, err = s.sch.Coerce(map[string]bool{"a": true}, aPath) c.Assert(out, gc.IsNil) c.Assert(err, gc.ErrorMatches, `<path>\.a: expected int, got bool\(true\)`) // First path entry shouldn't have dots in an error message. out, err = s.sch.Coerce(map[string]bool{"a": true}, nil) c.Assert(out, gc.IsNil) c.Assert(err, gc.ErrorMatches, `a: expected int, got bool\(true\)`) }
func device_2_0(source map[string]interface{}) (*device, error) { fields := schema.Fields{ "resource_uri": schema.String(), "system_id": schema.String(), "hostname": schema.String(), "fqdn": schema.String(), "parent": schema.String(), "owner": schema.String(), "ip_addresses": schema.List(schema.String()), "interface_set": schema.List(schema.StringMap(schema.Any())), "zone": schema.StringMap(schema.Any()), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, WrapWithDeserializationError(err, "device 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. interfaceSet, err := readInterfaceList(valid["interface_set"].([]interface{}), interface_2_0) if err != nil { return nil, errors.Trace(err) } zone, err := zone_2_0(valid["zone"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result := &device{ resourceURI: valid["resource_uri"].(string), systemID: valid["system_id"].(string), hostname: valid["hostname"].(string), fqdn: valid["fqdn"].(string), parent: valid["parent"].(string), owner: valid["owner"].(string), ipAddresses: convertToStringSlice(valid["ip_addresses"]), interfaceSet: interfaceSet, zone: zone, } return result, nil }
func versionedChecker(name string) schema.Checker { fields := schema.Fields{ "version": schema.Int(), } if name != "" { fields[name] = schema.List(schema.StringMap(schema.Any())) } return schema.FieldMap(fields, nil) // no defaults }
func importEndpointV1(source map[string]interface{}) (*endpoint, error) { fields := schema.Fields{ "service-name": schema.String(), "name": schema.String(), "role": schema.String(), "interface": schema.String(), "optional": schema.Bool(), "limit": schema.Int(), "scope": schema.String(), "unit-settings": schema.StringMap(schema.StringMap(schema.Any())), } checker := schema.FieldMap(fields, nil) // No defaults. coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "endpoint v1 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. result := &endpoint{ ServiceName_: valid["service-name"].(string), Name_: valid["name"].(string), Role_: valid["role"].(string), Interface_: valid["interface"].(string), Optional_: valid["optional"].(bool), Limit_: int(valid["limit"].(int64)), Scope_: valid["scope"].(string), UnitSettings_: make(map[string]map[string]interface{}), } for unitname, settings := range valid["unit-settings"].(map[string]interface{}) { result.UnitSettings_[unitname] = settings.(map[string]interface{}) } return result, nil }
func readMachines(controllerVersion version.Number, source interface{}) ([]*machine, error) { readFunc, err := getMachineDeserializationFunc(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, "machine base schema check failed") } valid := coerced.([]interface{}) return readMachineList(valid, readFunc) }
func readFile(controllerVersion version.Number, source interface{}) (*file, error) { readFunc, err := getFileDeserializationFunc(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, "file base schema check failed") } valid := coerced.(map[string]interface{}) return readFunc(valid) }
func blockdevice_2_0(source map[string]interface{}) (*blockdevice, error) { fields := schema.Fields{ "resource_uri": schema.String(), "id": schema.ForceInt(), "name": schema.String(), "model": schema.String(), "path": schema.String(), "used_for": schema.String(), "tags": schema.List(schema.String()), "block_size": schema.ForceUint(), "used_size": schema.ForceUint(), "size": schema.ForceUint(), "partitions": schema.List(schema.StringMap(schema.Any())), } checker := schema.FieldMap(fields, nil) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, WrapWithDeserializationError(err, "blockdevice 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. partitions, err := readPartitionList(valid["partitions"].([]interface{}), partition_2_0) if err != nil { return nil, errors.Trace(err) } result := &blockdevice{ resourceURI: valid["resource_uri"].(string), id: valid["id"].(int), name: valid["name"].(string), model: valid["model"].(string), path: valid["path"].(string), usedFor: valid["used_for"].(string), tags: convertToStringSlice(valid["tags"]), blockSize: valid["block_size"].(uint64), usedSize: valid["used_size"].(uint64), size: valid["size"].(uint64), partitions: partitions, } return result, nil }
func subnet_2_0(source map[string]interface{}) (*subnet, error) { fields := schema.Fields{ "resource_uri": schema.String(), "id": schema.ForceInt(), "name": schema.String(), "space": schema.String(), "gateway_ip": schema.OneOf(schema.Nil(""), schema.String()), "cidr": schema.String(), "vlan": schema.StringMap(schema.Any()), "dns_servers": schema.OneOf(schema.Nil(""), schema.List(schema.String())), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "subnet 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. vlan, err := vlan_2_0(valid["vlan"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } // Since the gateway_ip is optional, we use the two part cast assignment. If // the cast fails, then we get the default value we care about, which is the // empty string. gateway, _ := valid["gateway_ip"].(string) result := &subnet{ resourceURI: valid["resource_uri"].(string), id: valid["id"].(int), name: valid["name"].(string), space: valid["space"].(string), vlan: vlan, gateway: gateway, cidr: valid["cidr"].(string), dnsServers: convertToStringSlice(valid["dns_servers"]), } return result, nil }
func readVLANs(controllerVersion version.Number, source interface{}) ([]*vlan, error) { checker := schema.List(schema.StringMap(schema.Any())) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "vlan base schema check failed") } valid := coerced.([]interface{}) var deserialisationVersion version.Number for v := range vlanDeserializationFuncs { if v.Compare(deserialisationVersion) > 0 && v.Compare(controllerVersion) <= 0 { deserialisationVersion = v } } if deserialisationVersion == version.Zero { return nil, errors.Errorf("no vlan read func for version %s", controllerVersion) } readFunc := vlanDeserializationFuncs[deserialisationVersion] return readVLANList(valid, readFunc) }
func readBootResources(controllerVersion version.Number, source interface{}) ([]*bootResource, error) { checker := schema.List(schema.StringMap(schema.Any())) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, WrapWithDeserializationError(err, "boot resource base schema check failed") } valid := coerced.([]interface{}) var deserialisationVersion version.Number for v := range bootResourceDeserializationFuncs { if v.Compare(deserialisationVersion) > 0 && v.Compare(controllerVersion) <= 0 { deserialisationVersion = v } } if deserialisationVersion == version.Zero { return nil, NewUnsupportedVersionError("no boot resource read func for version %s", controllerVersion) } readFunc := bootResourceDeserializationFuncs[deserialisationVersion] return readBootResourceList(valid, readFunc) }
func partition_2_0(source map[string]interface{}) (*partition, error) { fields := schema.Fields{ "resource_uri": schema.String(), "id": schema.ForceInt(), "path": schema.String(), "uuid": schema.String(), "used_for": schema.String(), "size": schema.ForceUint(), "filesystem": schema.OneOf(schema.Nil(""), schema.StringMap(schema.Any())), } checker := schema.FieldMap(fields, nil) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, WrapWithDeserializationError(err, "partition 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 filesystem *filesystem if fsSource := valid["filesystem"]; fsSource != nil { filesystem, err = filesystem2_0(fsSource.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } } result := &partition{ resourceURI: valid["resource_uri"].(string), id: valid["id"].(int), path: valid["path"].(string), uuid: valid["uuid"].(string), usedFor: valid["used_for"].(string), size: valid["size"].(uint64), filesystem: filesystem, } return result, nil }
func (c cloudCredentialChecker) Coerce(v interface{}, path []string) (interface{}, error) { out := CloudCredential{ AuthCredentials: make(map[string]Credential), } v, err := schema.StringMap(cloudCredentialValueChecker{}).Coerce(v, path) if err != nil { return nil, err } mapv := v.(map[string]interface{}) for k, v := range mapv { switch k { case "default-region": out.DefaultRegion = v.(string) case "default-credential": out.DefaultCredential = v.(string) default: out.AuthCredentials[k] = v.(Credential) } } return out, nil }
func (c cloudCredentialValueChecker) Coerce(v interface{}, path []string) (interface{}, error) { field := path[len(path)-1] switch field { case "default-region", "default-credential": return schema.String().Coerce(v, path) } v, err := schema.StringMap(schema.String()).Coerce(v, path) if err != nil { return nil, err } mapv := v.(map[string]interface{}) authType, _ := mapv["auth-type"].(string) if authType == "" { return nil, errors.Errorf("%v: missing auth-type", strings.Join(path, "")) } attrs := make(map[string]string) delete(mapv, "auth-type") for k, v := range mapv { attrs[k] = v.(string) } return Credential{authType: AuthType(authType), attributes: attrs}, nil }
func importStoragePoolV1(source map[string]interface{}) (*storagepool, error) { fields := schema.Fields{ "name": schema.String(), "provider": schema.String(), "attributes": schema.StringMap(schema.Any()), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "storagepool v1 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. result := &storagepool{ Name_: valid["name"].(string), Provider_: valid["provider"].(string), Attributes_: valid["attributes"].(map[string]interface{}), } return result, nil }
func fabric_2_0(source map[string]interface{}) (*fabric, error) { fields := schema.Fields{ "resource_uri": schema.String(), "id": schema.ForceInt(), "name": schema.String(), "class_type": schema.OneOf(schema.Nil(""), schema.String()), "vlans": schema.List(schema.StringMap(schema.Any())), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "fabric 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. vlans, err := readVLANList(valid["vlans"].([]interface{}), vlan_2_0) if err != nil { return nil, errors.Trace(err) } // Since the class_type is optional, we use the two part cast assignment. If // the cast fails, then we get the default value we care about, which is the // empty string. classType, _ := valid["class_type"].(string) result := &fabric{ resourceURI: valid["resource_uri"].(string), id: valid["id"].(int), name: valid["name"].(string), classType: classType, vlans: vlans, } return result, nil }
func importMachineV1(source map[string]interface{}) (*machine, error) { fields := schema.Fields{ "id": schema.String(), "nonce": schema.String(), "password-hash": schema.String(), "placement": schema.String(), "instance": schema.StringMap(schema.Any()), "series": schema.String(), "container-type": schema.String(), "jobs": schema.List(schema.String()), "status": schema.StringMap(schema.Any()), "supported-containers": schema.List(schema.String()), "tools": schema.StringMap(schema.Any()), "containers": schema.List(schema.StringMap(schema.Any())), "opened-ports": schema.StringMap(schema.Any()), "provider-addresses": schema.List(schema.StringMap(schema.Any())), "machine-addresses": schema.List(schema.StringMap(schema.Any())), "preferred-public-address": schema.StringMap(schema.Any()), "preferred-private-address": schema.StringMap(schema.Any()), "block-devices": schema.StringMap(schema.Any()), } defaults := schema.Defaults{ "placement": "", "container-type": "", // Even though we are expecting instance data for every machine, // it isn't strictly necessary, so we allow it to not exist here. "instance": schema.Omit, "supported-containers": schema.Omit, "opened-ports": schema.Omit, "block-devices": schema.Omit, "provider-addresses": schema.Omit, "machine-addresses": schema.Omit, "preferred-public-address": schema.Omit, "preferred-private-address": schema.Omit, } addAnnotationSchema(fields, defaults) addConstraintsSchema(fields, defaults) addStatusHistorySchema(fields) checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "machine v1 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. result := &machine{ Id_: valid["id"].(string), Nonce_: valid["nonce"].(string), PasswordHash_: valid["password-hash"].(string), Placement_: valid["placement"].(string), Series_: valid["series"].(string), ContainerType_: valid["container-type"].(string), StatusHistory_: newStatusHistory(), Jobs_: convertToStringSlice(valid["jobs"]), } result.importAnnotations(valid) if err := result.importStatusHistory(valid); err != nil { return nil, errors.Trace(err) } if constraintsMap, ok := valid["constraints"]; ok { constraints, err := importConstraints(constraintsMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Constraints_ = constraints } if supported, ok := valid["supported-containers"]; ok { supportedList := supported.([]interface{}) s := make([]string, len(supportedList)) for i, containerType := range supportedList { s[i] = containerType.(string) } result.SupportedContainers_ = &s } if instanceMap, ok := valid["instance"]; ok { instance, err := importCloudInstance(instanceMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Instance_ = instance } if blockDeviceMap, ok := valid["block-devices"]; ok { devices, err := importBlockDevices(blockDeviceMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.setBlockDevices(devices) } else { result.setBlockDevices(nil) } // Tools and status are required, so we expect them to be there. tools, err := importAgentTools(valid["tools"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Tools_ = tools status, err := importStatus(valid["status"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Status_ = status if addresses, ok := valid["provider-addresses"]; ok { providerAddresses, err := importAddresses(addresses.([]interface{})) if err != nil { return nil, errors.Trace(err) } result.ProviderAddresses_ = providerAddresses } if addresses, ok := valid["machine-addresses"]; ok { machineAddresses, err := importAddresses(addresses.([]interface{})) if err != nil { return nil, errors.Trace(err) } result.MachineAddresses_ = machineAddresses } if address, ok := valid["preferred-public-address"]; ok { publicAddress, err := importAddress(address.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.PreferredPublicAddress_ = publicAddress } if address, ok := valid["preferred-private-address"]; ok { privateAddress, err := importAddress(address.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.PreferredPrivateAddress_ = privateAddress } machineList := valid["containers"].([]interface{}) machines, err := importMachineList(machineList, importMachineV1) if err != nil { return nil, errors.Annotatef(err, "containers") } result.Containers_ = machines if portsMap, ok := valid["opened-ports"]; ok { portsList, err := importOpenedPorts(portsMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.setOpenedPorts(portsList) } return result, nil }
func importModelV1(source map[string]interface{}) (*model, error) { fields := schema.Fields{ "owner": schema.String(), "config": schema.StringMap(schema.Any()), "latest-tools": schema.String(), "blocks": schema.StringMap(schema.String()), "users": schema.StringMap(schema.Any()), "machines": schema.StringMap(schema.Any()), "services": schema.StringMap(schema.Any()), "relations": schema.StringMap(schema.Any()), "sequences": schema.StringMap(schema.Int()), } // Some values don't have to be there. defaults := schema.Defaults{ "latest-tools": schema.Omit, "blocks": schema.Omit, } addAnnotationSchema(fields, defaults) addConstraintsSchema(fields, defaults) checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "model v1 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. result := &model{ Version: 1, Owner_: valid["owner"].(string), Config_: valid["config"].(map[string]interface{}), Sequences_: make(map[string]int), Blocks_: convertToStringMap(valid["blocks"]), } result.importAnnotations(valid) sequences := valid["sequences"].(map[string]interface{}) for key, value := range sequences { result.SetSequence(key, int(value.(int64))) } if constraintsMap, ok := valid["constraints"]; ok { constraints, err := importConstraints(constraintsMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Constraints_ = constraints } if availableTools, ok := valid["latest-tools"]; ok { num, err := version.Parse(availableTools.(string)) if err != nil { return nil, errors.Trace(err) } result.LatestToolsVersion_ = num } userMap := valid["users"].(map[string]interface{}) users, err := importUsers(userMap) if err != nil { return nil, errors.Annotate(err, "users") } result.setUsers(users) machineMap := valid["machines"].(map[string]interface{}) machines, err := importMachines(machineMap) if err != nil { return nil, errors.Annotate(err, "machines") } result.setMachines(machines) serviceMap := valid["services"].(map[string]interface{}) services, err := importServices(serviceMap) if err != nil { return nil, errors.Annotate(err, "services") } result.setServices(services) relationMap := valid["relations"].(map[string]interface{}) relations, err := importRelations(relationMap) if err != nil { return nil, errors.Annotate(err, "relations") } result.setRelations(relations) return result, nil }
func importVolumeV1(source map[string]interface{}) (*volume, error) { fields := schema.Fields{ "id": schema.String(), "storage-id": schema.String(), "binding": schema.String(), "provisioned": schema.Bool(), "size": schema.ForceUint(), "pool": schema.String(), "hardware-id": schema.String(), "volume-id": schema.String(), "persistent": schema.Bool(), "status": schema.StringMap(schema.Any()), "attachments": schema.StringMap(schema.Any()), } defaults := schema.Defaults{ "storage-id": "", "binding": "", "pool": "", "hardware-id": "", "volume-id": "", "attachments": schema.Omit, } addStatusHistorySchema(fields) checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "volume v1 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. result := &volume{ ID_: valid["id"].(string), StorageID_: valid["storage-id"].(string), Binding_: valid["binding"].(string), Provisioned_: valid["provisioned"].(bool), Size_: valid["size"].(uint64), Pool_: valid["pool"].(string), HardwareID_: valid["hardware-id"].(string), VolumeID_: valid["volume-id"].(string), Persistent_: valid["persistent"].(bool), StatusHistory_: newStatusHistory(), } if err := result.importStatusHistory(valid); err != nil { return nil, errors.Trace(err) } status, err := importStatus(valid["status"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Status_ = status attachments, err := importVolumeAttachments(valid["attachments"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.setAttachments(attachments) return result, nil }
func machine_2_0(source map[string]interface{}) (*machine, error) { fields := schema.Fields{ "resource_uri": schema.String(), "system_id": schema.String(), "hostname": schema.String(), "fqdn": schema.String(), "tag_names": schema.List(schema.String()), "osystem": schema.String(), "distro_series": schema.String(), "architecture": schema.String(), "memory": schema.ForceInt(), "cpu_count": schema.ForceInt(), "ip_addresses": schema.List(schema.String()), "power_state": schema.String(), "status_name": schema.String(), "status_message": schema.String(), "boot_interface": schema.StringMap(schema.Any()), "interface_set": schema.List(schema.StringMap(schema.Any())), "zone": schema.StringMap(schema.Any()), "physicalblockdevice_set": schema.List(schema.StringMap(schema.Any())), "blockdevice_set": schema.List(schema.StringMap(schema.Any())), } checker := schema.FieldMap(fields, nil) // no defaults coerced, err := checker.Coerce(source, nil) if err != nil { return nil, WrapWithDeserializationError(err, "machine 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. bootInterface, err := interface_2_0(valid["boot_interface"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } interfaceSet, err := readInterfaceList(valid["interface_set"].([]interface{}), interface_2_0) if err != nil { return nil, errors.Trace(err) } zone, err := zone_2_0(valid["zone"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } physicalBlockDevices, err := readBlockDeviceList(valid["physicalblockdevice_set"].([]interface{}), blockdevice_2_0) if err != nil { return nil, errors.Trace(err) } blockDevices, err := readBlockDeviceList(valid["blockdevice_set"].([]interface{}), blockdevice_2_0) if err != nil { return nil, errors.Trace(err) } result := &machine{ resourceURI: valid["resource_uri"].(string), systemID: valid["system_id"].(string), hostname: valid["hostname"].(string), fqdn: valid["fqdn"].(string), tags: convertToStringSlice(valid["tag_names"]), operatingSystem: valid["osystem"].(string), distroSeries: valid["distro_series"].(string), architecture: valid["architecture"].(string), memory: valid["memory"].(int), cpuCount: valid["cpu_count"].(int), ipAddresses: convertToStringSlice(valid["ip_addresses"]), powerState: valid["power_state"].(string), statusName: valid["status_name"].(string), statusMessage: valid["status_message"].(string), bootInterface: bootInterface, interfaceSet: interfaceSet, zone: zone, physicalBlockDevices: physicalBlockDevices, blockDevices: blockDevices, } return result, nil }
func importServiceV1(source map[string]interface{}) (*service, error) { fields := schema.Fields{ "name": schema.String(), "series": schema.String(), "subordinate": schema.Bool(), "charm-url": schema.String(), "cs-channel": schema.String(), "charm-mod-version": schema.Int(), "force-charm": schema.Bool(), "exposed": schema.Bool(), "min-units": schema.Int(), "status": schema.StringMap(schema.Any()), "settings": schema.StringMap(schema.Any()), "settings-refcount": schema.Int(), "leader": schema.String(), "leadership-settings": schema.StringMap(schema.Any()), "metrics-creds": schema.String(), "units": schema.StringMap(schema.Any()), } defaults := schema.Defaults{ "subordinate": false, "force-charm": false, "exposed": false, "min-units": int64(0), "leader": "", "metrics-creds": "", } addAnnotationSchema(fields, defaults) addConstraintsSchema(fields, defaults) addStatusHistorySchema(fields) checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "service v1 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. result := &service{ Name_: valid["name"].(string), Series_: valid["series"].(string), Subordinate_: valid["subordinate"].(bool), CharmURL_: valid["charm-url"].(string), Channel_: valid["cs-channel"].(string), CharmModifiedVersion_: int(valid["charm-mod-version"].(int64)), ForceCharm_: valid["force-charm"].(bool), Exposed_: valid["exposed"].(bool), MinUnits_: int(valid["min-units"].(int64)), Settings_: valid["settings"].(map[string]interface{}), SettingsRefCount_: int(valid["settings-refcount"].(int64)), Leader_: valid["leader"].(string), LeadershipSettings_: valid["leadership-settings"].(map[string]interface{}), StatusHistory_: newStatusHistory(), } result.importAnnotations(valid) if err := result.importStatusHistory(valid); err != nil { return nil, errors.Trace(err) } if constraintsMap, ok := valid["constraints"]; ok { constraints, err := importConstraints(constraintsMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Constraints_ = constraints } encodedCreds := valid["metrics-creds"].(string) // The model stores the creds encoded, but we want to make sure that // we are storing something that can be decoded. if _, err := base64.StdEncoding.DecodeString(encodedCreds); err != nil { return nil, errors.Annotate(err, "metrics credentials not valid") } result.MetricsCredentials_ = encodedCreds status, err := importStatus(valid["status"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Status_ = status units, err := importUnits(valid["units"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.setUnits(units) return result, nil }
func importModelV1(source map[string]interface{}) (*model, error) { fields := schema.Fields{ "owner": schema.String(), "cloud": schema.String(), "cloud-region": schema.String(), "config": schema.StringMap(schema.Any()), "latest-tools": schema.String(), "blocks": schema.StringMap(schema.String()), "users": schema.StringMap(schema.Any()), "machines": schema.StringMap(schema.Any()), "applications": schema.StringMap(schema.Any()), "relations": schema.StringMap(schema.Any()), "ssh-host-keys": schema.StringMap(schema.Any()), "cloud-image-metadata": schema.StringMap(schema.Any()), "actions": schema.StringMap(schema.Any()), "ip-addresses": schema.StringMap(schema.Any()), "spaces": schema.StringMap(schema.Any()), "subnets": schema.StringMap(schema.Any()), "link-layer-devices": schema.StringMap(schema.Any()), "volumes": schema.StringMap(schema.Any()), "filesystems": schema.StringMap(schema.Any()), "storages": schema.StringMap(schema.Any()), "storage-pools": schema.StringMap(schema.Any()), "sequences": schema.StringMap(schema.Int()), } // Some values don't have to be there. defaults := schema.Defaults{ "latest-tools": schema.Omit, "blocks": schema.Omit, "cloud-region": schema.Omit, } addAnnotationSchema(fields, defaults) addConstraintsSchema(fields, defaults) checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "model v1 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. result := &model{ Version: 1, Owner_: valid["owner"].(string), Config_: valid["config"].(map[string]interface{}), Sequences_: make(map[string]int), Blocks_: convertToStringMap(valid["blocks"]), Cloud_: valid["cloud"].(string), } result.importAnnotations(valid) sequences := valid["sequences"].(map[string]interface{}) for key, value := range sequences { result.SetSequence(key, int(value.(int64))) } if constraintsMap, ok := valid["constraints"]; ok { constraints, err := importConstraints(constraintsMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Constraints_ = constraints } if availableTools, ok := valid["latest-tools"]; ok { num, err := version.Parse(availableTools.(string)) if err != nil { return nil, errors.Trace(err) } result.LatestToolsVersion_ = num } if region, ok := valid["cloud-region"]; ok { result.CloudRegion_ = region.(string) } if credential, ok := valid["cloud-credential"]; ok { result.CloudCredential_ = credential.(string) } userMap := valid["users"].(map[string]interface{}) users, err := importUsers(userMap) if err != nil { return nil, errors.Annotate(err, "users") } result.setUsers(users) machineMap := valid["machines"].(map[string]interface{}) machines, err := importMachines(machineMap) if err != nil { return nil, errors.Annotate(err, "machines") } result.setMachines(machines) applicationMap := valid["applications"].(map[string]interface{}) applications, err := importApplications(applicationMap) if err != nil { return nil, errors.Annotate(err, "applications") } result.setApplications(applications) relationMap := valid["relations"].(map[string]interface{}) relations, err := importRelations(relationMap) if err != nil { return nil, errors.Annotate(err, "relations") } result.setRelations(relations) spaceMap := valid["spaces"].(map[string]interface{}) spaces, err := importSpaces(spaceMap) if err != nil { return nil, errors.Annotate(err, "spaces") } result.setSpaces(spaces) deviceMap := valid["link-layer-devices"].(map[string]interface{}) devices, err := importLinkLayerDevices(deviceMap) if err != nil { return nil, errors.Annotate(err, "link-layer-devices") } result.setLinkLayerDevices(devices) subnetsMap := valid["subnets"].(map[string]interface{}) subnets, err := importSubnets(subnetsMap) if err != nil { return nil, errors.Annotate(err, "subnets") } result.setSubnets(subnets) addressMap := valid["ip-addresses"].(map[string]interface{}) addresses, err := importIPAddresses(addressMap) if err != nil { return nil, errors.Annotate(err, "ip-addresses") } result.setIPAddresses(addresses) sshHostKeyMap := valid["ssh-host-keys"].(map[string]interface{}) hostKeys, err := importSSHHostKeys(sshHostKeyMap) if err != nil { return nil, errors.Annotate(err, "ssh-host-keys") } result.setSSHHostKeys(hostKeys) cloudimagemetadataMap := valid["cloud-image-metadata"].(map[string]interface{}) cloudimagemetadata, err := importCloudImageMetadata(cloudimagemetadataMap) if err != nil { return nil, errors.Annotate(err, "cloud-image-metadata") } result.setCloudImageMetadatas(cloudimagemetadata) actionsMap := valid["actions"].(map[string]interface{}) actions, err := importActions(actionsMap) if err != nil { return nil, errors.Annotate(err, "actions") } result.setActions(actions) volumes, err := importVolumes(valid["volumes"].(map[string]interface{})) if err != nil { return nil, errors.Annotate(err, "volumes") } result.setVolumes(volumes) filesystems, err := importFilesystems(valid["filesystems"].(map[string]interface{})) if err != nil { return nil, errors.Annotate(err, "filesystems") } result.setFilesystems(filesystems) storages, err := importStorages(valid["storages"].(map[string]interface{})) if err != nil { return nil, errors.Annotate(err, "storages") } result.setStorages(storages) pools, err := importStoragePools(valid["storage-pools"].(map[string]interface{})) if err != nil { return nil, errors.Annotate(err, "storage-pools") } result.setStoragePools(pools) return result, nil }
func importUnitV1(source map[string]interface{}) (*unit, error) { fields := schema.Fields{ "name": schema.String(), "machine": schema.String(), "agent-status": schema.StringMap(schema.Any()), "agent-status-history": schema.StringMap(schema.Any()), "workload-status": schema.StringMap(schema.Any()), "workload-status-history": schema.StringMap(schema.Any()), "principal": schema.String(), "subordinates": schema.List(schema.String()), "password-hash": schema.String(), "tools": schema.StringMap(schema.Any()), "meter-status-code": schema.String(), "meter-status-info": schema.String(), } defaults := schema.Defaults{ "principal": "", "subordinates": schema.Omit, "meter-status-code": "", "meter-status-info": "", } addAnnotationSchema(fields, defaults) addConstraintsSchema(fields, defaults) checker := schema.FieldMap(fields, defaults) coerced, err := checker.Coerce(source, nil) if err != nil { return nil, errors.Annotatef(err, "unit v1 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. result := &unit{ Name_: valid["name"].(string), Machine_: valid["machine"].(string), Principal_: valid["principal"].(string), PasswordHash_: valid["password-hash"].(string), MeterStatusCode_: valid["meter-status-code"].(string), MeterStatusInfo_: valid["meter-status-info"].(string), WorkloadStatusHistory_: newStatusHistory(), AgentStatusHistory_: newStatusHistory(), } result.importAnnotations(valid) workloadHistory := valid["workload-status-history"].(map[string]interface{}) if err := importStatusHistory(&result.WorkloadStatusHistory_, workloadHistory); err != nil { return nil, errors.Trace(err) } agentHistory := valid["agent-status-history"].(map[string]interface{}) if err := importStatusHistory(&result.AgentStatusHistory_, agentHistory); err != nil { return nil, errors.Trace(err) } if constraintsMap, ok := valid["constraints"]; ok { constraints, err := importConstraints(constraintsMap.(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Constraints_ = constraints } result.Subordinates_ = convertToStringSlice(valid["subordinates"]) // Tools and status are required, so we expect them to be there. tools, err := importAgentTools(valid["tools"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.Tools_ = tools agentStatus, err := importStatus(valid["agent-status"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.AgentStatus_ = agentStatus workloadStatus, err := importStatus(valid["workload-status"].(map[string]interface{})) if err != nil { return nil, errors.Trace(err) } result.WorkloadStatus_ = workloadStatus return result, nil }