Skip to content

Commit

Permalink
added private repositories argocd_repository acceptance tests, fixed …
Browse files Browse the repository at this point in the history
…sensitive repository data permadiffs, removed 1.4.x support (#24)

* added private repositories acceptance tests
* repository: add ForceNew flag to repo attribute
* fix sensitive data (passwords, keys) not being returned by ArgoCD API
* removed 1.4.x support
  • Loading branch information
oboukili authored Aug 5, 2020
1 parent b25af60 commit 804fb69
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
argocd_version: ["v1.6.1", "v1.5.8", "v1.4.3"]
argocd_version: ["v1.6.2", "v1.5.8"]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v1
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

---

## Compatibility promise

This provider is compatible with _at least_ the last 2 major releases of ArgoCD (e.g, ranging from 1.(n).m, to 1.(n-1).0, where `n` is the latest available major version).

Older releases are not supported and some resources may not work as expected.

---

## Requirements

- [Terraform](https://www.terraform.io/downloads.html) 0.12.24+
Expand Down
32 changes: 14 additions & 18 deletions argocd/features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/Masterminds/semver"
"github.com/argoproj/argo-cd/pkg/apiclient/version"
"github.com/stretchr/testify/assert"
"math/rand"
"testing"
)
Expand All @@ -14,39 +15,34 @@ const (
semverLess
)

func serverInterfaceTestData(argocdVersion string, semverOperator int) ServerInterface {

func serverInterfaceTestData(t *testing.T, argocdVersion string, semverOperator int) ServerInterface {
v, err := semver.NewVersion(argocdVersion)
if err != nil {
panic(err)
}
assert.NoError(t, err)

incPatch := rand.Int63n(100)
incMinor := rand.Int63n(100)
incMajor := rand.Int63n(100)

switch semverOperator {
case semverEquals:
case semverGreater:
if v, err = semver.NewVersion(
v, err = semver.NewVersion(
fmt.Sprintf("%d.%d.%d",
v.Major()+incMajor,
v.Minor()+incMinor,
v.Patch()+incPatch,
)); err != nil {
panic(err)
}

))
assert.NoError(t, err)
case semverLess:
if v, err = semver.NewVersion(
v, err = semver.NewVersion(
fmt.Sprintf("%d.%d.%d",
v.Major()-incMajor%v.Major(),
v.Minor()-incMinor%v.Minor(),
v.Patch()-incPatch%v.Patch(),
)); err != nil {
panic(err)
}
))
assert.NoError(t, err)
default:
panic("unsupported semver test semverOperator")
t.Error("unsupported semver test semverOperator")
}

vm := &version.VersionMessage{
Expand All @@ -72,21 +68,21 @@ func TestServerInterface_isFeatureSupported(t *testing.T) {
}{
{
name: "featureTokenID-1.5.3",
fields: serverInterfaceTestData("1.5.3", semverEquals),
fields: serverInterfaceTestData(t, "1.5.3", semverEquals),
args: args{feature: featureTokenIDs},
want: true,
wantErr: false,
},
{
name: "featureTokenID-1.5.3+",
fields: serverInterfaceTestData("1.5.3", semverGreater),
fields: serverInterfaceTestData(t, "1.5.3", semverGreater),
args: args{feature: featureTokenIDs},
want: true,
wantErr: false,
},
{
name: "featureTokenID-1.5.3-",
fields: serverInterfaceTestData("1.5.3", semverLess),
fields: serverInterfaceTestData(t, "1.5.3", semverLess),
args: args{feature: featureTokenIDs},
want: false,
wantErr: false,
Expand Down
5 changes: 2 additions & 3 deletions argocd/resource_argocd_project_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/stretchr/testify/assert"
"math"
"math/rand"
"regexp"
Expand All @@ -14,9 +15,7 @@ import (
func TestAccArgoCDProjectToken(t *testing.T) {
expiresInDurationFunc := func(i int) time.Duration {
d, err := time.ParseDuration(fmt.Sprintf("%ds", i))
if err != nil {
panic(err)
}
assert.NoError(t, err)
return d
}
count := 3 + rand.Intn(7)
Expand Down
9 changes: 7 additions & 2 deletions argocd/resource_argocd_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ func resourceArgoCDRepositoryCreate(d *schema.ResourceData, meta interface{}) er
if err != nil {
return err
}
if r == nil {
return fmt.Errorf("ArgoCD did not return an error or a repository result")
}
if r.ConnectionState.Status == application.ConnectionStatusFailed {
return fmt.Errorf(
"could not connect to repository %s: %s",
Expand All @@ -56,7 +59,7 @@ func resourceArgoCDRepositoryRead(d *schema.ResourceData, meta interface{}) erro

featureRepositoryGetSupported, err := server.isFeatureSupported(featureRepositoryGet)
if err != nil {
panic(err)
return err
}

switch featureRepositoryGetSupported {
Expand Down Expand Up @@ -100,7 +103,6 @@ func resourceArgoCDRepositoryRead(d *schema.ResourceData, meta interface{}) erro
return nil
}
}

}
return flattenRepository(r, d)
}
Expand All @@ -123,6 +125,9 @@ func resourceArgoCDRepositoryUpdate(d *schema.ResourceData, meta interface{}) er
return err
}
}
if r == nil {
return fmt.Errorf("ArgoCD did not return an error or a repository result")
}
if r.ConnectionState.Status == application.ConnectionStatusFailed {
return fmt.Errorf(
"could not connect to repository %s: %s",
Expand Down
19 changes: 11 additions & 8 deletions argocd/resource_argocd_repository_credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/stretchr/testify/assert"
"testing"
)

func TestAccArgoCDRepositoryCredentials(t *testing.T) {
repoUrl := fmt.Sprintf("https://git.local/%s/%s",
acctest.RandString(10),
acctest.RandString(10))
username := fmt.Sprintf(acctest.RandString(10))
repoUrl := "https://private-git-repository.argocd.svc.clusterlocal/project.git"
username := "git"
sshPrivateKey, err := generateSSHPrivateKey()
if err != nil {
panic(err)
}
assert.NoError(t, err)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Expand Down Expand Up @@ -65,3 +62,9 @@ func generateSSHPrivateKey() (privateKey string, err error) {
}
return string(pem.EncodeToMemory(&privBlock)), nil
}

func mustGenerateSSHPrivateKey(t *testing.T) string {
pk, err := generateSSHPrivateKey()
assert.NoError(t, err)
return pk
}
79 changes: 69 additions & 10 deletions argocd/resource_argocd_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,54 @@ import (
)

func TestAccArgoCDRepository(t *testing.T) {
repoUrl := "[email protected]:project.git"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
//{
// Config: testAccArgoCDRepositorySimple(),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttr(
// "argocd_repository.simple",
// "connection_state_status",
// "Successful",
// ),
// ),
//},
//{
// Config: testAccArgoCDRepositoryHelm(),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttr(
// "argocd_repository.helm",
// "connection_state_status",
// "Successful",
// ),
// ),
//},
//{
// Config: testAccArgoCDRepositoryPublicUsageInApplication(acctest.RandString(10)),
// Check: resource.ComposeTestCheckFunc(
// resource.TestCheckResourceAttrSet(
// "argocd_application.public",
// "metadata.0.uid",
// ),
// ),
//},
{
Config: testAccArgoCDRepositorySimple(),
Config: testAccArgoCDRepositoryPrivateGitSSH(repoUrl),
//ExpectNonEmptyPlan: true,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"argocd_repository.simple",
"argocd_repository.private",
"connection_state_status",
"Successful",
),
),
},
{
Config: testAccArgoCDRepositoryHelm(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"argocd_repository.helm",
"connection_state_status",
"Successful",
"argocd_repository.private",
"inherited_creds",
"false",
),
),
},
Expand All @@ -52,3 +79,35 @@ resource "argocd_repository" "helm" {
}
`)
}

func testAccArgoCDRepositoryPublicUsageInApplication(name string) string {
return testAccArgoCDRepositorySimple() + fmt.Sprintf(`
resource "argocd_application" "public" {
metadata {
name = "%s"
namespace = "argocd"
}
spec {
source {
repo_url = argocd_repository.simple.repo
path = "examples/helloWorld"
}
destination {
server = "https://kubernetes.default.svc"
namespace = "default"
}
}
}
`, name)
}

func testAccArgoCDRepositoryPrivateGitSSH(repoUrl string) string {
return fmt.Sprintf(`
resource "argocd_repository" "private" {
repo = "%s"
type = "git"
insecure = true
ssh_private_key = "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\nQyNTUxOQAAACCGe6Vx0gbKqKCI0wIplfgK5JBjCDO3bhtU3sZfLoeUZgAAAJB9cNEifXDR\nIgAAAAtzc2gtZWQyNTUxOQAAACCGe6Vx0gbKqKCI0wIplfgK5JBjCDO3bhtU3sZfLoeUZg\nAAAEAJeUrObjoTbGO1Sq4TXHl/j4RJ5aKMC1OemWuHmLK7XYZ7pXHSBsqooIjTAimV+Ark\nkGMIM7duG1Texl8uh5RmAAAAC3Rlc3RAYXJnb2NkAQI=\n-----END OPENSSH PRIVATE KEY-----"
}
`, repoUrl)
}
13 changes: 7 additions & 6 deletions argocd/schema_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ func repositorySchema() map[string]*schema.Schema {
"repo": {
Type: schema.TypeString,
Description: "URL of the repo",
ForceNew: true,
Required: true,
},
"enable_lfs": {
Expand All @@ -20,7 +21,7 @@ func repositorySchema() map[string]*schema.Schema {
"inherited_creds": {
Type: schema.TypeBool,
Description: "Whether credentials were inherited from a credential set",
Optional: true,
Computed: true,
},
"insecure": {
Type: schema.TypeBool,
Expand All @@ -44,11 +45,11 @@ func repositorySchema() map[string]*schema.Schema {
Optional: true,
},
"ssh_private_key": {
Type: schema.TypeString,
Sensitive: true,
Description: "SSH private key data for authenticating at the repo server only for Git repos",
// TODO: add a validator
Optional: true,
Type: schema.TypeString,
Sensitive: false,
Description: "SSH private key data for authenticating at the repo server only for Git repos",
ValidateFunc: validateSSHPrivateKey,
Optional: true,
},
"tls_client_cert_data": {
Type: schema.TypeString,
Expand Down
18 changes: 6 additions & 12 deletions argocd/schema_repository_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,15 @@ func repositoryCredentialsSchema() map[string]*schema.Schema {
"password": {
Type: schema.TypeString,
Sensitive: true,
Description: "Password for authenticating at the repo server, cannot be managed once created!",
Description: "Password for authenticating at the repo server",
Optional: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return true
},
},
"ssh_private_key": {
Type: schema.TypeString,
Sensitive: true,
Description: "SSH private key data for authenticating at the repo server only for Git repos, cannot be managed once created!",
// TODO: add a validator
Optional: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return true
},
Type: schema.TypeString,
Sensitive: true,
Description: "SSH private key data for authenticating at the repo server only for Git repos",
ValidateFunc: validateSSHPrivateKey,
Optional: true,
},
"tls_client_cert_data": {
Type: schema.TypeString,
Expand Down
15 changes: 7 additions & 8 deletions argocd/structure_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ func expandRepository(d *schema.ResourceData) *application.Repository {
if v, ok := d.GetOk("password"); ok {
repository.Password = v.(string)
}
if v, ok := d.GetOk("ssh_private_key"); ok {
repository.SSHPrivateKey = v.(string)
}
repository.SSHPrivateKey = d.Get("ssh_private_key").(string)
if v, ok := d.GetOk("tls_client_cert_data"); ok {
repository.TLSClientCertData = v.(string)
}
Expand All @@ -57,11 +55,12 @@ func flattenRepository(repository *application.Repository, d *schema.ResourceDat
"insecure": repository.Insecure,
"name": repository.Name,
"username": repository.Username,
"password": repository.Password,
"ssh_private_key": repository.SSHPrivateKey,
"tls_client_cert_data": repository.TLSClientCertData,
"tls_client_cert_key": repository.TLSClientCertKey,
"type": repository.Type,
// TODO: ArgoCD API does not return sensitive data!
//"password": repository.Password,
//"ssh_private_key": repository.SSHPrivateKey,
//"tls_client_cert_key": repository.TLSClientCertKey,
"tls_client_cert_data": repository.TLSClientCertData,
"type": repository.Type,
}
for k, v := range r {
if err := persistToState(k, v, d); err != nil {
Expand Down
Loading

0 comments on commit 804fb69

Please sign in to comment.