Skip to content

Commit

Permalink
Merge pull request #258 from cloudskiff/add_github_repository
Browse files Browse the repository at this point in the history
Add support for github_repository
  • Loading branch information
eliecharra authored Feb 16, 2021
2 parents 694c178 + 2c42fb3 commit da81eaf
Show file tree
Hide file tree
Showing 41 changed files with 9,322 additions and 97 deletions.
3 changes: 3 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Sometimes mock use unexported struct
inpackage: true
testonly: true
3 changes: 2 additions & 1 deletion doc/cmd/scan/supported_resources/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Supported remotes

- [AWS](aws.md)
- [AWS](aws.md)
- [Github](github.md)
23 changes: 23 additions & 0 deletions doc/cmd/scan/supported_resources/github.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Github

## Authentication

To use driftctl, we need credentials to make authenticated requests to github. Just like the terraform provider, we retrieve config from [environment variables](https://registry.terraform.io/providers/integrations/github/latest/docs#argument-reference).

```bash
$ GITHUB_TOKEN=14758f1afd44c09b7992073ccf00b43d GITHUB_ORGANIZATION=my-org driftctl scan --to github+tf
```

## Least privileged policy

Below you can find the minimal scope required for driftctl to be able to scan every github supported resources.

```shell
repo # Required to enumerate public and private repos
```

**⚠️ Beware that if you don't set correct permissions for your token, you won't see any errors and all resources will appear as deleted from remote**

## Supported resources

- [x] github_repository
12 changes: 4 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,31 @@ require (
github.com/eapache/go-resiliency v1.2.0
github.com/fatih/color v1.9.0
github.com/getsentry/sentry-go v0.9.0
github.com/google/go-cmp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.5.1
github.com/hashicorp/go-hclog v0.9.2
github.com/hashicorp/go-plugin v1.3.0
github.com/hashicorp/go-version v1.2.1
github.com/hashicorp/terraform v0.14.0
github.com/hashicorp/terraform-exec v0.12.0
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
github.com/jarcoal/httpmock v1.0.6
github.com/jmespath/go-jmespath v0.3.0
github.com/joho/godotenv v1.3.0
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/go-testing-interface v1.0.4 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce
github.com/pkg/errors v0.9.1
github.com/r3labs/diff/v2 v2.6.0
github.com/shurcooL/githubv4 v0.0.0-20201206200315-234843c633fa
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a // indirect
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.6.1
github.com/zclconf/go-cty v1.7.0
go.uber.org/atomic v1.4.0
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
)
107 changes: 30 additions & 77 deletions go.sum

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions mocks/GithubGraphQLClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/cmd/driftctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func TestDriftctlCmd_Scan(t *testing.T) {
env: map[string]string{
"DCTL_TO": "test",
},
err: fmt.Errorf("unsupported cloud provider 'test'\nValid values are: aws+tf"),
err: fmt.Errorf("unsupported cloud provider 'test'\nValid values are: aws+tf,github+tf"),
},
{
env: map[string]string{
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ func TestScanCmd_Invalid(t *testing.T) {
{args: []string{"scan", "-e"}, expected: `unknown shorthand flag: 'e' in -e`},
{args: []string{"scan", "--error"}, expected: `unknown flag: --error`},
{args: []string{"scan", "-t"}, expected: `flag needs an argument: 't' in -t`},
{args: []string{"scan", "-t", "glou"}, expected: "unsupported cloud provider 'glou'\nValid values are: aws+tf"},
{args: []string{"scan", "-t", "glou"}, expected: "unsupported cloud provider 'glou'\nValid values are: aws+tf,github+tf"},
{args: []string{"scan", "--to"}, expected: `flag needs an argument: --to`},
{args: []string{"scan", "--to", "glou"}, expected: "unsupported cloud provider 'glou'\nValid values are: aws+tf"},
{args: []string{"scan", "--to", "glou"}, expected: "unsupported cloud provider 'glou'\nValid values are: aws+tf,github+tf"},
{args: []string{"scan", "-f"}, expected: `flag needs an argument: 'f' in -f`},
{args: []string{"scan", "--from"}, expected: `flag needs an argument: --from`},
{args: []string{"scan", "--from"}, expected: `flag needs an argument: --from`},
Expand Down
3 changes: 3 additions & 0 deletions pkg/iac/deserializers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package iac
import (
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
ghdeserializer "github.com/cloudskiff/driftctl/pkg/resource/github/deserializer"
)

func Deserializers() []deserializer.CTYDeserializer {
Expand Down Expand Up @@ -53,5 +54,7 @@ func Deserializers() []deserializer.CTYDeserializer {
awsdeserializer.NewSNSTopicPolicyDeserializer(),
awsdeserializer.NewSNSTopicSubscriptionDeserializer(),
awsdeserializer.NewDynamoDBTableDeserializer(),

ghdeserializer.NewGithubRepositoryDeserializer(),
}
}
4 changes: 0 additions & 4 deletions pkg/iac/terraform/state/terraform_state_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ func (r *TerraformStateReader) decode(values map[string][]cty.Value) ([]resource
typ := deserializer.HandledType().String()
vals, exists := values[typ]
if !exists {
logrus.WithFields(logrus.Fields{
"path": r.config.Path,
"backend": r.config.Backend,
}).Debugf("No resource of type %s found in state", typ)
continue
}
decodedResources, err := deserializer.Deserialize(vals)
Expand Down
73 changes: 72 additions & 1 deletion pkg/iac/terraform/state/terraform_state_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cloudskiff/driftctl/pkg/iac"
"github.com/cloudskiff/driftctl/pkg/iac/terraform/state/backend"
"github.com/cloudskiff/driftctl/pkg/remote/aws"
"github.com/cloudskiff/driftctl/pkg/remote/github"
"github.com/cloudskiff/driftctl/pkg/resource"
"github.com/cloudskiff/driftctl/pkg/terraform"
"github.com/cloudskiff/driftctl/test/goldenfile"
Expand All @@ -35,7 +36,7 @@ func TestReadStateInvalid(t *testing.T) {
}
}

func TestTerraformStateReader_Resources(t *testing.T) {
func TestTerraformStateReader_AWS_Resources(t *testing.T) {
tests := []struct {
name string
dirName string
Expand Down Expand Up @@ -143,6 +144,76 @@ func TestTerraformStateReader_Resources(t *testing.T) {
}
}

func TestTerraformStateReader_Github_Resources(t *testing.T) {
tests := []struct {
name string
dirName string
wantErr bool
}{
{name: "github repository", dirName: "github_repository", wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
shouldUpdate := tt.dirName == *goldenfile.Update

var realProvider *github.GithubTerraformProvider

if shouldUpdate {
var err error
realProvider, err = github.NewGithubTerraformProvider()
if err != nil {
t.Fatal(err)
}
err = realProvider.Init()
if err != nil {
t.Fatal(err)
}
}

provider := mocks.NewMockedGoldenTFProvider(tt.dirName, realProvider, shouldUpdate)
library := terraform.NewProviderLibrary()
library.AddProvider(terraform.GITHUB, provider)

b, _ := backend.NewFileReader(path.Join(goldenfile.GoldenFilePath, tt.dirName, "terraform.tfstate"))
r := &TerraformStateReader{
backend: b,
library: library,
deserializers: iac.Deserializers(),
}

got, err := r.Resources()
resGoldenName := "result.golden.json"
if shouldUpdate {
unm, err := json.Marshal(got)
if err != nil {
panic(err)
}
goldenfile.WriteFile(tt.dirName, unm, resGoldenName)
}

file := goldenfile.ReadFile(tt.dirName, resGoldenName)
var want []interface{}
if err := json.Unmarshal(file, &want); err != nil {
panic(err)
}

if (err != nil) != tt.wantErr {
t.Errorf("Resources() error = %v, wantErr %v", err, tt.wantErr)
return
}
changelog, err := diff.Diff(convert(got), want)
if err != nil {
panic(err)
}
if len(changelog) > 0 {
for _, change := range changelog {
t.Errorf("%s got = %v, want %v", strings.Join(change.Path, "."), change.From, change.To)
}
}
})
}
}

func convert(got []resource.Resource) []interface{} {
unm, err := json.Marshal(got)
if err != nil {
Expand Down
74 changes: 74 additions & 0 deletions pkg/iac/terraform/state/test/github_repository/result.golden.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[
{
"AllowMergeCommit": true,
"AllowRebaseMerge": true,
"AllowSquashMerge": true,
"ArchiveOnDestroy": null,
"Archived": false,
"AutoInit": null,
"DefaultBranch": "main",
"DeleteBranchOnMerge": false,
"Description": "this is a private repo",
"Etag": "W/\"04420b05933b55f136bb12b9c8d1748e67e143b290d72ecadd0fd2d4f4a3048a\"",
"FullName": "driftctl-test/private-repo",
"GitCloneUrl": "git://github.com/driftctl-test/private-repo.git",
"GitignoreTemplate": null,
"HasDownloads": false,
"HasIssues": false,
"HasProjects": false,
"HasWiki": false,
"HomepageUrl": "",
"HtmlUrl": "https://github.com/driftctl-test/private-repo",
"HttpCloneUrl": "https://github.com/driftctl-test/private-repo.git",
"Id": "private-repo",
"IsTemplate": false,
"LicenseTemplate": null,
"Name": "private-repo",
"NodeId": "MDEwOlJlcG9zaXRvcnkzMzkwNzY5NjQ=",
"Private": true,
"RepoId": 339076964,
"SshCloneUrl": "[email protected]:driftctl-test/private-repo.git",
"SvnUrl": "https://github.com/driftctl-test/private-repo",
"Topics": null,
"Visibility": "private",
"VulnerabilityAlerts": false,
"Pages": [],
"Template": []
},
{
"AllowMergeCommit": true,
"AllowRebaseMerge": true,
"AllowSquashMerge": true,
"ArchiveOnDestroy": null,
"Archived": false,
"AutoInit": null,
"DefaultBranch": "main",
"DeleteBranchOnMerge": false,
"Description": "",
"Etag": "W/\"3e7a2583fb97097c8acbcb4c289e46fc0db70341071c5f55972bbd3270a2b957\"",
"FullName": "driftctl-test/public-repo",
"GitCloneUrl": "git://github.com/driftctl-test/public-repo.git",
"GitignoreTemplate": null,
"HasDownloads": false,
"HasIssues": false,
"HasProjects": false,
"HasWiki": false,
"HomepageUrl": "",
"HtmlUrl": "https://github.com/driftctl-test/public-repo",
"HttpCloneUrl": "https://github.com/driftctl-test/public-repo.git",
"Id": "public-repo",
"IsTemplate": false,
"LicenseTemplate": null,
"Name": "public-repo",
"NodeId": "MDEwOlJlcG9zaXRvcnkzMzkwNzY5Nzg=",
"Private": false,
"RepoId": 339076978,
"SshCloneUrl": "[email protected]:driftctl-test/public-repo.git",
"SvnUrl": "https://github.com/driftctl-test/public-repo",
"Topics": null,
"Visibility": "public",
"VulnerabilityAlerts": false,
"Pages": [],
"Template": []
}
]
Loading

0 comments on commit da81eaf

Please sign in to comment.