1
// Copyright 2014 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
"gopkg.in/juju/names.v2"
14
// MachineScope is a special scope name that is used
15
// for machine placement directives (e.g. --to 0).
19
var ErrPlacementScopeMissing = fmt.Errorf("placement scope missing")
21
// Placement defines a placement directive, which has a scope
22
// and a value that is scope-specific.
23
type Placement struct {
24
// Scope is the scope of the placement directive. Scope may
25
// be a container type (lxd, kvm), instance.MachineScope, or
26
// an environment name.
28
// If Scope is empty, then it must be inferred from the context.
29
Scope string `json:"scope"`
31
// Directive is a scope-specific placement directive.
33
// For MachineScope or a container scope, this may be empty or
34
// the ID of an existing machine.
35
Directive string `json:"directive"`
38
func (p *Placement) String() string {
39
return fmt.Sprintf("%s:%s", p.Scope, p.Directive)
42
func isContainerType(s string) bool {
43
_, err := ParseContainerType(s)
47
// ParsePlacement attempts to parse the specified string and create a
48
// corresponding Placement structure.
50
// If the placement directive is non-empty and missing a scope,
51
// ErrPlacementScopeMissing will be returned as well as a Placement
52
// with an empty Scope field.
53
func ParsePlacement(directive string) (*Placement, error) {
57
if colon := strings.IndexRune(directive, ':'); colon != -1 {
58
scope, directive := directive[:colon], directive[colon+1:]
60
return nil, ErrPlacementScopeMissing
62
// Sanity check: machine/container scopes require a machine ID as the value.
63
if (scope == MachineScope || isContainerType(scope)) && !names.IsValidMachine(directive) {
64
return nil, fmt.Errorf("invalid value %q for %q scope: expected machine-id", directive, scope)
66
return &Placement{Scope: scope, Directive: directive}, nil
68
if names.IsValidMachine(directive) {
69
return &Placement{Scope: MachineScope, Directive: directive}, nil
71
if isContainerType(directive) {
72
return &Placement{Scope: directive}, nil
74
return nil, ErrPlacementScopeMissing
77
// MustParsePlacement attempts to parse the specified string and create
78
// a corresponding Placement structure, panicking if an error occurs.
79
func MustParsePlacement(directive string) *Placement {
80
placement, err := ParsePlacement(directive)