Skip to content

Commit baa712b

Browse files
authored
feat: add methods for managing reserved tag keys (#1145)
* feat: add methods for managing reserved tag keys * chore: appease linter * chore: update changelog * chore: incorporate review feedback
1 parent d6e26fd commit baa712b

File tree

5 files changed

+465
-0
lines changed

5 files changed

+465
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Unreleased
22

3+
## Enhancements
4+
5+
* Adds support for managing reserved tag keys within a TFE organization, by @ctrombley [#1145](https://github.com/hashicorp/go-tfe/pull/1145)
6+
37
# v1.84.0
48

59
## Enhancements

errors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ var (
123123

124124
ErrInvalidPagination = errors.New("invalid value for page size or number")
125125

126+
ErrInvalidReservedTagKeyID = errors.New("invalid value for reserved tag key ID")
127+
126128
ErrInvalidRunTaskCategory = errors.New(`category must be "task"`)
127129

128130
ErrInvalidRunTaskID = errors.New("invalid value for run task ID")

reserved_tag_key.go

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package tfe
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"net/url"
10+
"time"
11+
)
12+
13+
// Compile-time proof of interface implementation.
14+
var _ ReservedTagKeys = (*reservedTagKeys)(nil)
15+
16+
// ReservedTagKeys describes all the reserved tag key endpoints that the
17+
// Terraform Enterprise API supports.
18+
//
19+
// TFE API docs: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/reserved-tag-keys
20+
type ReservedTagKeys interface {
21+
// List all the reserved tag keys for the given organization.
22+
List(ctx context.Context, organization string, options *ReservedTagKeyListOptions) (*ReservedTagKeyList, error)
23+
24+
// Create a new reserved tag key for the given organization.
25+
Create(ctx context.Context, organization string, options ReservedTagKeyCreateOptions) (*ReservedTagKey, error)
26+
27+
// Update the reserved tag key with the given ID.
28+
Update(ctx context.Context, reservedTagKeyID string, options ReservedTagKeyUpdateOptions) (*ReservedTagKey, error)
29+
30+
// Delete the reserved tag key with the given ID.
31+
Delete(ctx context.Context, reservedTagKeyID string) error
32+
}
33+
34+
// reservedTagKeys implements ReservedTagKeys.
35+
type reservedTagKeys struct {
36+
client *Client
37+
}
38+
39+
// ReservedTagKeyList represents a list of reserved tag keys.
40+
type ReservedTagKeyList struct {
41+
*Pagination
42+
Items []*ReservedTagKey
43+
}
44+
45+
// ReservedTagKey represents a Terraform Enterprise reserved tag key.
46+
type ReservedTagKey struct {
47+
ID string `jsonapi:"primary,reserved-tag-keys"`
48+
Key string `jsonapi:"attr,key"`
49+
DisableOverrides bool `jsonapi:"attr,disable-overrides"`
50+
CreatedAt time.Time `jsonapi:"attr,created_at,iso8601"`
51+
UpdatedAt time.Time `jsonapi:"attr,updated_at,iso8601"`
52+
}
53+
54+
// ReservedTagKeyListOptions represents the options for listing reserved tag
55+
// keys.
56+
type ReservedTagKeyListOptions struct {
57+
ListOptions
58+
}
59+
60+
// List all the reserved tag keys for the given organization.
61+
func (s *reservedTagKeys) List(ctx context.Context, organization string, options *ReservedTagKeyListOptions) (*ReservedTagKeyList, error) {
62+
if !validStringID(&organization) {
63+
return nil, ErrInvalidOrg
64+
}
65+
66+
u := fmt.Sprintf("organizations/%s/reserved-tag-keys", url.PathEscape(organization))
67+
68+
req, err := s.client.NewRequest("GET", u, options)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
rl := &ReservedTagKeyList{}
74+
err = req.Do(ctx, rl)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
return rl, nil
80+
}
81+
82+
// ReservedTagKeyCreateOptions represents the options for creating a
83+
// reserved tag key.
84+
type ReservedTagKeyCreateOptions struct {
85+
// Type is a public field utilized by JSON:API to
86+
// set the resource type via the field tag.
87+
// It is not a user-defined value and does not need to be set.
88+
// https://jsonapi.org/format/#crud-creating
89+
Type string `jsonapi:"primary,reserved-tag-keys"`
90+
91+
// Required: The reserved tag key's key string.
92+
Key string `jsonapi:"attr,key"`
93+
94+
// Optional: When true, project tag bindings that match this reserved tag key can not
95+
// be overridden at the workspace level.
96+
DisableOverrides *bool `jsonapi:"attr,disable-overrides,omitempty"`
97+
}
98+
99+
func (o ReservedTagKeyCreateOptions) valid() error {
100+
if !validString(&o.Key) {
101+
return ErrRequiredKey
102+
}
103+
return nil
104+
}
105+
106+
// Create a reserved tag key.
107+
func (s *reservedTagKeys) Create(ctx context.Context, organization string, options ReservedTagKeyCreateOptions) (*ReservedTagKey, error) {
108+
if !validStringID(&organization) {
109+
return nil, ErrInvalidOrg
110+
}
111+
112+
if err := options.valid(); err != nil {
113+
return nil, err
114+
}
115+
116+
u := fmt.Sprintf("organizations/%s/reserved-tag-keys", url.PathEscape(organization))
117+
req, err := s.client.NewRequest("POST", u, &options)
118+
if err != nil {
119+
return nil, err
120+
}
121+
122+
r := &ReservedTagKey{}
123+
err = req.Do(ctx, r)
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
return r, nil
129+
}
130+
131+
// ReservedTagKeyUpdateOptions represents the options for updating a
132+
// reserved tag key.
133+
type ReservedTagKeyUpdateOptions struct {
134+
// Type is a public field utilized by JSON:API to
135+
// set the resource type via the field tag.
136+
// It is not a user-defined value and does not need to be set.
137+
// https://jsonapi.org/format/#crud-creating
138+
Type string `jsonapi:"primary,reserved-tag-keys"`
139+
140+
// Optional: The reserved tag key's key string.
141+
Key *string `jsonapi:"attr,key,omitempty"`
142+
143+
// Optional: When true, project tag bindings that match this reserved tag key can not
144+
// be overridden at the workspace level.
145+
DisableOverrides *bool `jsonapi:"attr,disable-overrides,omitempty"`
146+
}
147+
148+
// Update the reserved tag key with the given ID.
149+
func (s *reservedTagKeys) Update(ctx context.Context, reservedTagKeyID string, options ReservedTagKeyUpdateOptions) (*ReservedTagKey, error) {
150+
if !validStringID(&reservedTagKeyID) {
151+
return nil, ErrInvalidReservedTagKeyID
152+
}
153+
154+
u := fmt.Sprintf("reserved-tag-keys/%s", url.PathEscape(reservedTagKeyID))
155+
req, err := s.client.NewRequest("PATCH", u, &options)
156+
if err != nil {
157+
return nil, err
158+
}
159+
160+
r := &ReservedTagKey{}
161+
err = req.Do(ctx, r)
162+
if err != nil {
163+
return nil, err
164+
}
165+
166+
return r, nil
167+
}
168+
169+
// Delete the reserved tag key with the given ID.
170+
func (s *reservedTagKeys) Delete(ctx context.Context, reservedTagKeyID string) error {
171+
if !validStringID(&reservedTagKeyID) {
172+
return ErrInvalidReservedTagKeyID
173+
}
174+
175+
u := fmt.Sprintf("reserved-tag-keys/%s", url.PathEscape(reservedTagKeyID))
176+
req, err := s.client.NewRequest("DELETE", u, nil)
177+
if err != nil {
178+
return err
179+
}
180+
181+
return req.Do(ctx, nil)
182+
}

0 commit comments

Comments
 (0)