26
25
"launchpad.net/juju-core/errors"
27
26
"launchpad.net/juju-core/instance"
28
27
"launchpad.net/juju-core/log"
28
"launchpad.net/juju-core/names"
29
29
"launchpad.net/juju-core/state/api/params"
30
30
"launchpad.net/juju-core/state/multiwatcher"
31
31
"launchpad.net/juju-core/state/presence"
36
36
// TODO(niemeyer): This must not be exported.
37
37
type D []bson.DocElem
39
const serviceSnippet = "[a-z][a-z0-9]*(-[a-z0-9]*[a-z][a-z0-9]*)*"
40
const numberSnippet = "(0|[1-9][0-9]*)"
41
const containerSnippet = "(/[a-z]+/" + numberSnippet + ")"
42
const machineSnippet = numberSnippet + containerSnippet + "*"
43
const containerSpecSnippet = "(([a-z])*:)?"
46
validService = regexp.MustCompile("^" + serviceSnippet + "$")
47
validUnit = regexp.MustCompile("^" + serviceSnippet + "/" + numberSnippet + "$")
48
validMachine = regexp.MustCompile("^" + machineSnippet + "$")
49
validMachineOrNewContainer = regexp.MustCompile("^" + containerSpecSnippet + machineSnippet + "$")
52
39
// BootstrapNonce is used as a nonce for the state server machine.
53
40
const BootstrapNonce = "user-admin:bootstrap"
55
// IsServiceName returns whether name is a valid service name.
56
func IsServiceName(name string) bool {
57
return validService.MatchString(name)
60
// IsUnitName returns whether name is a valid unit name.
61
func IsUnitName(name string) bool {
62
return validUnit.MatchString(name)
65
// IsMachineId returns whether id is a valid machine id.
66
func IsMachineId(id string) bool {
67
return validMachine.MatchString(id)
70
// IsMachineOrNewContainer returns whether spec is a valid machine id or new container definition.
71
func IsMachineOrNewContainer(spec string) bool {
72
return validMachineOrNewContainer.MatchString(spec)
75
42
// State represents the state of an environment
76
43
// managed by juju.
77
44
type State struct {
603
570
return nil, fmt.Errorf("invalid entity tag %q", tag)
605
572
prefix, id := tag[0:i], tag[i+1:]
608
id = MachineIdFromTag(tag)
609
if !IsMachineId(id) {
575
case names.MachineTagPrefix:
576
id, err := names.MachineIdFromTag(tag)
580
if !names.IsMachineId(id) {
610
581
return nil, fmt.Errorf("invalid entity tag %q", tag)
612
583
return st.Machine(id)
584
case names.UnitTagPrefix:
614
585
i := strings.LastIndex(id, "-")
616
587
return nil, fmt.Errorf("invalid entity tag %q", tag)
618
589
name := id[:i] + "/" + id[i+1:]
619
if !IsUnitName(name) {
590
if !names.IsUnitName(name) {
620
591
return nil, fmt.Errorf("invalid entity tag %q", tag)
622
593
return st.Unit(name)
594
case names.UserTagPrefix:
624
595
return st.User(id)
626
if !IsServiceName(id) {
596
case names.ServiceTagPrefix:
597
if !names.IsServiceName(id) {
627
598
return nil, fmt.Errorf("invalid entity tag %q", tag)
629
600
return st.Service(id)
601
case names.EnvironTagPrefix:
631
602
conf, err := st.EnvironConfig()
625
tagPrefix := parts[0] + "-"
627
case names.MachineTagPrefix:
656
628
coll = st.machines.Name
629
case names.ServiceTagPrefix:
658
630
coll = st.services.Name
631
case names.UnitTagPrefix:
660
632
coll = st.units.Name
661
633
// Handle replacements occurring when an entity name is created
665
637
return "", "", fmt.Errorf("invalid entity name %q", tag)
667
639
id = id[:idx] + "/" + id[idx+1:]
640
case names.UserTagPrefix:
669
641
coll = st.users.Name
671
643
return "", "", fmt.Errorf("invalid entity name %q", tag)
743
715
func (st *State) AddService(name string, ch *Charm) (service *Service, err error) {
744
716
defer utils.ErrorContextf(&err, "cannot add service %q", name)
745
717
// Sanity checks.
746
if !IsServiceName(name) {
718
if !names.IsServiceName(name) {
747
719
return nil, fmt.Errorf("invalid name")
804
776
// Service returns a service state by name.
805
777
func (st *State) Service(name string) (service *Service, err error) {
806
if !IsServiceName(name) {
778
if !names.IsServiceName(name) {
807
779
return nil, fmt.Errorf("%q is not a valid service name", name)
809
781
sdoc := &serviceDoc{}
1076
1048
// Unit returns a unit by name.
1077
1049
func (st *State) Unit(name string) (*Unit, error) {
1078
if !IsUnitName(name) {
1050
if !names.IsUnitName(name) {
1079
1051
return nil, fmt.Errorf("%q is not a valid unit name", name)
1081
1053
doc := unitDoc{}
1334
1306
var tagPrefix = map[byte]string{
1335
'm': machineTagPrefix,
1338
'e': "environment-",
1307
'm': names.MachineTagPrefix,
1308
's': names.ServiceTagPrefix,
1309
'u': names.UnitTagPrefix,
1310
'e': names.EnvironTagPrefix,
1341
1313
func tagForGlobalKey(key string) (string, bool) {