diff --git a/go.mod b/go.mod index b5626f9841..e14497d323 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/axiomhq/hyperloglog v0.0.0-20230201085229-3ddf4bad03dc github.com/coreos/go-oidc/v3 v3.10.0 github.com/dexidp/dex/api/v2 v2.2.0 + github.com/digitalocean/godo v1.130.0 github.com/envoyproxy/go-control-plane v0.13.0 github.com/fluxcd/helm-controller/api v1.0.1 github.com/go-errors/errors v1.4.2 @@ -168,6 +169,7 @@ require ( github.com/golang/mock v1.6.0 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect @@ -293,7 +295,7 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect diff --git a/go.sum b/go.sum index 882a5bc5bd..1646800a79 100644 --- a/go.sum +++ b/go.sum @@ -408,6 +408,8 @@ github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc h1:8WFBn63wegobsY github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/digitalocean/godo v1.130.0 h1:DbJg0wvBxTkYjY5Q9S1mwzAZLd5Wht3r57yFH4yeMCk= +github.com/digitalocean/godo v1.130.0/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= @@ -638,6 +640,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -1428,8 +1432,8 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/services/integration/integration-type/digitalocean-team/configs/credentials.go b/services/integration/integration-type/digitalocean-team/configs/credentials.go new file mode 100644 index 0000000000..b641667924 --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/configs/credentials.go @@ -0,0 +1,5 @@ +package configs + +type IntegrationCredentials struct { + AuthToken string `json:"auth_token"` +} diff --git a/services/integration/integration-type/digitalocean-team/configs/general.go b/services/integration/integration-type/digitalocean-team/configs/general.go new file mode 100644 index 0000000000..a22e8373c3 --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/configs/general.go @@ -0,0 +1,7 @@ +package configs + +import "github.com/opengovern/og-util/pkg/integration" + +const ( + IntegrationTypeDigitalOceanTeam = integration.Type("digitalocean_team") // example: AWS_ACCOUNT, AZURE_SUBSCRIPTION +) diff --git a/services/integration/integration-type/digitalocean-team/configs/nats.go b/services/integration/integration-type/digitalocean-team/configs/nats.go new file mode 100644 index 0000000000..f43720e974 --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/configs/nats.go @@ -0,0 +1,9 @@ +package configs + +const ( + StreamName = "og_describer_digitalocean_team" + JobQueueTopic = "og_describer_digitalocean_team_job_queue" + ConsumerGroup = "describer-digitalocean-team" + JobQueueTopicManuals = "og_describer_digitalocean_team_manuals_job_queue" + ConsumerGroupManuals = "describer-digitalocean-team-manuals" +) diff --git a/services/integration/integration-type/digitalocean-team/configs/resource_types_list.go b/services/integration/integration-type/digitalocean-team/configs/resource_types_list.go new file mode 100755 index 0000000000..71f13042fb --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/configs/resource_types_list.go @@ -0,0 +1,5 @@ +package configs + +var TablesToResourceTypes = map[string]string{} + +var ResourceTypesList = []string{} diff --git a/services/integration/integration-type/digitalocean-team/digitalocean-team.go b/services/integration/integration-type/digitalocean-team/digitalocean-team.go new file mode 100644 index 0000000000..9060ea826a --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/digitalocean-team.go @@ -0,0 +1,69 @@ +package digitalocean_team + +import ( + "context" + "encoding/json" + digitaloceanDescriberLocal "github.com/opengovern/opengovernance/services/integration/integration-type/digitalocean-team/configs" + "github.com/opengovern/opengovernance/services/integration/integration-type/digitalocean-team/discovery" + "github.com/opengovern/opengovernance/services/integration/integration-type/digitalocean-team/healthcheck" + "github.com/opengovern/opengovernance/services/integration/integration-type/interfaces" + "github.com/opengovern/opengovernance/services/integration/models" +) + +type DigitaloceanTeamIntegration struct{} + +func (i *DigitaloceanTeamIntegration) GetConfiguration() interfaces.IntegrationConfiguration { + return interfaces.IntegrationConfiguration{ + NatsScheduledJobsTopic: digitaloceanDescriberLocal.JobQueueTopic, + NatsManualJobsTopic: digitaloceanDescriberLocal.JobQueueTopicManuals, + NatsStreamName: digitaloceanDescriberLocal.StreamName, + + UISpecFileName: "digitalocean-team.json", + } +} + +func (i *DigitaloceanTeamIntegration) HealthCheck(jsonData []byte, _ string, _ map[string]string, _ map[string]string) (bool, error) { + var credentials digitaloceanDescriberLocal.IntegrationCredentials + err := json.Unmarshal(jsonData, &credentials) + if err != nil { + return false, err + } + + return healthcheck.DigitalOceanTeamHealthcheck(context.TODO(), healthcheck.Config{ + AuthToken: credentials.AuthToken, + }) +} + +func (i *DigitaloceanTeamIntegration) DiscoverIntegrations(jsonData []byte) ([]models.Integration, error) { + var credentials digitaloceanDescriberLocal.IntegrationCredentials + err := json.Unmarshal(jsonData, &credentials) + if err != nil { + return nil, err + } + + team, err := discovery.DigitalOceanTeamDiscovery(context.TODO(), discovery.Config{ + AuthToken: credentials.AuthToken, + }) + if err != nil { + return nil, err + } + + return []models.Integration{ + { + ProviderID: team.ID, + Name: team.Name, + }, + }, nil +} + +func (i *DigitaloceanTeamIntegration) GetResourceTypesByLabels(_ map[string]string) ([]string, error) { + return digitaloceanDescriberLocal.ResourceTypesList, nil +} + +func (i *DigitaloceanTeamIntegration) GetResourceTypeFromTableName(tableName string) string { + if v, ok := digitaloceanDescriberLocal.TablesToResourceTypes[tableName]; ok { + return v + } + + return "" +} diff --git a/services/integration/integration-type/digitalocean-team/discovery/discovery.go b/services/integration/integration-type/digitalocean-team/discovery/discovery.go new file mode 100644 index 0000000000..4a7912195d --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/discovery/discovery.go @@ -0,0 +1,36 @@ +package discovery + +import ( + "context" + "errors" + "github.com/digitalocean/godo" +) + +type Config struct { + AuthToken string +} + +type Team struct { + ID string `json:"id"` + Name string `json:"name"` +} + +func DigitalOceanTeamDiscovery(ctx context.Context, config Config) (*Team, error) { + client := godo.NewFromToken(config.AuthToken) + + account, resp, err := client.Account.Get(ctx) + if err != nil { + return nil, err + } + if resp.StatusCode != 200 { + return nil, err + } + if account.Team == nil { + return nil, errors.New("team not found") + } + + return &Team{ + ID: account.Team.UUID, + Name: account.Team.Name, + }, nil +} diff --git a/services/integration/integration-type/digitalocean-team/healthcheck/healthcheck.go b/services/integration/integration-type/digitalocean-team/healthcheck/healthcheck.go new file mode 100644 index 0000000000..e4e0f6fad3 --- /dev/null +++ b/services/integration/integration-type/digitalocean-team/healthcheck/healthcheck.go @@ -0,0 +1,25 @@ +package healthcheck + +import ( + "context" + "github.com/digitalocean/godo" +) + +type Config struct { + AuthToken string +} + +func DigitalOceanTeamHealthcheck(ctx context.Context, config Config) (bool, error) { + client := godo.NewFromToken(config.AuthToken) + + _, resp, err := client.Account.Get(ctx) + if err != nil { + return false, err + } + + if resp.StatusCode != 200 { + return false, err + } + + return true, nil +}