Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/cli/cmd/integration_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@ import (
"github.com/spf13/cobra"
)

var integrationDescription string

func newConfigIntegratioAddCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "Add integration",
}

cmd.PersistentFlags().StringVar(&integrationDescription, "description", "", "integration registration description")
cmd.AddCommand(newIntegrationAddDepTrackCmd())
return cmd
}
2 changes: 1 addition & 1 deletion app/cli/cmd/integration_add_deptrack.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func newIntegrationAddDepTrackCmd() *cobra.Command {
return fmt.Errorf("retrieving token from stdin: %w", err)
}

res, err := action.NewIntegrationAddDeptrack(actionOpts).Run(instance, string(apiKey), allowAutoCreate)
res, err := action.NewIntegrationAddDeptrack(actionOpts).Run(instance, string(apiKey), integrationDescription, allowAutoCreate)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions app/cli/cmd/integration_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ func integrationListTableOutput(items []*action.IntegrationItem) error {
}

t := newTableWriter()
t.AppendHeader(table.Row{"ID", "Name", "Config", "Created At"})
t.AppendHeader(table.Row{"ID", "Description", "Kind", "Config", "Created At"})
for _, i := range items {
var options []string
for k, v := range i.Config {
options = append(options, fmt.Sprintf("%s: %v", k, v))
}
t.AppendRow(table.Row{i.ID, i.Name, strings.Join(options, "\n"), i.CreatedAt.Format(time.RFC822)})
t.AppendRow(table.Row{i.ID, i.Description, i.Kind, strings.Join(options, "\n"), i.CreatedAt.Format(time.RFC822)})
t.AppendSeparator()
}

Expand Down
2 changes: 1 addition & 1 deletion app/cli/cmd/workflow_integration_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func integrationAttachmentListTableOutput(attachments []*action.IntegrationAttac
}
options = append(options, fmt.Sprintf("%s: %v", k, v))
}
t.AppendRow(table.Row{i.ID, integration.Name, strings.Join(options, "\n"), i.CreatedAt.Format(time.RFC822), wf.NamespacedName()})
t.AppendRow(table.Row{i.ID, integration.Kind, strings.Join(options, "\n"), i.CreatedAt.Format(time.RFC822), wf.NamespacedName()})
t.AppendSeparator()
}

Expand Down
3 changes: 2 additions & 1 deletion app/cli/internal/action/integration_add_deptrack.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewIntegrationAddDeptrack(cfg *ActionsOpts) *IntegrationAddDeptrack {
return &IntegrationAddDeptrack{cfg}
}

func (action *IntegrationAddDeptrack) Run(host, apiKey string, allowAutoProjectCreation bool) (*IntegrationItem, error) {
func (action *IntegrationAddDeptrack) Run(host, apiKey, description string, allowAutoProjectCreation bool) (*IntegrationItem, error) {
client := pb.NewIntegrationsServiceClient(action.cfg.CPConnection)
cdxRegistrationRequest := cxpb.RegistrationRequest{
ApiKey: apiKey,
Expand All @@ -48,6 +48,7 @@ func (action *IntegrationAddDeptrack) Run(host, apiKey string, allowAutoProjectC
i, err := client.Register(context.Background(), &pb.IntegrationsServiceRegisterRequest{
Kind: deptrack.ID,
RegistrationConfig: anyConfig,
DisplayName: description,
})
if err != nil {
return nil, err
Expand Down
16 changes: 10 additions & 6 deletions app/cli/internal/action/integration_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ type IntegrationList struct {
}

type IntegrationItem struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt *time.Time `json:"createdAt"`
Config map[string]interface{} `json:"config"`
ID string `json:"id"`
// Integration backend kind, i.e slack, pagerduty, etc
Kind string `json:"name"`
// Integration description for display and differentiation purposes
Description string `json:"description"`
CreatedAt *time.Time `json:"createdAt"`
Config map[string]interface{} `json:"config"`
}

func NewIntegrationList(cfg *ActionsOpts) *IntegrationList {
Expand Down Expand Up @@ -65,8 +68,9 @@ func pbIntegrationItemToAction(in *pb.IntegrationItem) (*IntegrationItem, error)
}

i := &IntegrationItem{
Name: in.GetKind(), ID: in.GetId(),
CreatedAt: toTimePtr(in.GetCreatedAt().AsTime()),
Kind: in.GetKind(), ID: in.GetId(),
Description: in.GetDisplayName(),
CreatedAt: toTimePtr(in.GetCreatedAt().AsTime()),
}

// Old format does not include config so we skip it
Expand Down
293 changes: 158 additions & 135 deletions app/controlplane/api/controlplane/v1/integrations.pb.go

Large diffs are not rendered by default.

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

5 changes: 5 additions & 0 deletions app/controlplane/api/controlplane/v1/integrations.proto
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ service IntegrationsService {

message IntegrationsServiceRegisterRequest {
// Kind of integration to register
// This should match the ID of an existing integration
string kind = 1 [(validate.rules).string.min_len = 1];
// Description of the registration, used for display purposes
string display_name = 3;
// Associated registration configuration
google.protobuf.Any registration_config = 2 [(validate.rules).any.required = true];
}
Expand Down Expand Up @@ -82,6 +85,8 @@ message ListAttachmentsResponse{
message IntegrationItem {
string id = 1;
string kind = 2;
// Description of the registration, used for display purposes
string display_name = 4;
google.protobuf.Timestamp created_at = 3;
// Arbitrary configuration for the integration
bytes config = 5;
Expand Down
39 changes: 36 additions & 3 deletions app/controlplane/api/gen/frontend/controlplane/v1/integrations.ts

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

28 changes: 21 additions & 7 deletions app/controlplane/internal/biz/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,32 @@ type IntegrationAttachment struct {
}

type Integration struct {
ID uuid.UUID
Kind string
CreatedAt *time.Time
Config []byte
ID uuid.UUID
// Kind is the type of the integration, it matches the registered extension ID
Kind string
// DisplayName is a human readable description of the integration registration
// It helps to differentiate different instances of the same kind
DisplayName string
// Registration Configuration, usually JSON marshalled
Config []byte
// Identifier to the external provider where any secret information is stored
SecretName string
CreatedAt *time.Time
}

type IntegrationAndAttachment struct {
*Integration
*IntegrationAttachment
}

type IntegrationCreateOpts struct {
Kind, DisplayName, SecretName string
OrgID uuid.UUID
Config []byte
}

type IntegrationRepo interface {
Create(ctx context.Context, orgID uuid.UUID, kind string, secretID string, config []byte) (*Integration, error)
Create(ctx context.Context, opts *IntegrationCreateOpts) (*Integration, error)
List(ctx context.Context, orgID uuid.UUID) ([]*Integration, error)
FindByIDInOrg(ctx context.Context, orgID, ID uuid.UUID) (*Integration, error)
SoftDelete(ctx context.Context, ID uuid.UUID) error
Expand Down Expand Up @@ -90,7 +101,7 @@ func NewIntegrationUseCase(opts *NewIntegrationUseCaseOpts) *IntegrationUseCase
}

// Persist the secret and integration with its configuration in the database
func (uc *IntegrationUseCase) RegisterAndSave(ctx context.Context, orgID string, i sdk.FanOut, regConfig *anypb.Any) (*Integration, error) {
func (uc *IntegrationUseCase) RegisterAndSave(ctx context.Context, orgID, displayName string, i sdk.FanOut, regConfig *anypb.Any) (*Integration, error) {
orgUUID, err := uuid.Parse(orgID)
if err != nil {
return nil, NewErrInvalidUUID(err)
Expand All @@ -117,7 +128,10 @@ func (uc *IntegrationUseCase) RegisterAndSave(ctx context.Context, orgID string,
}

// Persist the integration configuration
return uc.integrationRepo.Create(ctx, orgUUID, i.Describe().ID, secretID, registrationResponse.Configuration)
return uc.integrationRepo.Create(ctx, &IntegrationCreateOpts{
OrgID: orgUUID, Kind: i.Describe().ID, DisplayName: displayName,
SecretName: secretID, Config: registrationResponse.Configuration,
})
}

type AttachOpts struct {
Expand Down
6 changes: 4 additions & 2 deletions app/controlplane/internal/biz/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

func (s *testSuite) TestCreate() {
const kind = "my-integration"
const description = "my registration description"
assert := assert.New(s.T())

// Mocked integration that will return both generic configuration and credentials
Expand All @@ -47,9 +48,10 @@ func (s *testSuite) TestCreate() {
Password: "key", URL: "host"},
}, nil)

got, err := s.Integration.RegisterAndSave(ctx, s.org.ID, integration, s.configAny)
got, err := s.Integration.RegisterAndSave(ctx, s.org.ID, description, integration, s.configAny)
assert.NoError(err)
assert.Equal(kind, got.Kind)
assert.Equal(description, got.DisplayName)

// Check configuration was stored
assert.Equal(s.config, got.Config)
Expand Down Expand Up @@ -207,7 +209,7 @@ func (s *testSuite) SetupTest() {
fanOut.On("Register", ctx, mock.Anything).Return(&sdk.RegistrationResponse{Configuration: s.config}, nil)
s.fanOutIntegration = fanOut

s.integration, err = s.Integration.RegisterAndSave(ctx, s.org.ID, fanOut, s.configAny)
s.integration, err = s.Integration.RegisterAndSave(ctx, s.org.ID, "my integration instance", fanOut, s.configAny)
assert.NoError(err)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (s *OrgIntegrationTestSuite) SetupTest() {
configAny, err := anypb.New(config)
assert.NoError(err)

_, err = s.Integration.RegisterAndSave(ctx, s.org.ID, integration, configAny)
_, err = s.Integration.RegisterAndSave(ctx, s.org.ID, "", integration, configAny)
assert.NoError(err)

// OCI repository
Expand Down
Loading