Skip to content

Commit

Permalink
Merge pull request #226 from MrLuje/feat/project-scoped-repository
Browse files Browse the repository at this point in the history
feat: add support for add project scoped repositories
  • Loading branch information
onematchfox authored Jan 9, 2023
2 parents ea23a8a + f9a0c10 commit 94394f5
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 5 deletions.
2 changes: 2 additions & 0 deletions argocd/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
featureRepositoryGet
featureTokenIDs
featureProjectScopedClusters
featureProjectScopedRepositories
featureClusterMetadata
featureRepositoryCertificates
featureApplicationHelmSkipCrds
Expand All @@ -38,6 +39,7 @@ var featureVersionConstraintsMap = map[int]*semver.Version{
featureRepositoryGet: semver.MustParse("1.6.0"),
featureTokenIDs: semver.MustParse("1.5.3"),
featureProjectScopedClusters: semver.MustParse("2.2.0"),
featureProjectScopedRepositories: semver.MustParse("2.2.0"),
featureClusterMetadata: semver.MustParse("2.2.0"),
featureRepositoryCertificates: semver.MustParse("1.2.0"),
featureApplicationHelmSkipCrds: semver.MustParse("2.3.0"),
Expand Down
2 changes: 1 addition & 1 deletion argocd/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,6 @@ func testAccPreCheckFeatureNotSupported(t *testing.T, feature int) {
t.Fatal("feature constraint is not handled by the provider")
}
if i := versionConstraint.Compare(serverVersion); i != 1 {
t.Skipf("version %s does not support feature", v)
t.Skipf("not running test if feature is already supported (v%s)", v)
}
}
46 changes: 45 additions & 1 deletion argocd/resource_argocd_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,29 @@ func resourceArgoCDRepositoryCreate(ctx context.Context, d *schema.ResourceData,
c := *server.RepositoryClient
repo := expandRepository(d)

err := resource.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
featureProjectScopedRepositoriesSupported, err := server.isFeatureSupported(featureProjectScopedRepositories)
if err != nil {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: "feature not supported",
Detail: err.Error(),
},
}
}
if !featureProjectScopedRepositoriesSupported && repo.Project != "" {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: fmt.Sprintf(
"repository project is only supported from ArgoCD %s onwards",
featureVersionConstraintsMap[featureProjectScopedRepositories].String()),
Detail: "See https://argo-cd.readthedocs.io/en/stable/user-guide/projects/#project-scoped-repositories-and-clusters",
},
}
}

err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
tokenMutexConfiguration.Lock()
r, err := c.CreateRepository(
ctx,
Expand Down Expand Up @@ -191,6 +213,28 @@ func resourceArgoCDRepositoryUpdate(ctx context.Context, d *schema.ResourceData,
c := *server.RepositoryClient
repo := expandRepository(d)

featureProjectScopedRepositoriesSupported, err := server.isFeatureSupported(featureProjectScopedRepositories)
if err != nil {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: "feature not supported",
Detail: err.Error(),
},
}
}
if !featureProjectScopedRepositoriesSupported && repo.Project != "" {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: fmt.Sprintf(
"repository project is only supported from ArgoCD %s onwards",
featureVersionConstraintsMap[featureProjectScopedRepositories].String()),
Detail: "See https://argo-cd.readthedocs.io/en/stable/user-guide/projects/#project-scoped-repositories-and-clusters",
},
}
}

tokenMutexConfiguration.Lock()
r, err := c.UpdateRepository(
ctx,
Expand Down
83 changes: 83 additions & 0 deletions argocd/resource_argocd_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package argocd

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
Expand Down Expand Up @@ -81,6 +82,60 @@ func TestAccArgoCDRepository(t *testing.T) {
})
}

func TestAccArgoCDRepositoryScoped(t *testing.T) {
projectName := acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckFeatureSupported(t, featureProjectScopedRepositories) },
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccArgoCDRepositoryHelmProjectScoped(projectName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"argocd_repository.helm",
"connection_state_status",
"Successful",
),
resource.TestCheckResourceAttr(
"argocd_repository.helm",
"project",
projectName,
),
),
},
},
})
}

func TestAccArgoCDRepositoryScoped_NotSupported_On_OlderVersions(t *testing.T) {
name := acctest.RandomWithPrefix("test-acc-scoped-repo")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckFeatureNotSupported(t, featureProjectScopedRepositories) },
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
// Create tests
{
Config: testAccArgoCDRepositoryHelmProjectScoped(name),
ExpectError: regexp.MustCompile("repository project is only supported from ArgoCD"),
},
// Update tests (create repo without project, update it with project)
{
Config: testAccArgoCDRepositoryHelm(),
Check: resource.TestCheckResourceAttr(
"argocd_repository.helm",
"connection_state_status",
"Successful",
),
},
{
Config: testAccArgoCDRepositoryHelmProjectScoped(name),
ExpectError: regexp.MustCompile("repository project is only supported from ArgoCD"),
},
},
})
}

func testAccArgoCDRepositorySimple() string {
return fmt.Sprintf(`
resource "argocd_repository" "simple" {
Expand All @@ -99,6 +154,34 @@ resource "argocd_repository" "helm" {
`)
}

func testAccArgoCDRepositoryHelmProjectScoped(project string) string {
return fmt.Sprintf(`
resource "argocd_project" "simple" {
metadata {
name = "%[1]s"
namespace = "argocd"
}
spec {
description = "simple project"
source_repos = ["*"]
destination {
name = "anothercluster"
namespace = "bar"
}
}
}
resource "argocd_repository" "helm" {
repo = "https://helm.nginx.com/stable"
name = "nginx-stable-scoped"
type = "helm"
project = "%[1]s"
}
`, project)
}

func testAccArgoCDRepositoryPublicUsageInApplication(name string) string {
return testAccArgoCDRepositorySimple() + fmt.Sprintf(`
resource "argocd_application" "public" {
Expand Down
8 changes: 7 additions & 1 deletion argocd/schema_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package argocd

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

Expand Down Expand Up @@ -33,6 +34,11 @@ func repositorySchema() map[string]*schema.Schema {
Description: "only for Helm repos",
Optional: true,
},
"project": {
Type: schema.TypeString,
Description: "The project name, in case the repository is project scoped",
Optional: true,
},
"username": {
Type: schema.TypeString,
Description: "Username for authenticating at the repo server",
Expand Down Expand Up @@ -67,7 +73,7 @@ func repositorySchema() map[string]*schema.Schema {
"enable_oci": {
Type: schema.TypeBool,
Description: "Specify whether the repo server should be viewed as OCI compliant",
Optional: true,
Optional: true,
},
"type": {
Type: schema.TypeString,
Expand Down
2 changes: 1 addition & 1 deletion argocd/schema_repository_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func repositoryCredentialsSchema() map[string]*schema.Schema {
"enable_oci": {
Type: schema.TypeBool,
Description: "Specify whether the repo server should be viewed as OCI compliant",
Optional: true,
Optional: true,
},
}
}
4 changes: 4 additions & 0 deletions argocd/structure_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ func expandRepository(d *schema.ResourceData) *application.Repository {
if v, ok := d.GetOk("name"); ok {
repository.Name = v.(string)
}
if v, ok := d.GetOk("project"); ok {
repository.Project = v.(string)
}
if v, ok := d.GetOk("username"); ok {
repository.Username = v.(string)
}
Expand Down Expand Up @@ -59,6 +62,7 @@ func flattenRepository(repository *application.Repository, d *schema.ResourceDat
"inherited_creds": repository.InheritedCreds,
"insecure": repository.Insecure,
"name": repository.Name,
"project": repository.Project,
// TODO: in case of repositoryCredentials existence, will perma-diff
//"username": repository.Username,
// TODO: ArgoCD API does not return sensitive data!
Expand Down
3 changes: 2 additions & 1 deletion docs/resources/repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ resource "argocd_repository" "private" {
* `enable_lfs` - (Optional), boolean, whether git-lfs support should be enabled for this repository.
* `username` - (Optional), string, username to authenticate against the repository server.
* `password` - (Optional), string, password to authenticate against the repository server.
* `project` - (Optional), string, if the repository will be project-scoped, the name of that project. Refer to this [doc](https://argo-cd.readthedocs.io/en/stable/user-guide/projects/#project-scoped-repositories-and-clusters). Requires ArgoCD 2.2.0 onwards.
* `ssh_private_key` - (Optional), string, SSH private key data to authenticate against the repository server. **Only for Git repositories**.
* `tls_client_cert_data` - (Optional), TLS client cert data to authenticate against the repository server.
* `tls_client_cert_key` - (Optional), TLS client cert key to authenticate against the repository server.
Expand All @@ -52,4 +53,4 @@ ArgoCD repositories can be imported using an id consisting of `{repo}`, e.g.
$ terraform import argocd_repository.myrepo [email protected]:somerepo.git
```

**NOTE**: as ArgoCD API does not return any sensitive information, a subsequent _terraform apply_ should be executed to make the password, ssh_private_key and tls_client_cert_key attributes converge to their expected values defined within the plan.
**NOTE**: as ArgoCD API does not return any sensitive information, a subsequent _terraform apply_ should be executed to make the password, ssh_private_key and tls_client_cert_key attributes converge to their expected values defined within the plan.

0 comments on commit 94394f5

Please sign in to comment.