Skip to content

Commit

Permalink
feat: new resource spacelift_gitlab_integration (#557)
Browse files Browse the repository at this point in the history
* refactor: moved CustomVCSInput and CustomVCSUpdateInput to separate package vcs
* refactor: moved GitLab schema field name constants to gitlab_integration.go
* feat: implemented spacelift_gitlab_integration resource
* test: added tests for spacelift_gitlab_integration resource
* docs: added examples and docs for spacelift_gitlab_integration resource
* chore: added .envrc for easier setup of environment variables from .env file
* cicd: added SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_TOKEN and SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_TOKEN to GitHub test workflows
* fix: fix typo in GraphQL query for GitLabIntegration and add ForceNew flag to isDefault field in schema in spacelift/resource_gitlab_integration.go
* refactor: rename "webhookURL" field to "webhookUrl" in GitLabIntegration struct and remove "Token" field
* refactor: changes to spacelift/resource_gitlab_integration.go
* add CustomizeDiff function ensure space is set to root if the integration should be the default
* make gitLabUserFacingHost required and removed code to derive it from gitLabAPIHost if not set
* set default value for gitLabSpaceID to "root"
* docs: updated docs for spacelift_gitlab_integration
* tests: updated tests for spacelift_gitlab_integration
* added .envrc into .gitignore
* minor fixes: naming, messaging, verifying

---------

Co-authored-by: Thomas Meckel <[email protected]>
  • Loading branch information
truszkowski and tmeckel authored May 28, 2024
1 parent c8054ad commit 1cfb831
Show file tree
Hide file tree
Showing 17 changed files with 589 additions and 59 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/test-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v5
with: { go-version-file: go.mod }
Expand Down Expand Up @@ -83,12 +83,14 @@ jobs:
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_NAME: "GitLab Default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_ID: "gitlab-default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_APIHOST: "https://gitlab.com"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_TOKEN: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_TOKEN }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKSECRET: ${{ secrets.PROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKSECRET }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKURL: ${{ secrets.PROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKURL }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_NAME: "GitLab Space Level"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_ID: "gitlab-space-level"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_SPACE: "tests-01HPE6H08F8HR8PJR78DPYR3TC"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_APIHOST: "https://gitlab.com"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_TOKEN: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_TOKEN }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKSECRET: ${{ secrets.PROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKSECRET }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKURL: ${{ secrets.PROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKURL }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_AZUREDEVOPS_REPOSITORY_NAME: "spacelift-ci"
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v5
with: { go-version-file: go.mod }
Expand Down Expand Up @@ -85,12 +85,14 @@ jobs:
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_NAME: "GitLab Default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_ID: "gitlab-default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_APIHOST: "https://gitlab.com"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_TOKEN: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_TOKEN }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKSECRET: ${{ secrets.PREPROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKSECRET }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKURL: ${{ secrets.PREPROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_DEFAULT_WEBHOOKURL }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_NAME: "GitLab Space Level"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_ID: "gitlab-space-level"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_SPACE: "tests-01HPE6ENR1AZZ638QSRQRVW4DH"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_APIHOST: "https://gitlab.com"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_TOKEN: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_TOKEN }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKSECRET: ${{ secrets.PREPROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKSECRET }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKURL: ${{ secrets.PREPROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITLAB_SPACELEVEL_WEBHOOKURL }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_AZUREDEVOPS_REPOSITORY_NAME: "spacelift-ci"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ key.*
dist/

test.env
.envrc
62 changes: 62 additions & 0 deletions docs/resources/gitlab_integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "spacelift_gitlab_integration Resource - terraform-provider-spacelift"
subcategory: ""
description: |-
spacelift_gitlab_integration represents an integration with a GitLab instance
---

# spacelift_gitlab_integration (Resource)

`spacelift_gitlab_integration` represents an integration with a GitLab instance

## Example Usage

```terraform
resource "spacelift_gitlab_integration" "example" {
name = "GitLab integration (public)"
space_id = "root"
api_host = "https://mygitlab.myorg.com"
user_facing_host = "https://mygitlab.myorg.com"
private_token = "gitlab-token"
}
resource "spacelift_gitlab_integration" "private-example" {
name = "GitLab integration (private)"
is_default = true
api_host = "private://mygitlab"
user_facing_host = "https://mygitlab.myorg.com"
private_token = "gitlab-token"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `api_host` (String) API host URL
- `name` (String) The friendly name of the integration
- `private_token` (String, Sensitive) The GitLab API Token
- `user_facing_host` (String) User facing host URL.

### Optional

- `description` (String) Description of the integration
- `is_default` (Boolean) Is the GitLab integration the default for all spaces? If set to `true` the space must be set to `root` in `space_id` or left empty which uses the default
- `labels` (Set of String) Labels to set on the integration
- `space_id` (String) ID (slug) of the space the integration is in; Default: `root`

### Read-Only

- `id` (String) GitLab integration id.
- `webhook_secret` (String, Sensitive) Secret for webhooks originating from GitLab repositories
- `webhook_url` (String) URL for webhooks originating from GitLab repositories

## Import

Import is supported using the following syntax:

```shell
terraform import spacelift_gitlab_integration.example spacelift_gitlab_integration_id
```
1 change: 1 addition & 0 deletions examples/resources/spacelift_gitlab_integration/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import spacelift_gitlab_integration.example spacelift_gitlab_integration_id
15 changes: 15 additions & 0 deletions examples/resources/spacelift_gitlab_integration/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "spacelift_gitlab_integration" "example" {
name = "GitLab integration (public)"
space_id = "root"
api_host = "https://mygitlab.myorg.com"
user_facing_host = "https://mygitlab.myorg.com"
private_token = "gitlab-token"
}

resource "spacelift_gitlab_integration" "private-example" {
name = "GitLab integration (private)"
is_default = true
api_host = "private://mygitlab"
user_facing_host = "https://mygitlab.myorg.com"
private_token = "gitlab-token"
}
2 changes: 2 additions & 0 deletions spacelift/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ var testConfig struct {
Default struct {
Name string
ID string
Token string
APIHost string
WebhookSecret string
WebhookURL string
Expand All @@ -117,6 +118,7 @@ var testConfig struct {
ID string
Space string
APIHost string
Token string
WebhookSecret string
WebhookURL string
}
Expand Down
59 changes: 23 additions & 36 deletions spacelift/data_gitlab_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,70 +9,57 @@ import (
"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal"
)

const (
gitlabId = "id"
gitlabName = "name"
gitlabDescription = "description"
gitlabIsDefault = "is_default"
gitlabLabels = "labels"
gitlabSpaceID = "space_id"
gitlabAppID = "app_id"
gitlabAPIHost = "api_host"
gitlabWebhookSecret = "webhook_secret"
gitlabWebhookURL = "webhook_url"
)

func dataGitlabIntegration() *schema.Resource {
return &schema.Resource{
Description: "`spacelift_gitlab_integration` returns details about Gitlab integration",

ReadContext: dataGitlabIntegrationRead,

Schema: map[string]*schema.Schema{
gitlabId: {
gitLabID: {
Type: schema.TypeString,
Description: "Gitlab integration id. If not provided, the default integration will be returned",
Optional: true,
},
gitlabName: {
gitLabName: {
Type: schema.TypeString,
Description: "Gitlab integration name",
Computed: true,
},
gitlabDescription: {
gitLabDescription: {
Type: schema.TypeString,
Description: "Gitlab integration description",
Computed: true,
},
gitlabIsDefault: {
gitLabIsDefault: {
Type: schema.TypeBool,
Description: "Gitlab integration is default",
Computed: true,
},
gitlabLabels: {
gitLabLabels: {
Type: schema.TypeList,
Description: "Gitlab integration labels",
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
gitlabSpaceID: {
gitLabSpaceID: {
Type: schema.TypeString,
Description: "Gitlab integration space id",
Computed: true,
},
gitlabAPIHost: {
gitLabAPIHost: {
Type: schema.TypeString,
Description: "Gitlab integration api host",
Computed: true,
},
gitlabWebhookSecret: {
gitLabWebhookSecret: {
Type: schema.TypeString,
Description: "Gitlab integration webhook secret",
Computed: true,
},
gitlabWebhookURL: {
gitLabWebhookURL: {
Type: schema.TypeString,
Description: "Gitlab integration webhook url",
Computed: true,
Expand Down Expand Up @@ -101,35 +88,35 @@ func dataGitlabIntegrationRead(ctx context.Context, d *schema.ResourceData, meta

variables := map[string]interface{}{"id": ""}

if id, ok := d.GetOk(gitlabId); ok && id != "" {
if id, ok := d.GetOk(gitLabID); ok && id != "" {
variables["id"] = toID(id)
}

if err := meta.(*internal.Client).Query(ctx, "GitlabIntegrationRead", &query, variables); err != nil {
return diag.Errorf("could not query for gitlab integration: %v", err)
}

gitlabIntegration := query.GitlabIntegration
if gitlabIntegration == nil {
gitLabIntegration := query.GitlabIntegration
if gitLabIntegration == nil {
return diag.Errorf("gitlab integration not found")
}

d.SetId(gitlabIntegration.ID)
d.Set(gitlabAPIHost, gitlabIntegration.APIHost)
d.Set(gitlabWebhookSecret, gitlabIntegration.WebhookSecret)
d.Set(gitlabWebhookURL, gitlabIntegration.WebhookURL)
d.Set(gitlabId, gitlabIntegration.ID)
d.Set(gitlabName, gitlabIntegration.Name)
d.Set(gitlabDescription, gitlabIntegration.Description)
d.Set(gitlabIsDefault, gitlabIntegration.IsDefault)
d.Set(gitlabSpaceID, gitlabIntegration.Space.ID)
d.SetId(gitLabIntegration.ID)
d.Set(gitLabAPIHost, gitLabIntegration.APIHost)
d.Set(gitLabWebhookSecret, gitLabIntegration.WebhookSecret)
d.Set(gitLabWebhookURL, gitLabIntegration.WebhookURL)
d.Set(gitLabID, gitLabIntegration.ID)
d.Set(gitLabName, gitLabIntegration.Name)
d.Set(gitLabDescription, gitLabIntegration.Description)
d.Set(gitLabIsDefault, gitLabIntegration.IsDefault)
d.Set(gitLabSpaceID, gitLabIntegration.Space.ID)

labels := schema.NewSet(schema.HashString, []interface{}{})
for _, label := range gitlabIntegration.Labels {
for _, label := range gitLabIntegration.Labels {
labels.Add(label)
}

d.Set(gitlabLabels, labels)
d.Set(gitLabLabels, labels)

return nil
}
16 changes: 16 additions & 0 deletions spacelift/gitlab_integration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package spacelift

const (
gitLabID = "id"
gitLabName = "name"
gitLabDescription = "description"
gitLabIsDefault = "is_default"
gitLabLabels = "labels"
gitLabSpaceID = "space_id"
gitLabUserFacingHost = "user_facing_host"
gitLabAppID = "app_id"
gitLabAPIHost = "api_host"
gitLabToken = "private_token"
gitLabWebhookURL = "webhook_url"
gitLabWebhookSecret = "webhook_secret"
)
19 changes: 0 additions & 19 deletions spacelift/internal/structs/bitbucket_datacenter_integration.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package structs

import "github.com/shurcooL/graphql"

// BitbucketDatacenterIntegration represents the bitbucket datacenter integration data relevant to the provider.
type BitbucketDatacenterIntegration struct {
ID string `graphql:"id"`
Expand All @@ -18,20 +16,3 @@ type BitbucketDatacenterIntegration struct {
WebhookSecret string `graphql:"webhookSecret"`
WebhookURL string `graphql:"webhookURL"`
}

// CustomVCSInput represents the custom VCS input data.
type CustomVCSInput struct {
Name graphql.String `json:"name"`
SpaceID graphql.ID `json:"spaceID"`
Labels *[]graphql.String `json:"labels"`
Description *graphql.String `json:"description"`
IsDefault *graphql.Boolean `json:"isDefault"`
}

// CustomVCSUpdateInput represents the custom VCS update input data.
type CustomVCSUpdateInput struct {
ID graphql.ID `json:"id"`
SpaceID graphql.ID `json:"space"`
Labels *[]graphql.String `json:"labels"`
Description *graphql.String `json:"description"`
}
18 changes: 18 additions & 0 deletions spacelift/internal/structs/gitlab_integration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package structs

// GitLabIntegration represents an GitLab identity provided by the Spacelift
// integration.
type GitLabIntegration struct {
ID string `graphql:"id"`
Name string `graphql:"name"`
Space struct {
ID string `graphql:"id"`
} `graphql:"space"`
IsDefault bool `graphql:"isDefault"`
Labels []string `graphql:"labels"`
Description *string `graphql:"description"`
APIHost string `graphql:"apiHost"`
UserFacingHost string `graphql:"userFacingHost"`
WebhookSecret string `graphql:"webhookSecret"`
WebhookURL string `graphql:"webhookUrl"`
}
12 changes: 12 additions & 0 deletions spacelift/internal/structs/vcs/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package vcs

import "github.com/shurcooL/graphql"

// CustomVCSInput represents the custom VCS input data.
type CustomVCSInput struct {
Name graphql.String `json:"name"`
SpaceID graphql.ID `json:"spaceID"`
Labels *[]graphql.String `json:"labels"`
Description *graphql.String `json:"description"`
IsDefault *graphql.Boolean `json:"isDefault"`
}
11 changes: 11 additions & 0 deletions spacelift/internal/structs/vcs/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package vcs

import "github.com/shurcooL/graphql"

// CustomVCSUpdateInput represents the custom VCS update input data.
type CustomVCSUpdateInput struct {
ID graphql.ID `json:"id"`
SpaceID graphql.ID `json:"space"`
Labels *[]graphql.String `json:"labels"`
Description *graphql.String `json:"description"`
}
1 change: 1 addition & 0 deletions spacelift/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func Provider(commit, version string) plugin.ProviderFunc {
"spacelift_drift_detection": resourceDriftDetection(),
"spacelift_environment_variable": resourceEnvironmentVariable(),
"spacelift_gcp_service_account": resourceGCPServiceAccount(),
"spacelift_gitlab_integration": resourceGitLabIntegration(),
"spacelift_idp_group_mapping": resourceIdpGroupMapping(),
"spacelift_module": resourceModule(),
"spacelift_mounted_file": resourceMountedFile(),
Expand Down
Loading

0 comments on commit 1cfb831

Please sign in to comment.