Skip to content

Commit f0f6760

Browse files
authored
Merge pull request #1090 from hashicorp/ntodd/tf-25570/use-arch-fields-for-opa-and-sentinel-requests
[TF-25570] Add Archs Field to OPA and Sentinel Admin Versions
2 parents 461e134 + edb5e75 commit f0f6760

8 files changed

+328
-94
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
* Updates team token `Description` to be a pointer, allowing for both nil descriptions and empty string descriptions. Team token descriptions and the ability to create multiple team tokens is in BETA, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users, by @mkam [#1088](https://github.com/hashicorp/go-tfe/pull/1088)
88

9+
## Enhancements
10+
11+
* Add BETA support for use of OPA and Sentinel with Linux arm64 agents, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users @natalie-todd [#1090](https://github.com/hashicorp/go-tfe/pull/1090)
12+
913
# v1.78.0
1014

1115
## Enhancements

admin_opa_version.go

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"fmt"
99
"net/url"
10+
"reflect"
1011
"time"
1112
)
1213

@@ -42,17 +43,18 @@ type adminOPAVersions struct {
4243

4344
// AdminOPAVersion represents a OPA Version
4445
type AdminOPAVersion struct {
45-
ID string `jsonapi:"primary,opa-versions"`
46-
Version string `jsonapi:"attr,version"`
47-
URL string `jsonapi:"attr,url"`
48-
SHA string `jsonapi:"attr,sha"`
49-
Deprecated bool `jsonapi:"attr,deprecated"`
50-
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
51-
Official bool `jsonapi:"attr,official"`
52-
Enabled bool `jsonapi:"attr,enabled"`
53-
Beta bool `jsonapi:"attr,beta"`
54-
Usage int `jsonapi:"attr,usage"`
55-
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
46+
ID string `jsonapi:"primary,opa-versions"`
47+
Version string `jsonapi:"attr,version"`
48+
URL string `jsonapi:"attr,url,omitempty"`
49+
SHA string `jsonapi:"attr,sha,omitempty"`
50+
Deprecated bool `jsonapi:"attr,deprecated"`
51+
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
52+
Official bool `jsonapi:"attr,official"`
53+
Enabled bool `jsonapi:"attr,enabled"`
54+
Beta bool `jsonapi:"attr,beta"`
55+
Usage int `jsonapi:"attr,usage"`
56+
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
57+
Archs []*ToolVersionArchitecture `jsonapi:"attr,archs,omitempty"`
5658
}
5759

5860
// AdminOPAVersionsListOptions represents the options for listing
@@ -69,28 +71,30 @@ type AdminOPAVersionsListOptions struct {
6971

7072
// AdminOPAVersionCreateOptions for creating an OPA version.
7173
type AdminOPAVersionCreateOptions struct {
72-
Type string `jsonapi:"primary,opa-versions"`
73-
Version string `jsonapi:"attr,version"` // Required
74-
URL string `jsonapi:"attr,url"` // Required
75-
SHA string `jsonapi:"attr,sha"` // Required
76-
Official *bool `jsonapi:"attr,official,omitempty"`
77-
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
78-
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
79-
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
80-
Beta *bool `jsonapi:"attr,beta,omitempty"`
74+
Type string `jsonapi:"primary,opa-versions"`
75+
Version string `jsonapi:"attr,version"` // Required
76+
URL string `jsonapi:"attr,url,omitempty"` // Required w/ SHA unless Archs are provided
77+
SHA string `jsonapi:"attr,sha,omitempty"` // Required w/ URL unless Archs are provided
78+
Official *bool `jsonapi:"attr,official,omitempty"`
79+
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
80+
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
81+
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
82+
Beta *bool `jsonapi:"attr,beta,omitempty"`
83+
Archs []*ToolVersionArchitecture `jsonapi:"attr,archs,omitempty"` // Required unless URL and SHA are provided
8184
}
8285

8386
// AdminOPAVersionUpdateOptions for updating OPA version.
8487
type AdminOPAVersionUpdateOptions struct {
85-
Type string `jsonapi:"primary,opa-versions"`
86-
Version *string `jsonapi:"attr,version,omitempty"`
87-
URL *string `jsonapi:"attr,url,omitempty"`
88-
SHA *string `jsonapi:"attr,sha,omitempty"`
89-
Official *bool `jsonapi:"attr,official,omitempty"`
90-
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
91-
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
92-
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
93-
Beta *bool `jsonapi:"attr,beta,omitempty"`
88+
Type string `jsonapi:"primary,opa-versions"`
89+
Version *string `jsonapi:"attr,version,omitempty"`
90+
URL *string `jsonapi:"attr,url,omitempty"`
91+
SHA *string `jsonapi:"attr,sha,omitempty"`
92+
Official *bool `jsonapi:"attr,official,omitempty"`
93+
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
94+
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
95+
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
96+
Beta *bool `jsonapi:"attr,beta,omitempty"`
97+
Archs []*ToolVersionArchitecture `jsonapi:"attr,archs,omitempty"`
9498
}
9599

96100
// AdminOPAVersionsList represents a list of OPA versions.
@@ -192,18 +196,29 @@ func (a *adminOPAVersions) Delete(ctx context.Context, id string) error {
192196
}
193197

194198
func (o AdminOPAVersionCreateOptions) valid() error {
195-
if (o == AdminOPAVersionCreateOptions{}) {
199+
if (reflect.DeepEqual(o, AdminOPAVersionCreateOptions{})) {
196200
return ErrRequiredOPAVerCreateOps
197201
}
198202
if o.Version == "" {
199203
return ErrRequiredVersion
200204
}
201-
if o.URL == "" {
202-
return ErrRequiredURL
205+
if !o.validArch() {
206+
return ErrRequiredArchsOrURLAndSha
203207
}
204-
if o.SHA == "" {
205-
return ErrRequiredSha
208+
return nil
209+
}
210+
211+
func (o AdminOPAVersionCreateOptions) validArch() bool {
212+
if o.Archs == nil && o.URL != "" && o.SHA != "" {
213+
return true
206214
}
207215

208-
return nil
216+
emptyToolVersionFields := o.URL == "" && o.SHA == ""
217+
218+
for _, a := range o.Archs {
219+
if !validArch(a) || !emptyToolVersionFields && (o.URL != a.URL || o.SHA != a.Sha) {
220+
return false
221+
}
222+
}
223+
return true
209224
}

admin_opa_version_integration_test.go

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,45 @@ func TestAdminOPAVersions_CreateDelete(t *testing.T) {
102102
ctx := context.Background()
103103
version := createAdminOPAVersion()
104104

105-
t.Run("with valid options", func(t *testing.T) {
105+
t.Run("with valid options including archs", func(t *testing.T) {
106+
opts := AdminOPAVersionCreateOptions{
107+
Version: version,
108+
Deprecated: Bool(true),
109+
DeprecatedReason: String("Test Reason"),
110+
Official: Bool(false),
111+
Enabled: Bool(false),
112+
Beta: Bool(false),
113+
Archs: []*ToolVersionArchitecture{
114+
{
115+
URL: "https://www.hashicorp.com",
116+
Sha: *String(genSha(t)),
117+
OS: linux,
118+
Arch: amd64,
119+
},
120+
{
121+
URL: "https://www.hashicorp.com",
122+
Sha: *String(genSha(t)),
123+
OS: linux,
124+
Arch: arm64,
125+
}},
126+
}
127+
ov, err := client.Admin.OPAVersions.Create(ctx, opts)
128+
require.NoError(t, err)
129+
130+
defer func() {
131+
deleteErr := client.Admin.OPAVersions.Delete(ctx, ov.ID)
132+
require.NoError(t, deleteErr)
133+
}()
134+
135+
assert.Equal(t, opts.Version, ov.Version)
136+
assert.Equal(t, *opts.Official, ov.Official)
137+
assert.Equal(t, *opts.Deprecated, ov.Deprecated)
138+
assert.Equal(t, *opts.DeprecatedReason, *ov.DeprecatedReason)
139+
assert.Equal(t, *opts.Enabled, ov.Enabled)
140+
assert.Equal(t, *opts.Beta, ov.Beta)
141+
})
142+
143+
t.Run("with valid options including, url, and sha", func(t *testing.T) {
106144
opts := AdminOPAVersionCreateOptions{
107145
Version: version,
108146
URL: "https://www.hashicorp.com",
@@ -131,8 +169,8 @@ func TestAdminOPAVersions_CreateDelete(t *testing.T) {
131169
assert.Equal(t, *opts.Beta, ov.Beta)
132170
})
133171

134-
t.Run("with only required options", func(t *testing.T) {
135-
version := createAdminOPAVersion()
172+
t.Run("with only required options including tool version url and sha", func(t *testing.T) {
173+
version = createAdminOPAVersion()
136174
opts := AdminOPAVersionCreateOptions{
137175
Version: version,
138176
URL: "https://www.hashicorp.com",
@@ -156,6 +194,40 @@ func TestAdminOPAVersions_CreateDelete(t *testing.T) {
156194
assert.Equal(t, false, ov.Beta)
157195
})
158196

197+
t.Run("with only required options including archs", func(t *testing.T) {
198+
version = createAdminOPAVersion()
199+
opts := AdminOPAVersionCreateOptions{
200+
Version: version,
201+
Archs: []*ToolVersionArchitecture{
202+
{
203+
URL: "https://www.hashicorp.com",
204+
Sha: *String(genSha(t)),
205+
OS: linux,
206+
Arch: amd64,
207+
},
208+
{
209+
URL: "https://www.hashicorp.com",
210+
Sha: *String(genSha(t)),
211+
OS: linux,
212+
Arch: arm64,
213+
}},
214+
}
215+
ov, err := client.Admin.OPAVersions.Create(ctx, opts)
216+
require.NoError(t, err)
217+
218+
defer func() {
219+
deleteErr := client.Admin.OPAVersions.Delete(ctx, ov.ID)
220+
require.NoError(t, deleteErr)
221+
}()
222+
223+
assert.Equal(t, opts.Version, ov.Version)
224+
assert.Equal(t, false, ov.Official)
225+
assert.Equal(t, false, ov.Deprecated)
226+
assert.Nil(t, ov.DeprecatedReason)
227+
assert.Equal(t, true, ov.Enabled)
228+
assert.Equal(t, false, ov.Beta)
229+
})
230+
159231
t.Run("with empty options", func(t *testing.T) {
160232
_, err := client.Admin.OPAVersions.Create(ctx, AdminOPAVersionCreateOptions{})
161233
require.Equal(t, err, ErrRequiredOPAVerCreateOps)
@@ -170,6 +242,7 @@ func TestAdminOPAVersions_ReadUpdate(t *testing.T) {
170242

171243
t.Run("reads and updates", func(t *testing.T) {
172244
version := createAdminOPAVersion()
245+
sha := String(genSha(t))
173246
opts := AdminOPAVersionCreateOptions{
174247
Version: version,
175248
URL: "https://www.hashicorp.com",
@@ -179,6 +252,12 @@ func TestAdminOPAVersions_ReadUpdate(t *testing.T) {
179252
DeprecatedReason: String("Test Reason"),
180253
Enabled: Bool(false),
181254
Beta: Bool(false),
255+
Archs: []*ToolVersionArchitecture{{
256+
URL: "https://www.hashicorp.com",
257+
Sha: *sha,
258+
OS: linux,
259+
Arch: amd64,
260+
}},
182261
}
183262
ov, err := client.Admin.OPAVersions.Create(ctx, opts)
184263
require.NoError(t, err)
@@ -193,8 +272,8 @@ func TestAdminOPAVersions_ReadUpdate(t *testing.T) {
193272
require.NoError(t, err)
194273

195274
assert.Equal(t, opts.Version, ov.Version)
196-
assert.Equal(t, opts.URL, ov.URL)
197-
assert.Equal(t, opts.SHA, ov.SHA)
275+
assert.Equal(t, opts.Archs[0].URL, ov.URL)
276+
assert.Equal(t, opts.Archs[0].Sha, ov.SHA)
198277
assert.Equal(t, *opts.Official, ov.Official)
199278
assert.Equal(t, *opts.Deprecated, ov.Deprecated)
200279
assert.Equal(t, *opts.DeprecatedReason, *ov.DeprecatedReason)

admin_sentinel_version.go

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"fmt"
99
"net/url"
10+
"reflect"
1011
"time"
1112
)
1213

@@ -42,17 +43,18 @@ type adminSentinelVersions struct {
4243

4344
// AdminSentinelVersion represents a Sentinel Version
4445
type AdminSentinelVersion struct {
45-
ID string `jsonapi:"primary,sentinel-versions"`
46-
Version string `jsonapi:"attr,version"`
47-
URL string `jsonapi:"attr,url"`
48-
SHA string `jsonapi:"attr,sha"`
49-
Deprecated bool `jsonapi:"attr,deprecated"`
50-
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
51-
Official bool `jsonapi:"attr,official"`
52-
Enabled bool `jsonapi:"attr,enabled"`
53-
Beta bool `jsonapi:"attr,beta"`
54-
Usage int `jsonapi:"attr,usage"`
55-
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
46+
ID string `jsonapi:"primary,sentinel-versions"`
47+
Version string `jsonapi:"attr,version"`
48+
URL string `jsonapi:"attr,url,omitempty"`
49+
SHA string `jsonapi:"attr,sha,omitempty"`
50+
Deprecated bool `jsonapi:"attr,deprecated"`
51+
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
52+
Official bool `jsonapi:"attr,official"`
53+
Enabled bool `jsonapi:"attr,enabled"`
54+
Beta bool `jsonapi:"attr,beta"`
55+
Usage int `jsonapi:"attr,usage"`
56+
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
57+
Archs []*ToolVersionArchitecture `jsonapi:"attr,archs,omitempty"`
5658
}
5759

5860
// AdminSentinelVersionsListOptions represents the options for listing
@@ -69,28 +71,30 @@ type AdminSentinelVersionsListOptions struct {
6971

7072
// AdminSentinelVersionCreateOptions for creating an Sentinel version.
7173
type AdminSentinelVersionCreateOptions struct {
72-
Type string `jsonapi:"primary,sentinel-versions"`
73-
Version string `jsonapi:"attr,version"` // Required
74-
URL string `jsonapi:"attr,url"` // Required
75-
SHA string `jsonapi:"attr,sha"` // Required
76-
Official *bool `jsonapi:"attr,official,omitempty"`
77-
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
78-
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
79-
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
80-
Beta *bool `jsonapi:"attr,beta,omitempty"`
74+
Type string `jsonapi:"primary,sentinel-versions"`
75+
Version string `jsonapi:"attr,version"` // Required
76+
URL string `jsonapi:"attr,url,omitempty"` // Required w/ SHA unless Archs are provided
77+
SHA string `jsonapi:"attr,sha,omitempty"` // Required w/ URL unless Archs are provided
78+
Official *bool `jsonapi:"attr,official,omitempty"`
79+
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
80+
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
81+
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
82+
Beta *bool `jsonapi:"attr,beta,omitempty"`
83+
Archs []*ToolVersionArchitecture `jsonapi:"attr,archs,omitempty"` // Required unless URL and SHA are provided
8184
}
8285

8386
// AdminSentinelVersionUpdateOptions for updating Sentinel version.
8487
type AdminSentinelVersionUpdateOptions struct {
85-
Type string `jsonapi:"primary,sentinel-versions"`
86-
Version *string `jsonapi:"attr,version,omitempty"`
87-
URL *string `jsonapi:"attr,url,omitempty"`
88-
SHA *string `jsonapi:"attr,sha,omitempty"`
89-
Official *bool `jsonapi:"attr,official,omitempty"`
90-
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
91-
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
92-
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
93-
Beta *bool `jsonapi:"attr,beta,omitempty"`
88+
Type string `jsonapi:"primary,sentinel-versions"`
89+
Version *string `jsonapi:"attr,version,omitempty"`
90+
URL *string `jsonapi:"attr,url,omitempty"`
91+
SHA *string `jsonapi:"attr,sha,omitempty"`
92+
Official *bool `jsonapi:"attr,official,omitempty"`
93+
Deprecated *bool `jsonapi:"attr,deprecated,omitempty"`
94+
DeprecatedReason *string `jsonapi:"attr,deprecated-reason,omitempty"`
95+
Enabled *bool `jsonapi:"attr,enabled,omitempty"`
96+
Beta *bool `jsonapi:"attr,beta,omitempty"`
97+
Archs []*ToolVersionArchitecture `jsonapi:"attr,archs,omitempty"`
9498
}
9599

96100
// AdminSentinelVersionsList represents a list of Sentinel versions.
@@ -192,18 +196,29 @@ func (a *adminSentinelVersions) Delete(ctx context.Context, id string) error {
192196
}
193197

194198
func (o AdminSentinelVersionCreateOptions) valid() error {
195-
if (o == AdminSentinelVersionCreateOptions{}) {
199+
if (reflect.DeepEqual(o, AdminSentinelVersionCreateOptions{})) {
196200
return ErrRequiredSentinelVerCreateOps
197201
}
198202
if o.Version == "" {
199203
return ErrRequiredVersion
200204
}
201-
if o.URL == "" {
202-
return ErrRequiredURL
205+
if !o.validArch() {
206+
return ErrRequiredArchsOrURLAndSha
203207
}
204-
if o.SHA == "" {
205-
return ErrRequiredSha
208+
return nil
209+
}
210+
211+
func (o AdminSentinelVersionCreateOptions) validArch() bool {
212+
if o.Archs == nil && o.URL != "" && o.SHA != "" {
213+
return true
206214
}
207215

208-
return nil
216+
emptyToolVersionFields := o.URL == "" && o.SHA == ""
217+
218+
for _, a := range o.Archs {
219+
if !validArch(a) || !emptyToolVersionFields && (o.URL != a.URL || o.SHA != a.Sha) {
220+
return false
221+
}
222+
}
223+
return true
209224
}

0 commit comments

Comments
 (0)