Skip to content

Commit

Permalink
Add support for GitHub app credentials (#235)
Browse files Browse the repository at this point in the history
Co-authored-by: OneMatchFox <[email protected]>
  • Loading branch information
philamente and onematchfox authored Mar 14, 2023
1 parent 124d87b commit cb9f554
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 24 deletions.
22 changes: 20 additions & 2 deletions argocd/resource_argocd_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ func resourceArgoCDRepositoryCreate(ctx context.Context, d *schema.ResourceData,
}

c := *server.RepositoryClient
repo := expandRepository(d)
repo, err := expandRepository(d)
if err != nil {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: fmt.Sprintf("could not expand repository attributes: %s", err),
Detail: err.Error(),
},
}
}

featureProjectScopedRepositoriesSupported, err := server.isFeatureSupported(featureProjectScopedRepositories)
if err != nil {
Expand Down Expand Up @@ -211,7 +220,16 @@ func resourceArgoCDRepositoryUpdate(ctx context.Context, d *schema.ResourceData,
}
}
c := *server.RepositoryClient
repo := expandRepository(d)
repo, err := expandRepository(d)
if err != nil {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: fmt.Sprintf("could not expand repository attributes: %s", err),
Detail: err.Error(),
},
}
}

featureProjectScopedRepositoriesSupported, err := server.isFeatureSupported(featureProjectScopedRepositories)
if err != nil {
Expand Down
22 changes: 20 additions & 2 deletions argocd/resource_argocd_repository_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,16 @@ func resourceArgoCDRepositoryCredentialsCreate(ctx context.Context, d *schema.Re
}
}
c := *server.RepoCredsClient
repoCreds := expandRepositoryCredentials(d)
repoCreds, err := expandRepositoryCredentials(d)
if err != nil {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: fmt.Sprintf("could not expand repository credential attributes: %s", err),
Detail: err.Error(),
},
}
}

tokenMutexConfiguration.Lock()
rc, err := c.CreateRepositoryCredentials(
Expand Down Expand Up @@ -122,7 +131,16 @@ func resourceArgoCDRepositoryCredentialsUpdate(ctx context.Context, d *schema.Re
}
}
c := *server.RepoCredsClient
repoCreds := expandRepositoryCredentials(d)
repoCreds, err := expandRepositoryCredentials(d)
if err != nil {
return []diag.Diagnostic{
{
Severity: diag.Error,
Summary: fmt.Sprintf("could not expand repository credential attributes: %s", err),
Detail: err.Error(),
},
}
}

tokenMutexConfiguration.Lock()
r, err := c.UpdateRepositoryCredentials(
Expand Down
52 changes: 52 additions & 0 deletions argocd/resource_argocd_repository_credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,44 @@ func TestAccArgoCDRepositoryCredentials(t *testing.T) {
})
}

func TestAccArgoCDRepositoryCredentials_GitHubApp(t *testing.T) {
sshPrivateKey, err := generateSSHPrivateKey()
assert.NoError(t, err)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccArgoCDRepositoryCredentialsGitHubApp(
"https://private-git-repository.argocd.svc.cluster.local/project-1.git",
"123456",
"987654321",
"https://ghe.example.com/api/v3",
sshPrivateKey,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
"argocd_repository_credentials.githubapp",
"githubapp_id",
"123456",
),
resource.TestCheckResourceAttr(
"argocd_repository_credentials.githubapp",
"githubapp_installation_id",
"987654321",
),
resource.TestCheckResourceAttr(
"argocd_repository_credentials.githubapp",
"githubapp_enterprise_base_url",
"https://ghe.example.com/api/v3",
),
),
},
},
})
}

func testAccArgoCDRepositoryCredentialsSimple(repoUrl, username, sshPrivateKey string) string {
return fmt.Sprintf(`
resource "argocd_repository_credentials" "simple" {
Expand Down Expand Up @@ -80,6 +118,20 @@ resource "argocd_repository_credentials" "private" {
`)
}

func testAccArgoCDRepositoryCredentialsGitHubApp(repoUrl, id, installID, enterpriseBaseURL, appKey string) string {
return fmt.Sprintf(`
resource "argocd_repository_credentials" "githubapp" {
url = "%s"
githubapp_id = "%s"
githubapp_installation_id = "%s"
githubapp_enterprise_base_url = "%s"
githubapp_private_key = <<EOT
%s
EOT
}
`, repoUrl, id, installID, enterpriseBaseURL, appKey)
}

func generateSSHPrivateKey() (privateKey string, err error) {
pk, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
Expand Down
54 changes: 54 additions & 0 deletions argocd/resource_argocd_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/stretchr/testify/assert"
)

func TestAccArgoCDRepository(t *testing.T) {
Expand Down Expand Up @@ -136,6 +137,44 @@ func TestAccArgoCDRepositoryScoped_NotSupported_On_OlderVersions(t *testing.T) {
})
}

func TestAccArgoCDRepository_GitHubApp(t *testing.T) {
sshPrivateKey, err := generateSSHPrivateKey()
assert.NoError(t, err)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccArgoCDRepositoryGitHubApp(
"https://private-git-repository.argocd.svc.cluster.local/project-1.git",
"123456",
"987654321",
"https://ghe.example.com/api/v3",
sshPrivateKey,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
"argocd_repository.githubapp",
"githubapp_id",
"123456",
),
resource.TestCheckResourceAttr(
"argocd_repository.githubapp",
"githubapp_installation_id",
"987654321",
),
resource.TestCheckResourceAttr(
"argocd_repository.githubapp",
"githubapp_enterprise_base_url",
"https://ghe.example.com/api/v3",
),
),
},
},
})
}

func testAccArgoCDRepositorySimple() string {
return fmt.Sprintf(`
resource "argocd_repository" "simple" {
Expand Down Expand Up @@ -227,6 +266,21 @@ resource "argocd_repository" "private" {
`, repoCount)
}

func testAccArgoCDRepositoryGitHubApp(repoUrl, id, installID, baseURL, appKey string) string {
return fmt.Sprintf(`
resource "argocd_repository" "githubapp" {
project = "default"
repo = "%s"
githubapp_id = "%s"
githubapp_installation_id = "%s"
githubapp_enterprise_base_url = "%s"
githubapp_private_key = <<EOT
%s
EOT
}
`, repoUrl, id, installID, baseURL, appKey)
}

func testCheckMultipleResourceAttr(name, key, value string, count int) resource.TestCheckFunc {
return func(s *terraform.State) error {
for i := 0; i < count; i++ {
Expand Down
24 changes: 24 additions & 0 deletions argocd/schema_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,29 @@ func repositorySchema() map[string]*schema.Schema {
Type: schema.TypeString,
Computed: true,
},
"githubapp_id": {
Type: schema.TypeString,
Description: "GitHub App id for authenticating at the repo server only for GitHub repos",
ValidateFunc: validatePositiveInteger,
Optional: true,
},
"githubapp_installation_id": {
Type: schema.TypeString,
Description: "GitHub App installation id for authenticating at the repo server only for GitHub repos",
ValidateFunc: validatePositiveInteger,
Optional: true,
},
"githubapp_enterprise_base_url": {
Type: schema.TypeString,
Description: "If using GitHub App for a GitHub Enterprise repository the host url is required",
Optional: true,
},
"githubapp_private_key": {
Type: schema.TypeString,
Sensitive: true,
Description: "Private key data (pem) of GitHub App for authenticating at the repo server only for GitHub repos",
ValidateFunc: validateSSHPrivateKey,
Optional: true,
},
}
}
24 changes: 24 additions & 0 deletions argocd/schema_repository_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,29 @@ func repositoryCredentialsSchema() map[string]*schema.Schema {
Description: "Specify whether the repo server should be viewed as OCI compliant",
Optional: true,
},
"githubapp_id": {
Type: schema.TypeString,
Description: "GitHub App id for authenticating at the repo server only for GitHub repos",
ValidateFunc: validatePositiveInteger,
Optional: true,
},
"githubapp_installation_id": {
Type: schema.TypeString,
Description: "GitHub App installation id for authenticating at the repo server only for GitHub repos",
ValidateFunc: validatePositiveInteger,
Optional: true,
},
"githubapp_enterprise_base_url": {
Type: schema.TypeString,
Description: "If using GitHub App for a GitHub Enterprise repository the host url is required",
Optional: true,
},
"githubapp_private_key": {
Type: schema.TypeString,
Sensitive: true,
Description: "Private key data (pem) of GitHub App for authenticating at the repo server only for GitHub repos",
ValidateFunc: validateSSHPrivateKey,
Optional: true,
},
}
}
43 changes: 35 additions & 8 deletions argocd/structure_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (

// Expand

func expandRepository(d *schema.ResourceData) *application.Repository {
func expandRepository(d *schema.ResourceData) (*application.Repository, error) {
var err error

repository := &application.Repository{}
if v, ok := d.GetOk("repo"); ok {
repository.Repo = v.(string)
Expand Down Expand Up @@ -49,7 +51,25 @@ func expandRepository(d *schema.ResourceData) *application.Repository {
if v, ok := d.GetOk("type"); ok {
repository.Type = v.(string)
}
return repository
if v, ok := d.GetOk("githubapp_id"); ok {
repository.GithubAppId, err = convertStringToInt64(v.(string))
if err != nil {
return nil, err
}
}
if v, ok := d.GetOk("githubapp_installation_id"); ok {
repository.GithubAppInstallationId, err = convertStringToInt64(v.(string))
if err != nil {
return nil, err
}
}
if v, ok := d.GetOk("githubapp_enterprise_base_url"); ok {
repository.GitHubAppEnterpriseBaseURL = v.(string)
}
if v, ok := d.GetOk("githubapp_private_key"); ok {
repository.GithubAppPrivateKey = v.(string)
}
return repository, nil
}

// Flatten
Expand All @@ -64,13 +84,20 @@ func flattenRepository(repository *application.Repository, d *schema.ResourceDat
"name": repository.Name,
"project": repository.Project,
// TODO: in case of repositoryCredentials existence, will perma-diff
//"username": repository.Username,
//"username": repository.Username,
// 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,
//"password": repository.Password,
//"ssh_private_key": repository.SSHPrivateKey,
//"tls_client_cert_key": repository.TLSClientCertKey,
"tls_client_cert_data": repository.TLSClientCertData,
"type": repository.Type,
"githubapp_enterprise_base_url": repository.GitHubAppEnterpriseBaseURL,
}
if repository.GithubAppId > 0 {
r["githubapp_id"] = convertInt64ToString(repository.GithubAppId)
}
if repository.GithubAppInstallationId > 0 {
r["githubapp_installation_id"] = convertInt64ToString(repository.GithubAppInstallationId)
}
for k, v := range r {
if err := persistToState(k, v, d); err != nil {
Expand Down
Loading

0 comments on commit cb9f554

Please sign in to comment.