forked from viamrobotics/rdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathname.go
142 lines (127 loc) · 3.38 KB
/
name.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package resource
import (
"encoding/json"
"fmt"
"strings"
"github.com/pkg/errors"
)
// Name represents a known component/service representation of a robot.
type Name struct {
API API
Remote string
Name string
}
// NewName creates a new resource Name.
func NewName(api API, name string) Name {
r := strings.Split(name, ":")
remote := strings.Join(r[0:len(r)-1], ":")
nameIdent := r[len(r)-1]
return Name{
API: api,
Name: nameIdent,
Remote: remote,
}
}
// UnmarshalJSON unmarshals a resource name from a string.
func (n *Name) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
newN, err := NewFromString(s)
if err != nil {
return err
}
*n = newN
return nil
}
// newRemoteName creates a new Name for a resource attached to a remote.
func newRemoteName(remoteName string, api API, name string) Name {
n := NewName(api, name)
n.Remote = remoteName
return n
}
// NewFromString creates a new Name based on a fully qualified resource name string passed in.
func NewFromString(resourceName string) (Name, error) {
if !resRegexValidator.MatchString(resourceName) {
return Name{}, errors.Errorf("string %q is not a valid resource name", resourceName)
}
matches := resRegexValidator.FindStringSubmatch(resourceName)
rAPIParts := strings.Split(matches[1], ":")
remoteName := matches[2]
if len(remoteName) > 0 {
remoteName = remoteName[:len(remoteName)-1]
}
api := APINamespace(rAPIParts[0]).WithType(rAPIParts[1]).WithSubtype(rAPIParts[2])
return newRemoteName(remoteName, api, matches[3]), nil
}
// PrependRemote returns a Name with a remote prepended.
func (n Name) PrependRemote(remoteName string) Name {
if remoteName == "" {
return n
}
if len(n.Remote) > 0 {
remoteName = strings.Join([]string{remoteName, n.Remote}, ":")
}
return newRemoteName(
remoteName,
n.API,
n.Name)
}
// PopRemote pop the first remote from a Name (if any) and returns the new Name.
func (n Name) PopRemote() Name {
if n.Remote == "" {
return n
}
remotes := strings.Split(n.Remote, ":")
return newRemoteName(
strings.Join(remotes[1:], ":"),
n.API,
n.Name)
}
// ContainsRemoteNames return true if the resource is a remote resource.
func (n Name) ContainsRemoteNames() bool {
return len(n.Remote) > 0
}
// AsNamed is a helper to let this name return itself as a basic resource that does
// nothing.
func (n Name) AsNamed() Named {
return selfNamed{n}
}
// RemoveRemoteName returns a new name with remote removed.
func RemoveRemoteName(n Name) Name {
tempName := NewName(n.API, n.Name)
tempName.Remote = ""
return tempName
}
// ShortName returns the short name on Name n in the form of <remote>:<name>.
func (n Name) ShortName() string {
nameR := n.Name
if n.Remote != "" {
nameR = fmt.Sprintf("%s:%s", n.Remote, nameR)
}
return nameR
}
// Validate ensures that important fields exist and are valid.
func (n Name) Validate() error {
if n.Name == "" {
return errors.New("name field for resource is empty")
}
if err := n.API.Validate(); err != nil {
return err
}
if err := ContainsReservedCharacter(n.Name); err != nil {
return err
}
return nil
}
// String returns the fully qualified name for the resource.
func (n Name) String() string {
name := n.API.String()
if n.Remote != "" {
name = fmt.Sprintf("%s/%s:%s", name, n.Remote, n.Name)
} else {
name = fmt.Sprintf("%s/%s", name, n.Name)
}
return name
}