blob: 2314f8733d49ae31270927ba58a835545e954094 [file] [log] [blame]
David K. Bainbridge528b3182017-01-23 08:51:59 -08001// Copyright 2015 Canonical Ltd.
2// Licensed under the LGPLv3, see LICENCE file for details.
3
4package names
5
6import (
7 "fmt"
8 "regexp"
9 "strings"
10)
11
12const (
13 StorageTagKind = "storage"
14
15 // StorageNameSnippet is the regular expression that describes valid
16 // storage names (without the storage instance sequence number).
17 StorageNameSnippet = "(?:[a-z][a-z0-9]*(?:-[a-z0-9]*[a-z][a-z0-9]*)*)"
18)
19
20var validStorage = regexp.MustCompile("^(" + StorageNameSnippet + ")/" + NumberSnippet + "$")
21
22type StorageTag struct {
23 id string
24}
25
26func (t StorageTag) String() string { return t.Kind() + "-" + t.id }
27func (t StorageTag) Kind() string { return StorageTagKind }
28func (t StorageTag) Id() string { return storageTagSuffixToId(t.id) }
29
30// NewStorageTag returns the tag for the storage instance with the given ID.
31// It will panic if the given string is not a valid storage instance Id.
32func NewStorageTag(id string) StorageTag {
33 tag, ok := tagFromStorageId(id)
34 if !ok {
35 panic(fmt.Sprintf("%q is not a valid storage instance ID", id))
36 }
37 return tag
38}
39
40// ParseStorageTag parses a storage tag string.
41func ParseStorageTag(s string) (StorageTag, error) {
42 tag, err := ParseTag(s)
43 if err != nil {
44 return StorageTag{}, err
45 }
46 st, ok := tag.(StorageTag)
47 if !ok {
48 return StorageTag{}, invalidTagError(s, StorageTagKind)
49 }
50 return st, nil
51}
52
53// IsValidStorage returns whether id is a valid storage instance ID.
54func IsValidStorage(id string) bool {
55 return validStorage.MatchString(id)
56}
57
58// StorageName returns the storage name from a storage instance ID.
59// StorageName returns an error if "id" is not a valid storage
60// instance ID.
61func StorageName(id string) (string, error) {
62 s := validStorage.FindStringSubmatch(id)
63 if s == nil {
64 return "", fmt.Errorf("%q is not a valid storage instance ID", id)
65 }
66 return s[1], nil
67}
68
69func tagFromStorageId(id string) (StorageTag, bool) {
70 // replace only the last "/" with "-".
71 i := strings.LastIndex(id, "/")
72 if i <= 0 || !IsValidStorage(id) {
73 return StorageTag{}, false
74 }
75 id = id[:i] + "-" + id[i+1:]
76 return StorageTag{id}, true
77}
78
79func storageTagSuffixToId(s string) string {
80 // Replace only the last "-" with "/", as it is valid for storage
81 // names to contain hyphens.
82 if i := strings.LastIndex(s, "-"); i > 0 {
83 s = s[:i] + "/" + s[i+1:]
84 }
85 return s
86}