github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/instance/namespace.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package instance
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/errors"
    10  	"gopkg.in/juju/names.v2"
    11  )
    12  
    13  // uuidSuffixDigits defines how many of the uuid digits to use.
    14  // Since the NewNamespace function asserts that the modelUUID is valid, we know
    15  // it follows the UUID string format that ends with eight hex digits.
    16  const uuidSuffixDigits = 6
    17  
    18  // Namespace provides a way to generate machine hostanmes with a given prefix.
    19  type Namespace interface {
    20  	// Prefix returns the common part of the hostnames. i.e. 'juju-xxxxxx-'
    21  	Prefix() string
    22  	// Hostname returns a name suitable to be used for a machine hostname.
    23  	// This function returns an error if the machine tags is invalid.
    24  	Hostname(machineID string) (string, error)
    25  
    26  	// MachineTag does the reverse of the Hostname method, and extracts the
    27  	// Tag from the hostname.
    28  	MachineTag(hostname string) (names.MachineTag, error)
    29  }
    30  
    31  type namespace struct {
    32  	name string
    33  }
    34  
    35  // NewNamespace returns a Namespace identified by the last six hex digits of the
    36  // model UUID. NewNamespace returns an error if the model tag is invalid.
    37  func NewNamespace(modelUUID string) (Namespace, error) {
    38  	if !names.IsValidModel(modelUUID) {
    39  		return nil, errors.Errorf("model ID %q is not a valid model", modelUUID)
    40  	}
    41  	// The suffix is the last six hex digits of the model uuid.
    42  	suffix := modelUUID[len(modelUUID)-uuidSuffixDigits:]
    43  
    44  	return &namespace{name: suffix}, nil
    45  }
    46  
    47  // Hostname implements Namespace.
    48  func (n *namespace) Hostname(machineID string) (string, error) {
    49  	if !names.IsValidMachine(machineID) {
    50  		return "", errors.Errorf("machine ID %q is not a valid machine", machineID)
    51  	}
    52  	machineID = strings.Replace(machineID, "/", "-", -1)
    53  	return n.Prefix() + machineID, nil
    54  }
    55  
    56  // Hostname implements Namespace.
    57  func (n *namespace) MachineTag(hostname string) (names.MachineTag, error) {
    58  	prefix := n.Prefix()
    59  	if !strings.HasPrefix(hostname, prefix) {
    60  		return names.MachineTag{}, errors.Errorf("hostname %q not from namespace %q", hostname, prefix)
    61  	}
    62  	id := hostname[len(prefix):]
    63  	id = strings.Replace(id, "-", "/", -1)
    64  	if !names.IsValidMachine(id) {
    65  		return names.MachineTag{}, errors.Errorf("unexpected machine id %q", id)
    66  	}
    67  	return names.NewMachineTag(id), nil
    68  }
    69  
    70  // Prefix implements Namespace.
    71  func (n *namespace) Prefix() string {
    72  	return "juju-" + n.name + "-"
    73  }