Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added device support to bundle data #249

Merged
merged 2 commits into from
Jun 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ TAGS
.emacs*
*.test
*.sw[nop]

.vscode
2 changes: 1 addition & 1 deletion bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func checkWordpressBundle(c *gc.C, b charm.Bundle, path string) {
"wordpress": wordpressCharm,
"mysql": mysqlCharm,
}
err := bd.VerifyWithCharms(verifyOk, nil, charms)
err := bd.VerifyWithCharms(verifyOk, nil, nil, charms)
c.Assert(err, gc.IsNil)

c.Assert(bd.Applications, jc.DeepEquals, map[string]*charm.ApplicationSpec{
Expand Down
39 changes: 32 additions & 7 deletions bundledata.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ type ApplicationSpec struct {
// to units of the application.
Storage map[string]string `bson:",omitempty" json:",omitempty" yaml:",omitempty"`

// Devices holds the constraints for devices to assign
// to units of the application.
Devices map[string]string `bson:",omitempty" json:",omitempty" yaml:",omitempty"`

// EndpointBindings maps how endpoints are bound to spaces
EndpointBindings map[string]string `bson:"bindings,omitempty" json:"bindings,omitempty" yaml:"bindings,omitempty"`

Expand Down Expand Up @@ -285,6 +289,7 @@ type bundleDataVerifier struct {
errors []error
verifyConstraints func(c string) error
verifyStorage func(s string) error
verifyDevices func(s string) error
}

func (verifier *bundleDataVerifier) addErrorf(f string, a ...interface{}) {
Expand Down Expand Up @@ -324,23 +329,25 @@ func (bd *BundleData) VerifyLocal(
bundleDir string,
verifyConstraints func(c string) error,
verifyStorage func(s string) error,
verifyDevices func(s string) error,
) error {
return bd.verifyBundle(bundleDir, verifyConstraints, verifyStorage, nil)
return bd.verifyBundle(bundleDir, verifyConstraints, verifyStorage, verifyDevices, nil)
}

// Verify is a convenience method that calls VerifyWithCharms
// with a nil charms map.
func (bd *BundleData) Verify(
verifyConstraints func(c string) error,
verifyStorage func(s string) error,
verifyDevices func(s string) error,
) error {
return bd.VerifyWithCharms(verifyConstraints, verifyStorage, nil)
return bd.VerifyWithCharms(verifyConstraints, verifyStorage, verifyDevices, nil)
}

// VerifyWithCharms verifies that the bundle is consistent.
// The verifyConstraints function is called to verify any constraints
// that are found. If verifyConstraints is nil, no checking
// of constraints will be done. Similarly, a non-nil verifyStorage
// of constraints will be done. Similarly, a non-nil verifyStorage, verifyDevices
// function is called to verify any storage constraints.
//
// It verifies the following:
Expand All @@ -361,15 +368,17 @@ func (bd *BundleData) Verify(
func (bd *BundleData) VerifyWithCharms(
verifyConstraints func(c string) error,
verifyStorage func(s string) error,
verifyDevices func(s string) error,
charms map[string]Charm,
) error {
return bd.verifyBundle("", verifyConstraints, verifyStorage, charms)
return bd.verifyBundle("", verifyConstraints, verifyStorage, verifyDevices, charms)
}

func (bd *BundleData) verifyBundle(
bundleDir string,
verifyConstraints func(c string) error,
verifyStorage func(s string) error,
verifyDevices func(s string) error,
charms map[string]Charm,
) error {
if verifyConstraints == nil {
Expand All @@ -382,6 +391,11 @@ func (bd *BundleData) verifyBundle(
return nil
}
}
if verifyDevices == nil {
verifyDevices = func(string) error {
return nil
}
}
verifier := &bundleDataVerifier{
bundleDir: bundleDir,
verifyConstraints: verifyConstraints,
Expand Down Expand Up @@ -413,6 +427,7 @@ func (bd *BundleData) verifyBundle(
var (
validMachineId = regexp.MustCompile("^" + names.NumberSnippet + "$")
validStorageName = regexp.MustCompile("^" + names.StorageNameSnippet + "$")
validDeviceName = regexp.MustCompile("^" + "(?:[a-z][a-z0-9]*(?:-[a-z0-9]*[a-z][a-z0-9]*)*)" + "$")
)

func (verifier *bundleDataVerifier) verifyMachines() {
Expand Down Expand Up @@ -462,17 +477,18 @@ func (verifier *bundleDataVerifier) verifyApplications() {
verifier.addErrorf("invalid charm URL in application %q: %v", name, err)
}

// Check the series.
// Check the Series.
if curl != nil && curl.Series != "" && svc.Series != "" && curl.Series != svc.Series {
verifier.addErrorf("the charm URL for application %q has a series which does not match, please remove the series from the URL", name)
}
if svc.Series != "" && !IsValidSeries(svc.Series) {
verifier.addErrorf("application %q declares an invalid series %q", name, svc.Series)
}

// Check the Constraints.
if err := verifier.verifyConstraints(svc.Constraints); err != nil {
verifier.addErrorf("invalid constraints %q in application %q: %v", svc.Constraints, name, err)
}
// Check the Storage.
for storageName, storageConstraints := range svc.Storage {
if !validStorageName.MatchString(storageName) {
verifier.addErrorf("invalid storage name %q in application %q", storageName, name)
Expand All @@ -481,6 +497,15 @@ func (verifier *bundleDataVerifier) verifyApplications() {
verifier.addErrorf("invalid storage %q in application %q: %v", storageName, name, err)
}
}
// Check the Devices.
for deviceName, deviceConstraints := range svc.Devices {
if !validDeviceName.MatchString(deviceName) {
verifier.addErrorf("invalid device name %q in application %q", deviceName, name)
}
if err := verifier.verifyDevices(deviceConstraints); err != nil {
verifier.addErrorf("invalid device %q in application %q: %v", deviceName, name, err)
}
}
if verifier.charms != nil {
if ch, ok := verifier.charms[svc.Charm]; ok {
if ch.Meta().Subordinate {
Expand Down Expand Up @@ -617,7 +642,7 @@ func (verifier *bundleDataVerifier) verifyRelations() {
func (verifier *bundleDataVerifier) verifyEndpointBindings() {
for name, svc := range verifier.bd.Applications {
charm, ok := verifier.charms[name]
// Only thest the ok path here because the !ok path is tested in verifyApplications
// Only test the ok path here because the !ok path is tested in verifyApplications
if !ok {
continue
}
Expand Down
17 changes: 11 additions & 6 deletions bundledata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,11 +442,16 @@ func assertVerifyErrors(c *gc.C, bundleData string, charms map[string]charm.Char
}
return nil
}

validateDevices := func(c string) error {
if c == "bad device constraints" {
return fmt.Errorf("bad device constraint")
}
return nil
}
if charms != nil {
err = bd.VerifyWithCharms(validateConstraints, validateStorage, charms)
err = bd.VerifyWithCharms(validateConstraints, validateStorage, validateDevices, charms)
} else {
err = bd.VerifyLocal("internal/test-charm-repo/bundle", validateConstraints, validateStorage)
err = bd.VerifyLocal("internal/test-charm-repo/bundle", validateConstraints, validateStorage, validateDevices)
}

if len(expectErrors) == 0 {
Expand Down Expand Up @@ -482,7 +487,7 @@ func (*bundleDataSuite) TestVerifyCharmURL(c *gc.C) {
} {
c.Logf("test %d: %s", i, u)
bd.Applications["mediawiki"].Charm = u
err := bd.Verify(nil, nil)
err := bd.Verify(nil, nil, nil)
c.Check(err, gc.IsNil, gc.Commentf("charm url %q", u))
}
}
Expand All @@ -507,7 +512,7 @@ func (*bundleDataSuite) TestVerifyLocalCharm(c *gc.C) {
} {
c.Logf("test %d: %s", i, u)
bd.Applications["mediawiki"].Charm = u
err := bd.VerifyLocal(bundleDir, nil, nil)
err := bd.VerifyLocal(bundleDir, nil, nil, nil)
c.Check(err, gc.IsNil, gc.Commentf("charm url %q", u))
}
}
Expand All @@ -531,7 +536,7 @@ func (s *bundleDataSuite) testPrepareAndMutateBeforeVerifyWithCharms(c *gc.C, mu
mutator(bd)
}

return bd.VerifyWithCharms(nil, nil, charms)
return bd.VerifyWithCharms(nil, nil, nil, charms)
}

func (s *bundleDataSuite) TestVerifyBundleWithUnknownEndpointBindingGiven(c *gc.C) {
Expand Down