Skip to content

Commit 0007ee1

Browse files
authored
feat: Add latest_policy to storage block of docker hosted repository (datadrivers#460)
related to datadrivers#341
1 parent fcc6686 commit 0007ee1

11 files changed

+130
-17
lines changed

docs/data-sources/repository_docker_hosted.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ data "nexus_repository_docker_hosted" "example" {
2626
- `docker` (List of Object) docker contains the configuration of the docker repository (see [below for nested schema](#nestedatt--docker))
2727
- `id` (String) Used to identify data source at nexus
2828
- `online` (Boolean) Whether this repository accepts incoming requests
29-
- `storage` (List of Object) The storage configuration of the repository (see [below for nested schema](#nestedatt--storage))
29+
- `storage` (List of Object) The storage configuration of the repository docker hosted (see [below for nested schema](#nestedatt--storage))
3030

3131
<a id="nestedatt--cleanup"></a>
3232
### Nested Schema for `cleanup`
@@ -62,5 +62,6 @@ Read-Only:
6262
Read-Only:
6363

6464
- `blob_store_name` (String)
65+
- `latest_policy` (Boolean)
6566
- `strict_content_type_validation` (Boolean)
6667
- `write_policy` (String)

docs/resources/repository_docker_hosted.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ resource "nexus_repository_docker_hosted" "example" {
3232

3333
- `docker` (Block List, Min: 1, Max: 1) docker contains the configuration of the docker repository (see [below for nested schema](#nestedblock--docker))
3434
- `name` (String) A unique identifier for this repository
35-
- `storage` (Block List, Min: 1, Max: 1) The storage configuration of the repository (see [below for nested schema](#nestedblock--storage))
35+
- `storage` (Block List, Min: 1, Max: 1) The storage configuration of the repository docker hosted (see [below for nested schema](#nestedblock--storage))
3636

3737
### Optional
3838

@@ -69,6 +69,7 @@ Required:
6969

7070
Optional:
7171

72+
- `latest_policy` (Boolean) Whether to allow redeploying the 'latest' tag but defer to the Deployment Policy for all other tags. Only usable with write_policy "ALLOW_ONCE"
7273
- `write_policy` (String) Controls if deployments of and updates to assets are allowed
7374

7475

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ toolchain go1.21.1
66

77
require (
88
github.com/client9/misspell v0.3.4
9-
github.com/datadrivers/go-nexus-client v1.11.0
9+
github.com/datadrivers/go-nexus-client v1.12.0
1010
github.com/golangci/golangci-lint v1.59.1
1111
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
1212
github.com/hashicorp/terraform-plugin-docs v0.19.4

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53E
156156
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
157157
github.com/daixiang0/gci v0.13.4 h1:61UGkmpoAcxHM2hhNkZEf5SzwQtWJXTSws7jaPyqwlw=
158158
github.com/daixiang0/gci v0.13.4/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk=
159-
github.com/datadrivers/go-nexus-client v1.11.0 h1:fTmBYPzPBLL8v1LQOc8Fyzz40lHDl3Bm3ofvpNdHRro=
160-
github.com/datadrivers/go-nexus-client v1.11.0/go.mod h1:sPjBOxF7idUoiJoa730L3JyKZodjT0LDAvVF8u4kOLU=
159+
github.com/datadrivers/go-nexus-client v1.12.0 h1:ZBoTNAxdWbPs5gYZemJ+HLfk/8xt7aZyPtI1/R7ahag=
160+
github.com/datadrivers/go-nexus-client v1.12.0/go.mod h1:sPjBOxF7idUoiJoa730L3JyKZodjT0LDAvVF8u4kOLU=
161161
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
162162
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
163163
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

internal/acceptance/template-strings-repository-docker.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ resource "nexus_repository_docker_hosted" "acceptance" {
1616
{{- end }}
1717
v1_enabled = "{{ .Docker.V1Enabled }}"
1818
}
19-
` + TemplateStringHostedRepository
19+
` + TemplateStringNameOnline +
20+
TemplateStringCleanup +
21+
TemplateStringComponent +
22+
TemplateStringDockerStorageHosted +
23+
TemplateStringEnd
2024

2125
TemplateStringRepositoryDockerGroup = `
2226
resource "nexus_repository_docker_group" "acceptance" {
@@ -61,4 +65,17 @@ resource "nexus_repository_docker_proxy" "acceptance" {
6165
{{- end }}
6266
}
6367
` + TemplateStringProxyRepository
68+
69+
TemplateStringDockerStorageHosted = `
70+
storage {
71+
blob_store_name = "{{ .Storage.BlobStoreName }}"
72+
strict_content_type_validation = {{ .Storage.StrictContentTypeValidation }}
73+
{{- if .Storage.WritePolicy }}
74+
write_policy = "{{ .Storage.WritePolicy }}"
75+
{{- end }}
76+
{{- if .Storage.LatestPolicy }}
77+
latest_policy = "{{ .Storage.LatestPolicy }}"
78+
{{- end }}
79+
}
80+
`
6481
)

internal/schema/repository/schema_docker.go

+72
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package repository
22

33
import (
4+
"strings"
5+
46
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
58
)
69

710
var (
@@ -74,4 +77,73 @@ var (
7477
},
7578
},
7679
}
80+
81+
ResourceDockerHostedStorage = &schema.Schema{
82+
Description: "The storage configuration of the repository docker hosted",
83+
Type: schema.TypeList,
84+
Required: true,
85+
MaxItems: 1,
86+
Elem: &schema.Resource{
87+
Schema: map[string]*schema.Schema{
88+
"blob_store_name": {
89+
Description: "Blob store used to store repository contents",
90+
Required: true,
91+
Set: func(v interface{}) int {
92+
return schema.HashString(strings.ToLower(v.(string)))
93+
},
94+
Type: schema.TypeString,
95+
},
96+
"strict_content_type_validation": {
97+
Description: "Whether to validate uploaded content's MIME type appropriate for the repository format",
98+
Required: true,
99+
Type: schema.TypeBool,
100+
},
101+
"write_policy": {
102+
Description: "Controls if deployments of and updates to assets are allowed",
103+
Default: "ALLOW",
104+
Optional: true,
105+
Type: schema.TypeString,
106+
ValidateFunc: validation.StringInSlice([]string{
107+
"ALLOW",
108+
"ALLOW_ONCE",
109+
"DENY",
110+
}, false),
111+
},
112+
"latest_policy": {
113+
Description: "Whether to allow redeploying the 'latest' tag but defer to the Deployment Policy for all other tags. Only usable with write_policy \"ALLOW_ONCE\"",
114+
Optional: true,
115+
Type: schema.TypeBool,
116+
},
117+
},
118+
},
119+
}
120+
DataSourceDockerHostedStorage = &schema.Schema{
121+
Description: "The storage configuration of the repository docker hosted",
122+
Type: schema.TypeList,
123+
Computed: true,
124+
Elem: &schema.Resource{
125+
Schema: map[string]*schema.Schema{
126+
"blob_store_name": {
127+
Description: "Blob store used to store repository contents",
128+
Computed: true,
129+
Type: schema.TypeString,
130+
},
131+
"strict_content_type_validation": {
132+
Description: "Whether to validate uploaded content's MIME type appropriate for the repository format",
133+
Computed: true,
134+
Type: schema.TypeBool,
135+
},
136+
"write_policy": {
137+
Description: "Controls if deployments of and updates to assets are allowed",
138+
Computed: true,
139+
Type: schema.TypeString,
140+
},
141+
"latest_policy": {
142+
Description: "Whether to allow redeploying the 'latest' tag but defer to the Deployment Policy for all other tags. Only usable with write_policy \"ALLOW_ONCE\"",
143+
Computed: true,
144+
Type: schema.TypeBool,
145+
},
146+
},
147+
},
148+
}
77149
)

internal/services/repository/data_source_repository_docker_hosted.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func DataSourceRepositoryDockerHosted() *schema.Resource {
1919
// Hosted schemas
2020
"cleanup": repository.DataSourceCleanup,
2121
"component": repository.DataSourceComponent,
22-
"storage": repository.DataSourceHostedStorage,
22+
"storage": repository.DataSourceDockerHostedStorage,
2323
// Docker hosted schemas
2424
"docker": repository.DataSourceDocker,
2525
},

internal/services/repository/data_source_repository_docker_hosted_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ func TestAccDataSourceRepositoryDockerHosted(t *testing.T) {
2828
repo := repository.DockerHostedRepository{
2929
Name: name,
3030
Online: true,
31-
Storage: repository.HostedStorage{
31+
Storage: repository.DockerHostedStorage{
3232
BlobStoreName: "default",
3333
StrictContentTypeValidation: false,
34+
WritePolicy: "ALLOW",
3435
},
3536
Docker: repository.Docker{
3637
ForceBasicAuth: true,
@@ -56,6 +57,7 @@ func TestAccDataSourceRepositoryDockerHosted(t *testing.T) {
5657
resource.TestCheckResourceAttr(dataSourceName, "docker.0.v1_enabled", strconv.FormatBool(repo.Docker.V1Enabled)),
5758
resource.TestCheckResourceAttr(dataSourceName, "storage.0.blob_store_name", repo.Storage.BlobStoreName),
5859
resource.TestCheckResourceAttr(dataSourceName, "storage.0.strict_content_type_validation", strconv.FormatBool(repo.Storage.StrictContentTypeValidation)),
60+
resource.TestCheckResourceAttr(dataSourceName, "storage.0.write_policy", string(repo.Storage.WritePolicy)),
5961
),
6062
),
6163
},

internal/services/repository/flatten.go

+15
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,21 @@ func flattenHostedStorage(storage *repository.HostedStorage) []map[string]interf
212212
return []map[string]interface{}{data}
213213
}
214214

215+
func flattenDockerHostedStorage(dockerStorage *repository.DockerHostedStorage) []map[string]interface{} {
216+
if dockerStorage == nil {
217+
return nil
218+
}
219+
data := map[string]interface{}{
220+
"blob_store_name": dockerStorage.BlobStoreName,
221+
"strict_content_type_validation": dockerStorage.StrictContentTypeValidation,
222+
"write_policy": dockerStorage.WritePolicy,
223+
}
224+
if dockerStorage.LatestPolicy != nil {
225+
data["latest_policy"] = dockerStorage.LatestPolicy
226+
}
227+
return []map[string]interface{}{data}
228+
}
229+
215230
func flattenMaven(maven *repository.Maven) []map[string]interface{} {
216231
data := map[string]interface{}{
217232
"version_policy": maven.VersionPolicy,

internal/services/repository/resource_repository_docker_hosted.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func ResourceRepositoryDockerHosted() *schema.Resource {
3030
// Hosted schemas
3131
"cleanup": repositorySchema.ResourceCleanup,
3232
"component": repositorySchema.ResourceComponent,
33-
"storage": repositorySchema.ResourceHostedStorage,
33+
"storage": repositorySchema.ResourceDockerHostedStorage,
3434
// Docker hosted schemas
3535
"docker": repositorySchema.ResourceDocker,
3636
},
@@ -39,23 +39,26 @@ func ResourceRepositoryDockerHosted() *schema.Resource {
3939

4040
func getDockerHostedRepositoryFromResourceData(resourceData *schema.ResourceData) repository.DockerHostedRepository {
4141
storageConfig := resourceData.Get("storage").([]interface{})[0].(map[string]interface{})
42-
writePolicy := repository.StorageWritePolicy(storageConfig["write_policy"].(string))
4342
dockerConfig := resourceData.Get("docker").([]interface{})[0].(map[string]interface{})
4443

4544
repo := repository.DockerHostedRepository{
4645
Name: resourceData.Get("name").(string),
4746
Online: resourceData.Get("online").(bool),
48-
Storage: repository.HostedStorage{
47+
Storage: repository.DockerHostedStorage{
4948
BlobStoreName: storageConfig["blob_store_name"].(string),
5049
StrictContentTypeValidation: storageConfig["strict_content_type_validation"].(bool),
51-
WritePolicy: &writePolicy,
50+
WritePolicy: repository.StorageWritePolicy(storageConfig["write_policy"].(string)),
5251
},
5352
Docker: repository.Docker{
5453
ForceBasicAuth: dockerConfig["force_basic_auth"].(bool),
5554
V1Enabled: dockerConfig["v1_enabled"].(bool),
5655
},
5756
}
5857

58+
if latestPolicy, ok := storageConfig["latest_policy"]; ok {
59+
repo.Storage.LatestPolicy = tools.GetBoolPointer(latestPolicy.(bool))
60+
}
61+
5962
if httpPort, ok := dockerConfig["http_port"]; ok {
6063
if httpPort.(int) > 0 {
6164
repo.Docker.HTTPPort = tools.GetIntPointer(httpPort.(int))
@@ -109,7 +112,7 @@ func setDockerHostedRepositoryToResourceData(repo *repository.DockerHostedReposi
109112
return err
110113
}
111114

112-
if err := resourceData.Set("storage", flattenHostedStorage(&repo.Storage)); err != nil {
115+
if err := resourceData.Set("storage", flattenDockerHostedStorage(&repo.Storage)); err != nil {
113116
return err
114117
}
115118

internal/services/repository/resource_repository_docker_hosted_test.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
)
1717

1818
func testAccResourceRepositoryDockerHosted(name string) repository.DockerHostedRepository {
19-
writePolicy := repository.StorageWritePolicyAllow
19+
latestPolicy := true
2020

2121
return repository.DockerHostedRepository{
2222
Name: name,
@@ -27,10 +27,11 @@ func testAccResourceRepositoryDockerHosted(name string) repository.DockerHostedR
2727
HTTPSPort: tools.GetIntPointer(rand.Intn(999) + 33000),
2828
V1Enabled: false,
2929
},
30-
Storage: repository.HostedStorage{
30+
Storage: repository.DockerHostedStorage{
3131
BlobStoreName: "default",
3232
StrictContentTypeValidation: true,
33-
WritePolicy: &writePolicy,
33+
WritePolicy: repository.StorageWritePolicyAllowOnce,
34+
LatestPolicy: &latestPolicy,
3435
},
3536
Cleanup: &repository.Cleanup{
3637
PolicyNames: []string{"cleanup-weekly"},
@@ -77,7 +78,8 @@ func TestAccResourceRepositoryDockerHosted(t *testing.T) {
7778
resource.TestCheckResourceAttr(resourceName, "storage.#", "1"),
7879
resource.TestCheckResourceAttr(resourceName, "storage.0.blob_store_name", repo.Storage.BlobStoreName),
7980
resource.TestCheckResourceAttr(resourceName, "storage.0.strict_content_type_validation", strconv.FormatBool(repo.Storage.StrictContentTypeValidation)),
80-
resource.TestCheckResourceAttr(resourceName, "storage.0.write_policy", string(*repo.Storage.WritePolicy)),
81+
resource.TestCheckResourceAttr(resourceName, "storage.0.write_policy", string(repo.Storage.WritePolicy)),
82+
resource.TestCheckResourceAttr(resourceName, "storage.0.latest_policy", strconv.FormatBool(*repo.Storage.LatestPolicy)),
8183
resource.TestCheckResourceAttr(resourceName, "cleanup.#", "1"),
8284
resource.TestCheckResourceAttr(resourceName, "cleanup.0.policy_names.#", "1"),
8385
resource.TestCheckResourceAttr(resourceName, "cleanup.0.policy_names.0", repo.Cleanup.PolicyNames[0]),

0 commit comments

Comments
 (0)