Skip to content

Commit

Permalink
Add gitlab provider (GoogleCloudPlatform#1006)
Browse files Browse the repository at this point in the history
* Add import gitlab_project

* Heredoc for project variable and ignore `mirror` fields in projects

* Be more specific in the IgnoreKeys

* Disable heredoc

* Add project's BranchProtections TagProtections ProjectMembership

* Add group's GroupVariables GroupMembership

* Add docs

* Update docs

* Remove invalid test

* Fix golangci-lint

* Fix golangci-lint
  • Loading branch information
duyleekun authored Aug 27, 2021
1 parent 27e08aa commit cd8a7a3
Show file tree
Hide file tree
Showing 10 changed files with 587 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ A CLI tool that generates `tf`/`json` and `tfstate` files based on existing infr
* [PAN-OS](/docs/panos.md)
* VCS
* [GitHub](/docs/github.md)
* [Gitlab](/docs/gitlab.md)
* Monitoring & System Management
* [Datadog](/docs/datadog.md)
* [New Relic](/docs/relic.md)
Expand Down
58 changes: 58 additions & 0 deletions cmd/provider_cmd_gitlab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2018 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd

import (
"log"
"strings"

gitLab_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/gitlab"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)

func newCmdGitLabImporter(options ImportOptions) *cobra.Command {
token := ""
baseURL := ""
groups := []string{}
cmd := &cobra.Command{
Use: "gitlab",
Short: "Import current state to Terraform configuration from GitLab",
Long: "Import current state to Terraform configuration from GitLab",
RunE: func(cmd *cobra.Command, args []string) error {
originalPathPattern := options.PathPattern
for _, group := range groups {
provider := newGitLabProvider()
options.PathPattern = originalPathPattern
options.PathPattern = strings.ReplaceAll(options.PathPattern, "{provider}", "{provider}/"+group)
log.Println(provider.GetName() + " importing group " + group)
err := Import(provider, options, []string{group, token, baseURL})
if err != nil {
return err
}
}
return nil
},
}
cmd.AddCommand(listCmd(newGitLabProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "repository", "repository=id1:id2:id4")
cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "YOUR_GITLAB_TOKEN or env param GITLAB_TOKEN")
cmd.PersistentFlags().StringSliceVarP(&groups, "group", "", []string{}, "paths to groups")
cmd.PersistentFlags().StringVarP(&baseURL, "base-url", "", "", "")
return cmd
}

func newGitLabProvider() terraformutils.ProviderGenerator {
return &gitLab_terraforming.GitLabProvider{}
}
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func providerImporterSubcommands() []func(options ImportOptions) *cobra.Command
newCmdPanosImporter,
// VCS
newCmdGithubImporter,
newCmdGitLabImporter,
// Monitoring & System Management
newCmdDatadogImporter,
newCmdNewRelicImporter,
Expand Down Expand Up @@ -108,6 +109,7 @@ func providerGenerators() map[string]func() terraformutils.ProviderGenerator {
newCloudflareProvider,
// VCS
newGitHubProvider,
newGitLabProvider,
// Monitoring & System Management
newDataDogProvider,
newNewRelicProvider,
Expand Down
20 changes: 20 additions & 0 deletions docs/gitlab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
### Use with GitLab

Example:

```shell
./terraformer import gitlab --group=GROUP_TO_IMPORT --resources=projects --token=YOUR_TOKEN # or GITLAB_TOKEN in env
./terraformer import gitlab --group=GROUP_TO_IMPORT --resources=groups --base-url=https://your-self-hosted-gitlab-domain/api/v4
```

List of supported resources:

* `projects`
* `gitlab_project`
* `gitlab_project_value`
* `gitlab_project_membership`
* `gitlab_tag_protection`
* `gitlab_branch_protection`
* `groups`
* `gitlab_group_membership`
* `gitlab_group_variable`
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go v3.0.233+incompatible
github.com/tencentyun/cos-go-sdk-v5 v0.7.19
github.com/vultr/govultr v0.5.0
github.com/xanzy/go-gitlab v0.50.2
github.com/yandex-cloud/go-genproto v0.0.0-20200722140432-762fe965ce77
github.com/yandex-cloud/go-sdk v0.0.0-20200722140627-2194e5077f13
github.com/zclconf/go-cty v1.8.4
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es
github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY=
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI=
Expand Down Expand Up @@ -1209,6 +1210,8 @@ github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37w
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vultr/govultr v0.5.0 h1:iQzYhzbokmpDARbvIkvTkoyS7WMH82zVTKAL1PZ4JOA=
github.com/vultr/govultr v0.5.0/go.mod h1:wZZXZbYbqyY1n3AldoeYNZK4Wnmmoq6dNFkvd5TV3ss=
github.com/xanzy/go-gitlab v0.50.2 h1:Qm/um2Jryuqusc6VmN7iZYVTQVzNynzSiuMJDnCU1wE=
github.com/xanzy/go-gitlab v0.50.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
Expand Down Expand Up @@ -1384,6 +1387,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -1597,6 +1601,7 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
google.golang.org/api v0.40.0 h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
Expand Down
103 changes: 103 additions & 0 deletions providers/gitlab/gitlab_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2018 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gitlab

import (
"os"

"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
)

type GitLabProvider struct { //nolint
terraformutils.Provider
group string
token string
baseURL string
}

func (p GitLabProvider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}

func (p GitLabProvider) GetProviderData(arg ...string) map[string]interface{} {
return map[string]interface{}{
"provider": map[string]interface{}{
"gitlab": map[string]interface{}{
// TODO: Should I add some default config here?
// "token": p.token,
// "base_url": p.baseURL,
},
},
}
}

func (p *GitLabProvider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"token": cty.StringVal(p.token),
// NOTE: Real provider doesn't support empty/null base_url, only set when there's value
"base_url": cty.StringVal(p.baseURL),
})
}

// Init GitLabProvider with group
func (p *GitLabProvider) Init(args []string) error {
p.group = args[0]
p.baseURL = gitLabDefaultURL
if len(args) < 2 {
if os.Getenv("GITLAB_TOKEN") == "" {
return errors.New("token requirement")
}
p.token = os.Getenv("GITLAB_TOKEN")
} else {
p.token = args[1]
}
if len(args) > 2 {
if args[2] != "" {
p.baseURL = args[2]
}
}
return nil
}

func (p *GitLabProvider) GetName() string {
return "gitlab"
}

func (p *GitLabProvider) InitService(serviceName string, verbose bool) error {
var isSupported bool
if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
return errors.New(p.GetName() + ": " + serviceName + " not supported service")
}
p.Service = p.GetSupportedService()[serviceName]
p.Service.SetName(serviceName)
p.Service.SetVerbose(verbose)
p.Service.SetProviderName(p.GetName())
p.Service.SetArgs(map[string]interface{}{
"group": p.group,
"token": p.token,
"base_url": p.baseURL,
})
return nil
}

// GetSupportedService return map of support service for gitlab
func (p *GitLabProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
return map[string]terraformutils.ServiceGenerator{
"projects": &ProjectGenerator{},
"groups": &GroupGenerator{},
}
}
41 changes: 41 additions & 0 deletions providers/gitlab/gitlab_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gitlab

import (
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/xanzy/go-gitlab"
)

const gitLabDefaultURL = "https://gitlab.com/api/v4/"

type GitLabService struct { //nolint
terraformutils.Service
}

func (g *GitLabService) createClient() (*gitlab.Client, error) {
if g.GetArgs()["base_url"].(string) == gitLabDefaultURL {
return g.createRegularClient()
}
return g.createEnterpriseClient()
}

func (g *GitLabService) createRegularClient() (*gitlab.Client, error) {
return gitlab.NewClient(g.Args["token"].(string))
}

func (g *GitLabService) createEnterpriseClient() (*gitlab.Client, error) {
return gitlab.NewClient(g.Args["token"].(string), gitlab.WithBaseURL(g.GetArgs()["base_url"].(string)))
}
Loading

0 comments on commit cd8a7a3

Please sign in to comment.