// MergeServicesV1 merges a v1 compose file into an existing set of service configs
func MergeServicesV1(existingServices *ServiceConfigs, environmentLookup EnvironmentLookup, resourceLookup ResourceLookup, file string, datas RawServiceMap, options *ParseOptions) (map[string]*ServiceConfigV1, error) {
	if options.Interpolate {
		if err := Interpolate(environmentLookup, &datas); err != nil {
			return nil, err
		}
	}

	if options.Preprocess != nil {
		var err error
		datas, err = options.Preprocess(datas)
		if err != nil {
			return nil, err
		}
	}

	if options.Validate {
		if err := validate(datas); err != nil {
			return nil, err
		}
	}

	for name, data := range datas {
		data, err := parseV1(resourceLookup, environmentLookup, file, data, datas, options)
		if err != nil {
			logrus.Errorf("Failed to parse service %s: %v", name, err)
			return nil, err
		}

		if serviceConfig, ok := existingServices.Get(name); ok {
			var rawExistingService RawService
			if err := utils.Convert(serviceConfig, &rawExistingService); err != nil {
				return nil, err
			}

			data = mergeConfig(rawExistingService, data)
		}

		datas[name] = data
	}

	if options.Validate {
		for name, data := range datas {
			err := validateServiceConstraints(data, name)
			if err != nil {
				return nil, err
			}
		}
	}

	serviceConfigs := make(map[string]*ServiceConfigV1)
	if err := utils.Convert(datas, &serviceConfigs); err != nil {
		return nil, err
	}

	return serviceConfigs, nil
}
Exemple #2
0
// MergeServices merges a compose file into an existing set of service configs
func MergeServices(existingServices *Configs, environmentLookup EnvironmentLookup, resourceLookup ResourceLookup, file string, bytes []byte) (map[string]*ServiceConfig, error) {
	configs := make(map[string]*ServiceConfig)

	datas := make(RawServiceMap)
	if err := yaml.Unmarshal(bytes, &datas); err != nil {
		return nil, err
	}

	if err := Interpolate(environmentLookup, &datas); err != nil {
		return nil, err
	}

	if err := validate(datas); err != nil {
		return nil, err
	}

	for name, data := range datas {
		data, err := parse(resourceLookup, environmentLookup, file, data, datas)
		if err != nil {
			logrus.Errorf("Failed to parse service %s: %v", name, err)
			return nil, err
		}

		if serviceConfig, ok := existingServices.Get(name); ok {
			var rawExistingService RawService
			if err := utils.Convert(serviceConfig, &rawExistingService); err != nil {
				return nil, err
			}

			data = mergeConfig(rawExistingService, data)
		}

		datas[name] = data
	}

	for name, data := range datas {
		err := validateServiceConstraints(data, name)
		if err != nil {
			return nil, err
		}
	}

	if err := utils.Convert(datas, &configs); err != nil {
		return nil, err
	}

	adjustValues(configs)

	return configs, nil
}
Exemple #3
0
// MergeServicesV2 merges a v2 compose file into an existing set of service configs
func MergeServicesV2(existingServices *ServiceConfigs, environmentLookup EnvironmentLookup, resourceLookup ResourceLookup, file string, bytes []byte, options *ParseOptions) (map[string]*ServiceConfig, error) {
	var config Config
	if err := yaml.Unmarshal(bytes, &config); err != nil {
		return nil, err
	}

	datas := config.Services

	if options.Interpolate {
		if err := Interpolate(environmentLookup, &datas); err != nil {
			return nil, err
		}
	}

	if options.Preprocess != nil {
		var err error
		datas, err = options.Preprocess(datas)
		if err != nil {
			return nil, err
		}
	}

	for name, data := range datas {
		data, err := parseV2(resourceLookup, environmentLookup, file, data, datas, options)
		if err != nil {
			logrus.Errorf("Failed to parse service %s: %v", name, err)
			return nil, err
		}

		if serviceConfig, ok := existingServices.Get(name); ok {
			var rawExistingService RawService
			if err := utils.Convert(serviceConfig, &rawExistingService); err != nil {
				return nil, err
			}

			data = mergeConfig(rawExistingService, data)
		}

		datas[name] = data
	}

	serviceConfigs := make(map[string]*ServiceConfig)
	if err := utils.Convert(datas, &serviceConfigs); err != nil {
		return nil, err
	}

	return serviceConfigs, nil
}
func (c *Context) unmarshalBytes(composeBytes, bytes []byte) error {
	rawServiceMap := project.RawServiceMap{}
	if composeBytes != nil {
		if err := yaml.Unmarshal(composeBytes, &rawServiceMap); err != nil {
			return err
		}

		for key := range rawServiceMap {
			delete(rawServiceMap[key], "hostname")
		}
	}
	if bytes != nil {
		if err := yaml.Unmarshal(bytes, &rawServiceMap); err != nil {
			return err
		}
	}
	if err := project.Interpolate(c.EnvironmentLookup, &rawServiceMap); err != nil {
		return err
	}
	if err := utils.Convert(rawServiceMap, &c.RancherConfig); err != nil {
		return err
	}
	for _, v := range c.RancherConfig {
		rUtils.RemoveInterfaceKeys(v.Metadata)
	}
	return nil
}
Exemple #5
0
func (q *QuestionLookup) parse(file string) error {
	contents, err := ioutil.ReadFile(file)
	if os.IsNotExist(err) {
		return nil
	} else if err != nil {
		return err
	}

	data := map[string]map[string]interface{}{}
	if err := yaml.Unmarshal(contents, &data); err != nil {
		return err
	}

	rawQuestions := data[".catalog"]
	if rawQuestions != nil {
		var wrapper questionWrapper
		if err := utils.Convert(rawQuestions, &wrapper); err != nil {
			return err
		}

		for _, question := range wrapper.Questions {
			q.questions[question.Variable] = question
		}
	}

	return nil
}
func (q *QuestionLookup) parse(file string) error {
	contents, err := ioutil.ReadFile(file)
	if os.IsNotExist(err) {
		return nil
	} else if err != nil {
		return err
	}

	config, err := config.CreateConfig(contents)
	if err != nil {
		return err
	}
	data := config.Services

	rawQuestions := data[".catalog"]
	if rawQuestions != nil {
		var wrapper questionWrapper
		if err := utils.Convert(rawQuestions, &wrapper); err != nil {
			return err
		}

		for _, question := range wrapper.Questions {
			q.questions[question.Variable] = question
		}
	}

	return nil
}
func ParseCatalogConfig(contents []byte) (*model.RancherCompose, error) {
	cfg, err := config.CreateConfig(contents)
	if err != nil {
		return nil, err
	}
	var rawCatalogConfig interface{}

	if cfg.Version == "2" && cfg.Services[".catalog"] != nil {
		rawCatalogConfig = cfg.Services[".catalog"]
	}

	var data map[string]interface{}
	if err := yaml.Unmarshal(contents, &data); err != nil {
		return nil, err
	}

	if data["catalog"] != nil {
		rawCatalogConfig = data["catalog"]
	} else if data[".catalog"] != nil {
		rawCatalogConfig = data[".catalog"]
	}

	if rawCatalogConfig != nil {
		var catalogConfig model.RancherCompose
		if err := utils.Convert(rawCatalogConfig, &catalogConfig); err != nil {
			return nil, err
		}

		return &catalogConfig, nil
	}

	return &model.RancherCompose{}, nil
}
Exemple #8
0
func mergeProject(p *Project, bytes []byte) (map[string]*ServiceConfig, error) {
	configs := make(map[string]*ServiceConfig)

	datas := make(rawServiceMap)
	if err := yaml.Unmarshal(bytes, &datas); err != nil {
		return nil, err
	}

	if err := interpolate(p.context.EnvironmentLookup, &datas); err != nil {
		return nil, err
	}

	for name, data := range datas {
		data, err := parse(p.context.ConfigLookup, p.context.EnvironmentLookup, p.File, data, datas)
		if err != nil {
			logrus.Errorf("Failed to parse service %s: %v", name, err)
			return nil, err
		}

		datas[name] = data
	}

	if err := utils.Convert(datas, &configs); err != nil {
		return nil, err
	}

	adjustValues(configs)
	return configs, nil
}
Exemple #9
0
func createLaunchConfigs(r *RancherService) (rancherClient.LaunchConfig, []rancherClient.SecondaryLaunchConfig, error) {
	secondaryLaunchConfigs := []rancherClient.SecondaryLaunchConfig{}
	launchConfig, err := createLaunchConfig(r, r.Name(), r.Config())
	if err != nil {
		return launchConfig, nil, err
	}
	launchConfig.HealthCheck = r.HealthCheck("")

	if secondaries, ok := r.Context().SidekickInfo.primariesToSidekicks[r.Name()]; ok {
		for _, secondaryName := range secondaries {
			serviceConfig, ok := r.Context().Project.Configs[secondaryName]
			if !ok {
				return launchConfig, nil, fmt.Errorf("Failed to find sidekick: %s", secondaryName)
			}

			launchConfig, err := createLaunchConfig(r, secondaryName, serviceConfig)
			if err != nil {
				return launchConfig, nil, err
			}
			launchConfig.HealthCheck = r.HealthCheck(secondaryName)

			var secondaryLaunchConfig rancherClient.SecondaryLaunchConfig
			utils.Convert(launchConfig, &secondaryLaunchConfig)
			secondaryLaunchConfig.Name = secondaryName

			if secondaryLaunchConfig.Labels == nil {
				secondaryLaunchConfig.Labels = map[string]interface{}{}
			}
			secondaryLaunchConfigs = append(secondaryLaunchConfigs, secondaryLaunchConfig)
		}
	}

	return launchConfig, secondaryLaunchConfigs, nil
}
Exemple #10
0
func readEnvFile(configLookup ConfigLookup, inFile string, serviceData rawService) (rawService, error) {
	var config ServiceConfig

	if err := utils.Convert(serviceData, &config); err != nil {
		return nil, err
	}

	if len(config.EnvFile.Slice()) == 0 {
		return serviceData, nil
	}

	if configLookup == nil {
		return nil, fmt.Errorf("Can not use env_file in file %s no mechanism provided to load files", inFile)
	}

	vars := config.Environment.Slice()

	for i := len(config.EnvFile.Slice()) - 1; i >= 0; i-- {
		envFile := config.EnvFile.Slice()[i]
		content, _, err := configLookup.Lookup(envFile, inFile)
		if err != nil {
			return nil, err
		}

		if err != nil {
			return nil, err
		}

		scanner := bufio.NewScanner(bytes.NewBuffer(content))
		for scanner.Scan() {
			line := strings.TrimSpace(scanner.Text())
			key := strings.SplitAfter(line, "=")[0]

			found := false
			for _, v := range vars {
				if strings.HasPrefix(v, key) {
					found = true
					break
				}
			}

			if !found {
				vars = append(vars, line)
			}
		}

		if scanner.Err() != nil {
			return nil, scanner.Err()
		}
	}

	serviceData["environment"] = vars

	delete(serviceData, "env_file")

	return serviceData, nil
}
func (c *Context) unmarshalBytes(bytes []byte) error {
	rawServiceMap := project.RawServiceMap{}
	if err := yaml.Unmarshal(bytes, &rawServiceMap); err != nil {
		return err
	}
	if err := project.Interpolate(c.EnvironmentLookup, &rawServiceMap); err != nil {
		return err
	}
	return utils.Convert(rawServiceMap, &c.RancherConfig)
}
Exemple #12
0
func hashObj(obj interface{}) (string, error) {
	hash := sha1.New()

	mapObj := map[interface{}]interface{}{}
	if err := utils.Convert(obj, &mapObj); err != nil {
		return "", err
	}

	writeNativeMap(hash, mapObj)

	return hex.EncodeToString(hash.Sum(nil)), nil
}
//ExtractBindings gets bindings from created RawServiceMap
func ExtractBindings(yamlContent []byte) (BindingProperty, error) {
	var rawConfigDocker config.RawServiceMap
	var bindingsMap map[string]ServiceBinding
	var bindingPropertyMap BindingProperty
	var labels libYaml.SliceorMap

	config, err := config.CreateConfig(yamlContent)
	if err != nil {
		return nil, err
	}
	rawConfigDocker = config.Services

	preProcessServiceMap := preprocess.PreprocessServiceMap(nil)
	rawConfigDocker, err = preProcessServiceMap(rawConfigDocker)
	if err != nil {
		log.Errorf("Error during preprocess : %v\n", err)
		return nil, err
	}

	bindingsMap = make(map[string]ServiceBinding)
	bindingPropertyMap = make(map[string]interface{})

	for key := range rawConfigDocker {
		if _, serviceParsed := bindingsMap[key]; serviceParsed {
			log.Debugf("Service bindings already provided")
			continue
		}
		newServiceBinding := ServiceBinding{}

		newServiceBinding.Labels = MapLabel{}
		newServiceBinding.Ports = PortArray{}

		if rawConfigDocker[key]["labels"] != nil {
			err := utils.Convert(rawConfigDocker[key]["labels"], &labels)
			if err != nil {
				return nil, err
			}
			for k, v := range labels {
				newServiceBinding.Labels[k] = v
			}
		}
		if rawConfigDocker[key]["ports"] != nil {
			for _, port := range rawConfigDocker[key]["ports"].([]interface{}) {
				newServiceBinding.Ports = append(newServiceBinding.Ports, port)
			}
		}
		bindingsMap[key] = newServiceBinding
	}

	bindingPropertyMap["services"] = bindingsMap

	return bindingPropertyMap, nil
}
Exemple #14
0
// ParseNetworks parses networks in a compose file
func ParseNetworks(bytes []byte) (map[string]*NetworkConfig, error) {
	networkConfigs := make(map[string]*NetworkConfig)

	var config Config
	if err := yaml.Unmarshal(bytes, &config); err != nil {
		return nil, err
	}

	if err := utils.Convert(config.Networks, &networkConfigs); err != nil {
		return nil, err
	}

	return networkConfigs, nil
}
Exemple #15
0
// ParseVolumes parses volumes in a compose file
func ParseVolumes(bytes []byte) (map[string]*VolumeConfig, error) {
	volumeConfigs := make(map[string]*VolumeConfig)

	var config Config
	if err := yaml.Unmarshal(bytes, &config); err != nil {
		return nil, err
	}

	if err := utils.Convert(config.Volumes, &volumeConfigs); err != nil {
		return nil, err
	}

	return volumeConfigs, nil
}
func (c *Context) fillInRancherConfig(rawServiceMap config.RawServiceMap) error {
	if err := config.Interpolate(c.EnvironmentLookup, &rawServiceMap); err != nil {
		return err
	}

	rawServiceMap, err := preprocess.TryConvertStringsToInts(rawServiceMap, getRancherConfigObjects())
	if err != nil {
		return err
	}
	if err := utils.Convert(rawServiceMap, &c.RancherConfig); err != nil {
		return err
	}
	for _, v := range c.RancherConfig {
		rUtils.RemoveInterfaceKeys(v.Metadata)
	}
	return nil
}
Exemple #17
0
func LookupHash(service *client.Service) (ServiceHash, bool) {
	ret := ServiceHash{
		SecondaryLaunchConfigs: map[string]string{},
	}

	ret.Service = toString(service.Metadata[ServiceHashKey])
	ret.LaunchConfig = toString(service.LaunchConfig.Labels[ServiceHashKey])

	for _, rawSecondaryLaunchConfig := range service.SecondaryLaunchConfigs {
		var secondaryLaunchConfig client.SecondaryLaunchConfig
		if err := utils.Convert(rawSecondaryLaunchConfig, &secondaryLaunchConfig); err != nil {
			return ret, false
		}
		ret.SecondaryLaunchConfigs[secondaryLaunchConfig.Name] = toString(secondaryLaunchConfig.Labels[ServiceHashKey])
	}

	return ret, ret.Service != ""
}
// ParseNetworks parses networks in a compose file
func ParseNetworks(bytes []byte) (map[string]*NetworkConfig, error) {
	networkConfigs := make(map[string]*NetworkConfig)

	var config Config
	if err := yaml.Unmarshal(bytes, &config); err != nil {
		return nil, err
	}

	if err := utils.Convert(config.Networks, &networkConfigs); err != nil {
		return nil, err
	}

	for key, value := range networkConfigs {
		if value == nil {
			networkConfigs[key] = &NetworkConfig{}
		}
	}

	return networkConfigs, nil
}
Exemple #19
0
// Merge read the specified byte array, which is the content of a yaml composefile,
// and merge it into the current project.
func Merge(p *Project, bytes []byte) (map[string]*ServiceConfig, error) {
	configs := make(map[string]*ServiceConfig)

	datas := make(rawServiceMap)
	err := yaml.Unmarshal(bytes, &datas)
	if err != nil {
		logrus.Fatalf("Could not parse config for project %s : %v", p.Name, err)
	}

	for name, data := range datas {
		data, err := parse(p.context.ConfigLookup, p.File, data, datas)
		if err != nil {
			logrus.Errorf("Failed to parse service %s: %v", name, err)
			return nil, err
		}

		datas[name] = data
	}

	err = utils.Convert(datas, &configs)
	return configs, err
}
func (r *RancherService) createNormalService() (*rancherClient.Service, error) {
	secondaryLaunchConfigs := []interface{}{}

	launchConfig, err := r.createLaunchConfig(r.serviceConfig)
	if err != nil {
		return nil, err
	}

	if secondaries, ok := r.context.SidekickInfo.primariesToSidekicks[r.name]; ok {
		for _, secondaryName := range secondaries {
			serviceConfig, ok := r.context.Project.Configs[secondaryName]
			if !ok {
				return nil, fmt.Errorf("Failed to find sidekick: %s", secondaryName)
			}

			launchConfig, err := r.createLaunchConfig(serviceConfig)
			if err != nil {
				return nil, err
			}

			var secondaryLaunchConfig rancherClient.SecondaryLaunchConfig
			utils.Convert(launchConfig, &secondaryLaunchConfig)
			secondaryLaunchConfig.Name = secondaryName

			secondaryLaunchConfigs = append(secondaryLaunchConfigs, secondaryLaunchConfig)
		}
	}

	return r.context.Client.Service.Create(&rancherClient.Service{
		Name:                   r.name,
		Metadata:               r.getMetadata(),
		LaunchConfig:           launchConfig,
		SecondaryLaunchConfigs: secondaryLaunchConfigs,
		Scale:             int64(r.getConfiguredScale()),
		EnvironmentId:     r.context.Environment.Id,
		SelectorContainer: r.getSelectorContainer(),
		SelectorLink:      r.getSelectorLink(),
	})
}
Exemple #21
0
// ConvertServices converts a set of v1 service configs to v2 service configs
func ConvertServices(v1Services map[string]*ServiceConfigV1) (map[string]*ServiceConfig, error) {
	v2Services := make(map[string]*ServiceConfig)
	replacementFields := make(map[string]*ServiceConfig)

	for name, service := range v1Services {
		replacementFields[name] = &ServiceConfig{
			Build: Build{
				Context:    service.Build,
				Dockerfile: service.Dockerfile,
			},
			Logging: Log{
				Driver:  service.LogDriver,
				Options: service.LogOpt,
			},
			NetworkMode: service.Net,
		}

		v1Services[name].Build = ""
		v1Services[name].Dockerfile = ""
		v1Services[name].LogDriver = ""
		v1Services[name].LogOpt = nil
		v1Services[name].Net = ""
	}

	if err := utils.Convert(v1Services, &v2Services); err != nil {
		return nil, err
	}

	for name := range v2Services {
		v2Services[name].Build = replacementFields[name].Build
		v2Services[name].Logging = replacementFields[name].Logging
		v2Services[name].NetworkMode = replacementFields[name].NetworkMode
	}

	return v2Services, nil
}
Exemple #22
0
func readEnvFile(resourceLookup ResourceLookup, inFile string, serviceData RawService) (RawService, error) {
	if _, ok := serviceData["env_file"]; !ok {
		return serviceData, nil
	}

	var envFiles composeYaml.Stringorslice

	if err := utils.Convert(serviceData["env_file"], &envFiles); err != nil {
		return nil, err
	}

	if len(envFiles) == 0 {
		return serviceData, nil
	}

	if resourceLookup == nil {
		return nil, fmt.Errorf("Can not use env_file in file %s no mechanism provided to load files", inFile)
	}

	var vars composeYaml.MaporEqualSlice

	if _, ok := serviceData["environment"]; ok {
		if err := utils.Convert(serviceData["environment"], &vars); err != nil {
			return nil, err
		}
	}

	for i := len(envFiles) - 1; i >= 0; i-- {
		envFile := envFiles[i]
		content, _, err := resourceLookup.Lookup(envFile, inFile)
		if err != nil {
			return nil, err
		}

		if err != nil {
			return nil, err
		}

		scanner := bufio.NewScanner(bytes.NewBuffer(content))
		for scanner.Scan() {
			line := strings.TrimSpace(scanner.Text())

			if len(line) > 0 && !strings.HasPrefix(line, "#") {
				key := strings.SplitAfter(line, "=")[0]

				found := false
				for _, v := range vars {
					if strings.HasPrefix(v, key) {
						found = true
						break
					}
				}

				if !found {
					vars = append(vars, line)
				}
			}
		}

		if scanner.Err() != nil {
			return nil, scanner.Err()
		}
	}

	serviceData["environment"] = vars

	delete(serviceData, "env_file")

	return serviceData, nil
}
Exemple #23
0
// Merge merges a compose file into an existing set of service configs
func Merge(existingServices *ServiceConfigs, environmentLookup EnvironmentLookup, resourceLookup ResourceLookup, file string, bytes []byte, options *ParseOptions) (string, map[string]*ServiceConfig, map[string]*VolumeConfig, map[string]*NetworkConfig, error) {
	if options == nil {
		options = &defaultParseOptions
	}

	config, err := CreateConfig(bytes)
	if err != nil {
		return "", nil, nil, nil, err
	}
	baseRawServices := config.Services

	if options.Interpolate {
		if err := InterpolateRawServiceMap(&baseRawServices, environmentLookup); err != nil {
			return "", nil, nil, nil, err
		}

		for k, v := range config.Volumes {
			if err := Interpolate(k, &v, environmentLookup); err != nil {
				return "", nil, nil, nil, err
			}
			config.Volumes[k] = v
		}

		for k, v := range config.Networks {
			if err := Interpolate(k, &v, environmentLookup); err != nil {
				return "", nil, nil, nil, err
			}
			config.Networks[k] = v
		}
	}

	if options.Preprocess != nil {
		var err error
		baseRawServices, err = options.Preprocess(baseRawServices)
		if err != nil {
			return "", nil, nil, nil, err
		}
	}

	var serviceConfigs map[string]*ServiceConfig
	if config.Version == "2" {
		var err error
		serviceConfigs, err = MergeServicesV2(existingServices, environmentLookup, resourceLookup, file, baseRawServices, options)
		if err != nil {
			return "", nil, nil, nil, err
		}
	} else {
		serviceConfigsV1, err := MergeServicesV1(existingServices, environmentLookup, resourceLookup, file, baseRawServices, options)
		if err != nil {
			return "", nil, nil, nil, err
		}
		serviceConfigs, err = ConvertServices(serviceConfigsV1)
		if err != nil {
			return "", nil, nil, nil, err
		}
	}

	adjustValues(serviceConfigs)

	if options.Postprocess != nil {
		var err error
		serviceConfigs, err = options.Postprocess(serviceConfigs)
		if err != nil {
			return "", nil, nil, nil, err
		}
	}

	var volumes map[string]*VolumeConfig
	var networks map[string]*NetworkConfig
	if err := utils.Convert(config.Volumes, &volumes); err != nil {
		return "", nil, nil, nil, err
	}
	if err := utils.Convert(config.Networks, &networks); err != nil {
		return "", nil, nil, nil, err
	}

	return config.Version, serviceConfigs, volumes, networks, nil
}
func TestCreateBindings(t *testing.T) {
	var labelsCompose libYaml.SliceorMap
	var labels libYaml.SliceorMap
	var ports PortArray

	bindingPropertyMap, err := ExtractBindings([]byte(`
test_v1:
  ports:
  - 9000:9000/tcp
  labels:
    label_1: value_1
  tty: true
  image: foo`))
	if err != nil {
		t.Fatal(err)
	}

	labelsCompose = make(map[string]string)
	labelsCompose["label_1"] = "value_1"
	portsCompose := PortArray{}
	portsCompose = append(portsCompose, "9000:9000/tcp")

	if len(bindingPropertyMap) != 1 {
		t.Fatal("Bindings not created")
	}

	if _, ok := bindingPropertyMap["services"]; ok {
		service := bindingPropertyMap["services"].(map[string]ServiceBinding)

		err = utils.Convert(service["test_v1"].Labels, &labels)
		if err != nil {
			t.Fatal(err)
		}

		if !(reflect.DeepEqual(labels, labelsCompose)) {
			t.Fatal("Bindings labels incorrect")
		}

		err = utils.Convert(service["test_v1"].Ports, &ports)
		if err != nil {
			t.Fatal(err)
		}

		if !(reflect.DeepEqual(ports, portsCompose)) {
			t.Fatal("Bindings ports incorrect")
		}
	}

	bindingPropertyMap, err = ExtractBindings([]byte(`
version: '2'
services:
  test_v2:
    labels:
      label_2: value_2
    ports:
    - 9001:9001/tcp
`))
	if err != nil {
		t.Fatal(err)
	}

	labelsCompose = make(map[string]string)
	labelsCompose["label_2"] = "value_2"
	portsCompose = PortArray{}
	portsCompose = append(portsCompose, "9001:9001/tcp")

	if len(bindingPropertyMap) != 1 {
		t.Fatal("Bindings not created")
	}

	if _, ok := bindingPropertyMap["services"]; ok {
		service := bindingPropertyMap["services"].(map[string]ServiceBinding)

		err = utils.Convert(service["test_v2"].Labels, &labels)
		if err != nil {
			t.Fatal(err)
		}

		if !(reflect.DeepEqual(labels, labelsCompose)) {
			t.Fatal("Bindings labels incorrect")
		}

		err = utils.Convert(service["test_v2"].Ports, &ports)
		if err != nil {
			t.Fatal(err)
		}

		if !(reflect.DeepEqual(ports, portsCompose)) {
			t.Fatal("Bindings ports incorrect")
		}
	}
}