Skip to content

Commit

Permalink
Bugfix: Resolve missing data elements
Browse files Browse the repository at this point in the history
Fixes the loss of Relationship Interface data and the copying the
wrong data within Relationships. By cloning the parent before merging
the parent was never accidentially referenced.

Interface merging applied to RelationshipTemplates in the same manner
as NodeTemplates.

Adds test cases to verify the Interfaces on a RelationshipTemplate.
  • Loading branch information
kenjones-cisco committed Dec 2, 2016
1 parent 68f37fb commit f9aab13
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 70 deletions.
9 changes: 1 addition & 8 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
FROM golang:1.6

RUN apt-get update && apt-get install -y --no-install-recommends \
zip \
&& rm -rf /var/lib/apt/lists/*
FROM golang:1.7

ENV GLIDE_VERSION v0.12.3

Expand All @@ -16,7 +12,4 @@ RUN go get -u github.com/jteeuwen/go-bindata/... \
&& rm /tmp/glide.tgz

ENV CGO_ENABLED 0
ENV GO15VENDOREXPERIMENT 1
ENV GOEXPERIMENT framepointer
ENV GOPATH /go:/toscalib

23 changes: 17 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SHELL := /bin/bash

.PHONY: clean test cover lint format

PROJECT = toscalib
export PROJECT = toscalib

IMPORT_PATH := github.com/CiscoCloud/${PROJECT}

Expand All @@ -25,14 +25,17 @@ DOCKERNOVENDOR := docker run --rm -i \
${DEV_IMAGE}

clean:
@rm -rf cover *.txt
@rm -rf cover

veryclean: clean
@rm -rf .glide vendor

# ----------------------------------------------
# docker build
# build

# builds the builder container
build/image_build:
docker build -t ${DEV_IMAGE} -f Dockerfile.dev .
@docker build --quiet -t ${DEV_IMAGE} -f Dockerfile.dev .

# top-level target for vendoring our packages: glide install requires
# being in the package directory so we have to run this for each package
Expand All @@ -41,9 +44,12 @@ vendor: build/image_build

# fetch a dependency via go get, vendor it, and then save into the parent
# package's glide.yml
# usage DEP=github.com/owner/package make add-dep
# usage: DEP=github.com/owner/package make add-dep
add-dep: build/image_build
${DOCKERNOVENDOR} bash -c "DEP=$(DEP) ./scripts/add_dep.sh"
ifeq ($(strip $(DEP)),)
$(error "No dependency provided. Expected: DEP=<go import path>")
endif
${DOCKERNOVENDOR} glide get ${DEP}

# ----------------------------------------------
# develop and test
Expand All @@ -67,3 +73,8 @@ cover: check
# ------ Generator
generate: build/image_build NormativeTypes/*
${DOCKERRUN} go-bindata -pkg=toscalib -prefix=NormativeTypes/ -o normative_definitions.go NormativeTypes/

# ------ Minishift / Docker Machine Helpers
.PHONY: setup
setup:
@bash ./scripts/setup.sh
3 changes: 3 additions & 0 deletions NormativeTypes/capability_types
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ capability_types:
tosca.capabilities.network.Bindable:
derived_from: tosca.capabilities.Node

tosca.capabilities.network.Linkable:
derived_from: tosca.capabilities.Node

tosca.capabilities.Node:
derived_from: tosca.capabilities.Root

Expand Down
70 changes: 70 additions & 0 deletions NormativeTypes/node_types
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,76 @@ node_types:
occurrences: [0, UNBOUNDED]
description: Connection to one or more load balanced applications

tosca.nodes.network.Network:
derived_from: tosca.nodes.Root
properties:
ip_version:
type: integer
required: false
default: 4
constraints:
- valid_values: [ 4, 6 ]
cidr:
type: string
required: false
start_ip:
type: string
required: false
end_ip:
type: string
required: false
gateway_ip:
type: string
required: false
network_name:
type: string
required: false
network_id:
type: string
required: false
segmentation_id:
type: string
required: false
network_type:
type: string
required: false
physical_network:
type: string
required: false
capabilities:
link:
type: tosca.capabilities.network.Linkable

tosca.nodes.network.Port:
derived_from: tosca.nodes.Root
properties:
ip_address:
type: string
required: false
order:
type: integer
required: true
default: 0
constraints:
- greater_or_equal: 0
is_default:
type: boolean
required: false
default: false
ip_range_start:
type: string
required: false
ip_range_end:
type: string
required: false
requirements:
- link:
capability: tosca.capabilities.network.Linkable
relationship: tosca.relationships.network.LinksTo
- binding:
capability: tosca.capabilities.network.Bindable
relationship: tosca.relationships.network.BindsTo

tosca.nodes.Storage.ObjectStorage:
derived_from: tosca.nodes.Root
properties:
Expand Down
8 changes: 8 additions & 0 deletions NormativeTypes/relationship_types
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ relationship_types:
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.Container ]

tosca.relationships.network.BindsTo:
derived_from: tosca.relationships.DependsOn
valid_target_types: [ tosca.capabilities.network.Bindable ]

tosca.relationships.network.LinksTo:
derived_from: tosca.relationships.DependsOn
valid_target_types: [ tosca.capabilities.network.Linkable ]

tosca.relationships.Root:
description: The TOSCA root Relationship Type all other TOSCA base Relationship Types derive from
attributes:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Abstract

This library is an implementation of the TOSCA definition as described in the document written in pure GO
[TOSCA Simple Profile in YAML Version 1.0](http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/TOSCA-Simple-Profile-YAML-v1.0.html)
[TOSCA Simple Profile in YAML Version 1.1](http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.1/TOSCA-Simple-Profile-YAML-v1.1.html)

## Status

Expand Down
93 changes: 67 additions & 26 deletions flattener.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,27 @@ type flatTypes struct {
Policies map[string]PolicyType
}

// TODO(kenjones): Switch to reflect if possible in the future (if simple)

func flattenCapType(name string, s ServiceTemplateDefinition) CapabilityType {
if ct, ok := s.CapabilityTypes[name]; ok {
if ct.DerivedFrom != "" {
parent := flattenCapType(ct.DerivedFrom, s)

// clone the parent first before applying any changes
tmp := clone(parent)
ctm, _ := tmp.(CapabilityType)

// mergo does not handle merging Slices so the rt items
// will wipe away, capture the values here.
sources := parent.ValidSources
sources := ctm.ValidSources

_ = mergo.MergeWithOverwrite(&parent, ct)
_ = mergo.MergeWithOverwrite(&ctm, ct)

// now copy them back in using append, if the child type had
// any previously, otherwise it will duplicate the parents.
if len(ct.ValidSources) > 0 {
parent.ValidSources = append(parent.ValidSources, sources...)
ctm.ValidSources = append(ctm.ValidSources, sources...)
}
return parent
return ctm
}
return ct
}
Expand All @@ -39,8 +42,13 @@ func flattenIntfType(name string, s ServiceTemplateDefinition) InterfaceType {
if it, ok := s.InterfaceTypes[name]; ok {
if it.DerivedFrom != "" {
parent := flattenIntfType(it.DerivedFrom, s)
_ = mergo.MergeWithOverwrite(&parent, it)
return parent

// clone the parent first before applying any changes
tmp := clone(parent)
itm, _ := tmp.(InterfaceType)

_ = mergo.MergeWithOverwrite(&itm, it)
return itm
}
return it
}
Expand All @@ -51,18 +59,23 @@ func flattenRelType(name string, s ServiceTemplateDefinition) RelationshipType {
if rt, ok := s.RelationshipTypes[name]; ok {
if rt.DerivedFrom != "" {
parent := flattenRelType(rt.DerivedFrom, s)

// clone the parent first before applying any changes
tmp := clone(parent)
rtm, _ := tmp.(RelationshipType)

// mergo does not handle merging Slices so the rt items
// will wipe away, capture the values here.
targets := parent.ValidTarget
targets := rtm.ValidTarget

_ = mergo.MergeWithOverwrite(&parent, rt)
_ = mergo.MergeWithOverwrite(&rtm, rt)

// now copy them back in using append, if the child type had
// any previously, otherwise it will duplicate the parents.
if len(rt.ValidTarget) > 0 {
parent.ValidTarget = append(parent.ValidTarget, targets...)
rtm.ValidTarget = append(rtm.ValidTarget, targets...)
}
return parent
return rtm
}
return rt
}
Expand All @@ -73,18 +86,23 @@ func flattenNodeType(name string, s ServiceTemplateDefinition) NodeType {
if nt, ok := s.NodeTypes[name]; ok {
if nt.DerivedFrom != "" {
parent := flattenNodeType(nt.DerivedFrom, s)

// clone the parent first before applying any changes
tmp := clone(parent)
ntm, _ := tmp.(NodeType)

// mergo does not handle merging Slices so the nt items
// will wipe away, capture the values here.
reqs := parent.Requirements
reqs := ntm.Requirements

_ = mergo.MergeWithOverwrite(&parent, nt)
_ = mergo.MergeWithOverwrite(&ntm, nt)

// now copy them back in using append, if the child node type had
// any previously, otherwise it will duplicate the parents.
if len(nt.Requirements) > 0 {
parent.Requirements = append(parent.Requirements, reqs...)
ntm.Requirements = append(ntm.Requirements, reqs...)
}
return parent
return ntm
}
return nt
}
Expand All @@ -95,22 +113,27 @@ func flattenGroupType(name string, s ServiceTemplateDefinition) GroupType {
if gt, ok := s.GroupTypes[name]; ok {
if gt.DerivedFrom != "" {
parent := flattenGroupType(gt.DerivedFrom, s)

// clone the parent first before applying any changes
tmp := clone(parent)
gtm, _ := tmp.(GroupType)

// mergo does not handle merging Slices so the nt items
// will wipe away, capture the values here.
reqs := parent.Requirements
members := parent.Members
reqs := gtm.Requirements
members := gtm.Members

_ = mergo.MergeWithOverwrite(&parent, gt)
_ = mergo.MergeWithOverwrite(&gtm, gt)

// now copy them back in using append, if the child type had
// any previously, otherwise it will duplicate the parents.
if len(gt.Requirements) > 0 {
parent.Requirements = append(parent.Requirements, reqs...)
gtm.Requirements = append(gtm.Requirements, reqs...)
}
if len(gt.Members) > 0 {
parent.Members = append(parent.Members, members...)
gtm.Members = append(gtm.Members, members...)
}
return parent
return gtm
}
return gt
}
Expand All @@ -121,18 +144,23 @@ func flattenPolicyType(name string, s ServiceTemplateDefinition) PolicyType {
if pt, ok := s.PolicyTypes[name]; ok {
if pt.DerivedFrom != "" {
parent := flattenPolicyType(pt.DerivedFrom, s)

// clone the parent first before applying any changes
tmp := clone(parent)
ptm, _ := tmp.(PolicyType)

// mergo does not handle merging Slices so the items
// will wipe away, capture the values here.
targets := parent.Targets
targets := ptm.Targets

_ = mergo.MergeWithOverwrite(&parent, pt)
_ = mergo.MergeWithOverwrite(&ptm, pt)

// now copy them back in using append, if the child type had
// any previously, otherwise it will duplicate the parents.
if len(pt.Targets) > 0 {
parent.Targets = append(parent.Targets, targets...)
ptm.Targets = append(ptm.Targets, targets...)
}
return parent
return ptm
}
return pt
}
Expand All @@ -157,6 +185,19 @@ func flattenHierarchy(s ServiceTemplateDefinition) flatTypes {
flats.Relationships[name] = flattenRelType(name, s)
}

for k, v := range flats.Relationships {
for name, iDef := range v.Interfaces {
// during merge the Type is not always properly inherited, so set it
// from the parent.
if iDef.Type == "" {
iDef.Type = flats.Relationships[v.DerivedFrom].Interfaces[name].Type
}
iDef.extendFrom(flats.Interfaces[iDef.Type])
v.Interfaces[name] = iDef
}
flats.Relationships[k] = v
}

flats.Nodes = make(map[string]NodeType)
for name := range s.NodeTypes {
flats.Nodes[name] = flattenNodeType(name, s)
Expand Down
Loading

0 comments on commit f9aab13

Please sign in to comment.