Skip to content

Commit 18203a2

Browse files
feat: Support import for sonatyperepo_repository_p2_* resources (#177)
* hotfix: docker repository import error * simplify repository common for import and add docker import test * use common constant for errors * handle import for p2 repositories * follow docker repositories pattern
1 parent 66efe7f commit 18203a2

File tree

6 files changed

+101
-4
lines changed

6 files changed

+101
-4
lines changed

docs/resources/repository_p2_proxy.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,16 @@ Required:
122122
Optional:
123123

124124
- `asset_path_regex` (String) Regular Expression of Asset Paths to pull pre-emptively pull
125+
126+
## Import
127+
128+
Import is supported using the following syntax:
129+
130+
```shell
131+
# Existing proxy p2 repository configuration can be imported as follows.
132+
#
133+
# NOTE: The Identifier REPOSITORY_NAME needs to match repository name in your sonatype nexus repository instance.
134+
135+
# Example
136+
terraform import sonatyperepo_repository_p2_proxy.example REPOSITORY_NAME
137+
```
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Existing proxy p2 repository configuration can be imported as follows.
2+
#
3+
# NOTE: The Identifier REPOSITORY_NAME needs to match repository name in your sonatype nexus repository instance.
4+
5+
# Example
6+
terraform import sonatyperepo_repository_p2_proxy.example REPOSITORY_NAME

internal/provider/model/repository_p2.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package model
1818

1919
import (
20+
"terraform-provider-sonatyperepo/internal/provider/common"
21+
2022
"github.com/hashicorp/terraform-plugin-framework/types"
2123

2224
sonatyperepo "github.com/sonatype-nexus-community/nexus-repo-api-client-go/v3"
@@ -48,7 +50,14 @@ func (m *RepositoryP2ProxyModel) FromApiModel(api sonatyperepo.SimpleApiProxyRep
4850
m.HttpClient.MapFromApiHttpClientAttributes(&api.HttpClient)
4951
m.RoutingRule = types.StringPointerValue(api.RoutingRuleName)
5052
if api.Replication != nil {
53+
m.Replication = &RepositoryReplicationModel{}
5154
m.Replication.MapFromApi(api.Replication)
55+
} else {
56+
// Set default values when API doesn't provide replication data
57+
m.Replication = &RepositoryReplicationModel{
58+
PreemptivePullEnabled: types.BoolValue(common.DEFAULT_PROXY_PREEMPTIVE_PULL),
59+
AssetPathRegex: types.StringNull(),
60+
}
5261
}
5362
}
5463

internal/provider/repository/format/p2.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ func (f *P2RepositoryFormatProxy) DoReadRequest(state any, apiClient *sonatypere
6767

6868
// Call to API to Read
6969
apiResponse, httpResponse, err := apiClient.RepositoryManagementAPI.GetP2ProxyRepository(ctx, stateModel.Name.ValueString()).Execute()
70+
if err != nil {
71+
return nil, httpResponse, err
72+
}
7073
return *apiResponse, httpResponse, err
7174
}
7275

@@ -102,7 +105,21 @@ func (f *P2RepositoryFormatProxy) UpdatePlanForState(plan any) any {
102105
}
103106

104107
func (f *P2RepositoryFormatProxy) UpdateStateFromApi(state any, api any) any {
105-
stateModel := (state).(model.RepositoryP2ProxyModel)
108+
var stateModel model.RepositoryP2ProxyModel
109+
// During import, state might be nil, so we create a new model
110+
if state != nil {
111+
stateModel = (state).(model.RepositoryP2ProxyModel)
112+
}
106113
stateModel.FromApiModel((api).(sonatyperepo.SimpleApiProxyRepository))
107114
return stateModel
108115
}
116+
117+
// DoImportRequest implements the import functionality for P2 Proxy repositories
118+
func (f *P2RepositoryFormatProxy) DoImportRequest(repositoryName string, apiClient *sonatyperepo.APIClient, ctx context.Context) (any, *http.Response, error) {
119+
// Call to API to Read repository for import
120+
apiResponse, httpResponse, err := apiClient.RepositoryManagementAPI.GetP2ProxyRepository(ctx, repositoryName).Execute()
121+
if err != nil {
122+
return nil, httpResponse, err
123+
}
124+
return *apiResponse, httpResponse, nil
125+
}

internal/provider/repository/repository_common.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ func (r *repositoryResource) ImportState(ctx context.Context, req resource.Impor
381381
if httpResponse != nil && httpResponse.StatusCode == http.StatusNotFound {
382382
resp.Diagnostics.AddError(
383383
fmt.Sprintf("Repository '%s' not found", repositoryName),
384-
fmt.Sprintf("The %s %s repository '%s' does not exist or you do not have permission to access it.",
384+
fmt.Sprintf("The %s %s repository '%s' does not exist or you do not have permission to access it.",
385385
r.RepositoryFormat.GetKey(), r.RepositoryType.String(), repositoryName),
386386
)
387387
} else {
@@ -408,7 +408,7 @@ func (r *repositoryResource) ImportState(ctx context.Context, req resource.Impor
408408
// UpdateStateFromApi expects an empty instance of the proper model type and returns a populated one
409409
// Pass nil as the first parameter - UpdateStateFromApi will create the proper model type
410410
stateModel := r.RepositoryFormat.UpdateStateFromApi(nil, apiResponse)
411-
411+
412412
// Update plan for state (sets last_updated timestamp)
413413
stateModel = r.RepositoryFormat.UpdatePlanForState(stateModel)
414414

@@ -504,4 +504,4 @@ func getHostedStandardSchema(repoFormat string, repoType format.RepositoryType)
504504
},
505505
},
506506
}
507-
}
507+
}

internal/provider/repository/repository_p2_x_resources_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,55 @@ resource "%s" "repo" {
106106
},
107107
})
108108
}
109+
110+
func TestAccRepositoryP2ProxyImport(t *testing.T) {
111+
randomString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
112+
resourceType := "sonatyperepo_repository_p2_proxy"
113+
resourceName := fmt.Sprintf("%s.repo", resourceType)
114+
repoName := fmt.Sprintf("p2-proxy-import-%s", randomString)
115+
116+
resource.Test(t, resource.TestCase{
117+
ProtoV6ProviderFactories: utils_test.TestAccProtoV6ProviderFactories,
118+
Steps: []resource.TestStep{
119+
// Create with minimal configuration
120+
{
121+
Config: fmt.Sprintf(utils_test.ProviderConfig+`
122+
resource "%s" "repo" {
123+
name = "%s"
124+
online = true
125+
storage = {
126+
blob_store_name = "default"
127+
strict_content_type_validation = true
128+
}
129+
proxy = {
130+
remote_url = "https://download.eclipse.org/releases/2025-06"
131+
content_max_age = 1440
132+
metadata_max_age = 1440
133+
}
134+
negative_cache = {
135+
enabled = true
136+
time_to_live = 1440
137+
}
138+
http_client = {
139+
blocked = false
140+
auto_block = true
141+
}
142+
}
143+
`, resourceType, repoName),
144+
Check: resource.ComposeAggregateTestCheckFunc(
145+
resource.TestCheckResourceAttr(resourceName, "name", repoName),
146+
resource.TestCheckResourceAttr(resourceName, "online", "true"),
147+
),
148+
},
149+
// Import and verify no changes
150+
{
151+
ResourceName: resourceName,
152+
ImportState: true,
153+
ImportStateVerify: true,
154+
ImportStateId: repoName,
155+
ImportStateVerifyIdentifierAttribute: "name",
156+
ImportStateVerifyIgnore: []string{"last_updated"},
157+
},
158+
},
159+
})
160+
}

0 commit comments

Comments
 (0)