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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
package linodego
import (
"context"
"encoding/json"
"errors"
)
// Tag represents a Tag object
type Tag struct {
Label string `json:"label"`
}
// TaggedObject represents a Tagged Object object
type TaggedObject struct {
Type string `json:"type"`
RawData json.RawMessage `json:"data"`
Data any `json:"-"`
}
// SortedObjects currently only includes Instances
type SortedObjects struct {
Instances []Instance
LKEClusters []LKECluster
Domains []Domain
Volumes []Volume
NodeBalancers []NodeBalancer
/*
StackScripts []Stackscript
*/
}
// TaggedObjectList are a list of TaggedObjects, as returning by ListTaggedObjects
type TaggedObjectList []TaggedObject
// TagCreateOptions fields are those accepted by CreateTag
type TagCreateOptions struct {
Label string `json:"label"`
Linodes []int `json:"linodes,omitempty"`
// @TODO is this implemented?
LKEClusters []int `json:"lke_clusters,omitempty"`
Domains []int `json:"domains,omitempty"`
Volumes []int `json:"volumes,omitempty"`
NodeBalancers []int `json:"nodebalancers,omitempty"`
}
// GetCreateOptions converts a Tag to TagCreateOptions for use in CreateTag
func (i Tag) GetCreateOptions() (o TagCreateOptions) {
o.Label = i.Label
return
}
// ListTags lists Tags
func (c *Client) ListTags(ctx context.Context, opts *ListOptions) ([]Tag, error) {
return getPaginatedResults[Tag](ctx, c, "tags", opts)
}
// fixData stores an object of the type defined by Type in Data using RawData
func (i *TaggedObject) fixData() (*TaggedObject, error) {
switch i.Type {
case "linode":
obj := Instance{}
if err := json.Unmarshal(i.RawData, &obj); err != nil {
return nil, err
}
i.Data = obj
case "lke_cluster":
obj := LKECluster{}
if err := json.Unmarshal(i.RawData, &obj); err != nil {
return nil, err
}
i.Data = obj
case "nodebalancer":
obj := NodeBalancer{}
if err := json.Unmarshal(i.RawData, &obj); err != nil {
return nil, err
}
i.Data = obj
case "domain":
obj := Domain{}
if err := json.Unmarshal(i.RawData, &obj); err != nil {
return nil, err
}
i.Data = obj
case "volume":
obj := Volume{}
if err := json.Unmarshal(i.RawData, &obj); err != nil {
return nil, err
}
i.Data = obj
}
return i, nil
}
// ListTaggedObjects lists Tagged Objects
func (c *Client) ListTaggedObjects(ctx context.Context, label string, opts *ListOptions) (TaggedObjectList, error) {
response, err := getPaginatedResults[TaggedObject](ctx, c, formatAPIPath("tags/%s", label), opts)
if err != nil {
return nil, err
}
for i := range response {
if _, err := response[i].fixData(); err != nil {
return nil, err
}
}
return response, nil
}
// SortedObjects converts a list of TaggedObjects into a Sorted Objects struct, for easier access
func (t TaggedObjectList) SortedObjects() (SortedObjects, error) {
so := SortedObjects{}
for _, o := range t {
switch o.Type {
case "linode":
if instance, ok := o.Data.(Instance); ok {
so.Instances = append(so.Instances, instance)
} else {
return so, errors.New("expected an Instance when Type was \"linode\"")
}
case "lke_cluster":
if lkeCluster, ok := o.Data.(LKECluster); ok {
so.LKEClusters = append(so.LKEClusters, lkeCluster)
} else {
return so, errors.New("expected an LKECluster when Type was \"lke_cluster\"")
}
case "domain":
if domain, ok := o.Data.(Domain); ok {
so.Domains = append(so.Domains, domain)
} else {
return so, errors.New("expected a Domain when Type was \"domain\"")
}
case "volume":
if volume, ok := o.Data.(Volume); ok {
so.Volumes = append(so.Volumes, volume)
} else {
return so, errors.New("expected an Volume when Type was \"volume\"")
}
case "nodebalancer":
if nodebalancer, ok := o.Data.(NodeBalancer); ok {
so.NodeBalancers = append(so.NodeBalancers, nodebalancer)
} else {
return so, errors.New("expected an NodeBalancer when Type was \"nodebalancer\"")
}
}
}
return so, nil
}
// CreateTag creates a Tag
func (c *Client) CreateTag(ctx context.Context, opts TagCreateOptions) (*Tag, error) {
return doPOSTRequest[Tag](ctx, c, "tags", opts)
}
// DeleteTag deletes the Tag with the specified id
func (c *Client) DeleteTag(ctx context.Context, label string) error {
e := formatAPIPath("tags/%s", label)
return doDELETERequest(ctx, c, e)
}
|