Skip to content

Commit b9c81f0

Browse files
authored
feat(controlplane): add unique name to registered integrations (#643)
Signed-off-by: Miguel Martinez Trivino <[email protected]>
1 parent 4cc02b7 commit b9c81f0

34 files changed

+701
-334
lines changed

app/cli/cmd/registered_integration_add.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2023 The Chainloop Authors.
2+
// Copyright 2024 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -29,12 +29,12 @@ import (
2929

3030
func newRegisteredIntegrationAddCmd() *cobra.Command {
3131
var options []string
32-
var integrationDescription string
32+
var integrationDescription, integrationName string
3333

3434
cmd := &cobra.Command{
35-
Use: "add INTEGRATION_ID --options key=value,key=value",
35+
Use: "add INTEGRATION_ID --name [registration-name] --options key=value,key=value",
3636
Short: "Register a new instance of an integration",
37-
Example: ` chainloop integration registered add dependencytrack --opt instance=https://deptrack.company.com,apiKey=1234567890 --opt username=chainloop`,
37+
Example: ` chainloop integration registered add dependencytrack --name send-to-prod --opt instance=https://deptrack.company.com,apiKey=1234567890 --opt username=chainloop`,
3838
Args: cobra.ExactArgs(1),
3939
RunE: func(cmd *cobra.Command, args []string) error {
4040
// Retrieve schema for validation and options marshaling
@@ -57,7 +57,7 @@ func newRegisteredIntegrationAddCmd() *cobra.Command {
5757
return err
5858
}
5959

60-
res, err := action.NewRegisteredIntegrationAdd(actionOpts).Run(args[0], integrationDescription, opts)
60+
res, err := action.NewRegisteredIntegrationAdd(actionOpts).Run(args[0], integrationName, integrationDescription, opts)
6161
if err != nil {
6262
return err
6363
}
@@ -66,6 +66,10 @@ func newRegisteredIntegrationAddCmd() *cobra.Command {
6666
},
6767
}
6868

69+
cmd.Flags().StringVar(&integrationName, "name", "", "unique registration name, i.e my-registration, sboms-to-prod, etc.")
70+
err := cmd.MarkFlagRequired("name")
71+
cobra.CheckErr(err)
72+
6973
cmd.Flags().StringVar(&integrationDescription, "description", "", "integration registration description")
7074
// StringSlice seems to struggle with comma-separated values such as p12 jsonKeys provided as passwords
7175
// So we need to use StringArrayVar instead

app/cli/cmd/registered_integration_list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ func registeredIntegrationListTableOutput(items []*action.RegisteredIntegrationI
5353
}
5454

5555
t := newTableWriter()
56-
t.AppendHeader(table.Row{"ID", "Description", "Kind", "Config", "Created At"})
56+
t.AppendHeader(table.Row{"ID", "Name", "Description", "Kind", "Config", "Created At"})
5757
for _, i := range items {
5858
var options []string
5959
for k, v := range i.Config {
6060
options = append(options, fmt.Sprintf("%s: %v", k, v))
6161
}
62-
t.AppendRow(table.Row{i.ID, i.Description, i.Kind, strings.Join(options, "\n"), i.CreatedAt.Format(time.RFC822)})
62+
t.AppendRow(table.Row{i.ID, i.Name, i.Description, i.Kind, strings.Join(options, "\n"), i.CreatedAt.Format(time.RFC822)})
6363
t.AppendSeparator()
6464
}
6565

app/cli/internal/action/registered_integration_add.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func NewRegisteredIntegrationAdd(cfg *ActionsOpts) *RegisteredIntegrationAdd {
3131
return &RegisteredIntegrationAdd{cfg}
3232
}
3333

34-
func (action *RegisteredIntegrationAdd) Run(pluginID, description string, options map[string]any) (*RegisteredIntegrationItem, error) {
34+
func (action *RegisteredIntegrationAdd) Run(pluginID, name, description string, options map[string]any) (*RegisteredIntegrationItem, error) {
3535
// Transform to structpb for transport
3636
requestConfig, err := structpb.NewStruct(options)
3737
if err != nil {
@@ -40,6 +40,7 @@ func (action *RegisteredIntegrationAdd) Run(pluginID, description string, option
4040

4141
client := pb.NewIntegrationsServiceClient(action.cfg.CPConnection)
4242
i, err := client.Register(context.Background(), &pb.IntegrationsServiceRegisterRequest{
43+
Name: name,
4344
PluginId: pluginID,
4445
Config: requestConfig,
4546
Description: description,

app/cli/internal/action/registered_integration_list.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ type RegisteredIntegrationList struct {
3030

3131
type RegisteredIntegrationItem struct {
3232
ID string `json:"id"`
33+
// Registration name used for declarative configuration
34+
Name string `json:"name"`
3335
// Integration backend kind, i.e slack, pagerduty, etc
34-
Kind string `json:"name"`
36+
Kind string `json:"kind"`
3537
// Integration description for display and differentiation purposes
3638
Description string `json:"description"`
3739
CreatedAt *time.Time `json:"createdAt"`
@@ -68,7 +70,7 @@ func pbRegisteredIntegrationItemToAction(in *pb.RegisteredIntegrationItem) (*Reg
6870
}
6971

7072
i := &RegisteredIntegrationItem{
71-
Kind: in.GetKind(), ID: in.GetId(),
73+
Kind: in.GetKind(), ID: in.GetId(), Name: in.GetName(),
7274
Description: in.GetDescription(),
7375
CreatedAt: toTimePtr(in.GetCreatedAt().AsTime()),
7476
}

app/controlplane/api/controlplane/v1/integrations.pb.go

Lines changed: 221 additions & 200 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/api/controlplane/v1/integrations.pb.validate.go

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/api/controlplane/v1/integrations.proto

Lines changed: 86 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -17,137 +17,142 @@ syntax = "proto3";
1717

1818
package controlplane.v1;
1919

20-
option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1";
21-
import "validate/validate.proto";
22-
import "google/protobuf/timestamp.proto";
23-
import "google/protobuf/struct.proto";
2420
import "controlplane/v1/response_messages.proto";
21+
import "google/protobuf/struct.proto";
22+
import "google/protobuf/timestamp.proto";
23+
import "validate/validate.proto";
24+
25+
option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1";
2526

2627
service IntegrationsService {
27-
// Integrations available and loaded in the controlplane ready to be used during registration
28-
rpc ListAvailable (IntegrationsServiceListAvailableRequest) returns (IntegrationsServiceListAvailableResponse);
29-
30-
// Registration Related operations
31-
// Register a new integration in the organization
32-
rpc Register (IntegrationsServiceRegisterRequest) returns (IntegrationsServiceRegisterResponse);
33-
// Delete registered integrations
34-
rpc Deregister (IntegrationsServiceDeregisterRequest) returns (IntegrationsServiceDeregisterResponse);
35-
// List registered integrations
36-
rpc ListRegistrations (IntegrationsServiceListRegistrationsRequest) returns (IntegrationsServiceListRegistrationsResponse);
37-
// View registered integration
38-
rpc DescribeRegistration (IntegrationsServiceDescribeRegistrationRequest) returns (IntegrationsServiceDescribeRegistrationResponse);
39-
40-
// Attachment Related operations
41-
// Attach an integration to a workflow
42-
rpc Attach (IntegrationsServiceAttachRequest) returns (IntegrationsServiceAttachResponse);
43-
// Detach integration from a workflow
44-
rpc Detach (IntegrationsServiceDetachRequest) returns (IntegrationsServiceDetachResponse);
45-
// List attachments
46-
rpc ListAttachments (ListAttachmentsRequest) returns (ListAttachmentsResponse);
28+
// Integrations available and loaded in the controlplane ready to be used during registration
29+
rpc ListAvailable(IntegrationsServiceListAvailableRequest) returns (IntegrationsServiceListAvailableResponse);
30+
31+
// Registration Related operations
32+
// Register a new integration in the organization
33+
rpc Register(IntegrationsServiceRegisterRequest) returns (IntegrationsServiceRegisterResponse);
34+
// Delete registered integrations
35+
rpc Deregister(IntegrationsServiceDeregisterRequest) returns (IntegrationsServiceDeregisterResponse);
36+
// List registered integrations
37+
rpc ListRegistrations(IntegrationsServiceListRegistrationsRequest) returns (IntegrationsServiceListRegistrationsResponse);
38+
// View registered integration
39+
rpc DescribeRegistration(IntegrationsServiceDescribeRegistrationRequest) returns (IntegrationsServiceDescribeRegistrationResponse);
40+
41+
// Attachment Related operations
42+
// Attach an integration to a workflow
43+
rpc Attach(IntegrationsServiceAttachRequest) returns (IntegrationsServiceAttachResponse);
44+
// Detach integration from a workflow
45+
rpc Detach(IntegrationsServiceDetachRequest) returns (IntegrationsServiceDetachResponse);
46+
// List attachments
47+
rpc ListAttachments(ListAttachmentsRequest) returns (ListAttachmentsResponse);
4748
}
4849

4950
message IntegrationsServiceRegisterRequest {
50-
// Kind of integration to register
51-
// This should match the ID of an existing plugin
52-
string plugin_id = 1 [(validate.rules).string.min_len = 1];
53-
// Arbitrary configuration for the integration
54-
google.protobuf.Struct config = 3 [(validate.rules).message.required = true];
55-
// Description of the registration, used for display purposes
56-
string description = 4;
51+
// unique, DNS-like name for the registration
52+
string name = 5 [(validate.rules).string = {min_len: 1}];
53+
// Kind of integration to register
54+
// This should match the ID of an existing plugin
55+
string plugin_id = 1 [(validate.rules).string.min_len = 1];
56+
// Arbitrary configuration for the integration
57+
google.protobuf.Struct config = 3 [(validate.rules).message.required = true];
58+
// Description of the registration, used for display purposes
59+
string description = 4;
5760
}
5861

5962
message IntegrationsServiceRegisterResponse {
60-
RegisteredIntegrationItem result = 1;
63+
RegisteredIntegrationItem result = 1;
6164
}
6265

63-
message IntegrationsServiceAttachRequest{
64-
// UUID of the workflow to attach
65-
string workflow_id = 1 [(validate.rules).string.uuid = true];
66-
// UUID of the integration registration to attach
67-
string integration_id = 2 [(validate.rules).string.uuid = true];
68-
// Arbitrary configuration for the integration
69-
google.protobuf.Struct config = 4 [(validate.rules).message.required = true];
66+
message IntegrationsServiceAttachRequest {
67+
// UUID of the workflow to attach
68+
string workflow_id = 1 [(validate.rules).string.uuid = true];
69+
// UUID of the integration registration to attach
70+
string integration_id = 2 [(validate.rules).string.uuid = true];
71+
// Arbitrary configuration for the integration
72+
google.protobuf.Struct config = 4 [(validate.rules).message.required = true];
7073
}
7174

72-
message IntegrationsServiceAttachResponse{
73-
IntegrationAttachmentItem result = 1;
75+
message IntegrationsServiceAttachResponse {
76+
IntegrationAttachmentItem result = 1;
7477
}
7578

76-
message IntegrationsServiceListAvailableRequest{}
77-
message IntegrationsServiceListAvailableResponse{
78-
repeated IntegrationAvailableItem result = 1;
79+
message IntegrationsServiceListAvailableRequest {}
80+
message IntegrationsServiceListAvailableResponse {
81+
repeated IntegrationAvailableItem result = 1;
7982
}
8083

8184
message IntegrationAvailableItem {
82-
// Integration identifier
83-
string id = 1;
84-
string version = 2;
85-
string description = 3;
85+
// Integration identifier
86+
string id = 1;
87+
string version = 2;
88+
string description = 3;
8689

87-
oneof type {
88-
PluginFanout fanout = 4;
89-
}
90+
oneof type {
91+
PluginFanout fanout = 4;
92+
}
9093
}
9194

9295
// PluginFanout describes a plugin that can be used to fanout attestation and materials to multiple integrations
9396
message PluginFanout {
94-
// Registration JSON schema
95-
bytes registration_schema = 4;
96-
// Attachment JSON schema
97-
bytes attachment_schema = 5;
98-
// List of materials that the integration is subscribed to
99-
repeated string subscribed_materials = 6;
97+
// Registration JSON schema
98+
bytes registration_schema = 4;
99+
// Attachment JSON schema
100+
bytes attachment_schema = 5;
101+
// List of materials that the integration is subscribed to
102+
repeated string subscribed_materials = 6;
100103
}
101104

102-
message IntegrationsServiceListRegistrationsRequest{}
103-
message IntegrationsServiceListRegistrationsResponse{
104-
repeated RegisteredIntegrationItem result = 1;
105+
message IntegrationsServiceListRegistrationsRequest {}
106+
message IntegrationsServiceListRegistrationsResponse {
107+
repeated RegisteredIntegrationItem result = 1;
105108
}
106109

107-
message IntegrationsServiceDescribeRegistrationRequest{
110+
message IntegrationsServiceDescribeRegistrationRequest {
108111
string id = 1 [(validate.rules).string.uuid = true];
109112
}
110113

111-
message IntegrationsServiceDescribeRegistrationResponse{
112-
RegisteredIntegrationItem result = 1;
114+
message IntegrationsServiceDescribeRegistrationResponse {
115+
RegisteredIntegrationItem result = 1;
113116
}
114117

115-
message IntegrationsServiceDetachRequest{
118+
message IntegrationsServiceDetachRequest {
116119
string id = 1 [(validate.rules).string.uuid = true];
117120
}
118121

119122
message IntegrationsServiceDetachResponse {}
120123

121-
message ListAttachmentsRequest{
124+
message ListAttachmentsRequest {
122125
// Filter by workflow
123126
string workflow_id = 1;
124127
}
125128

126-
message ListAttachmentsResponse{
127-
repeated IntegrationAttachmentItem result = 1;
129+
message ListAttachmentsResponse {
130+
repeated IntegrationAttachmentItem result = 1;
128131
}
129132

130133
message RegisteredIntegrationItem {
131-
string id = 1;
132-
string kind = 2;
133-
// Description of the registration, used for display purposes
134-
string description = 4;
135-
google.protobuf.Timestamp created_at = 3;
136-
// Arbitrary configuration for the integration
137-
bytes config = 5;
134+
string id = 1;
135+
// unique, DNS-like name for the registration
136+
string name = 6;
137+
string kind = 2;
138+
// Description of the registration, used for display purposes
139+
string description = 4;
140+
google.protobuf.Timestamp created_at = 3;
141+
// Arbitrary configuration for the integration
142+
bytes config = 5;
138143
}
139144

140145
message IntegrationAttachmentItem {
141-
string id = 1;
142-
google.protobuf.Timestamp created_at = 2;
143-
// Arbitrary configuration for the attachment
144-
bytes config = 3;
145-
RegisteredIntegrationItem integration = 4;
146-
WorkflowItem workflow = 5;
146+
string id = 1;
147+
google.protobuf.Timestamp created_at = 2;
148+
// Arbitrary configuration for the attachment
149+
bytes config = 3;
150+
RegisteredIntegrationItem integration = 4;
151+
WorkflowItem workflow = 5;
147152
}
148153

149154
message IntegrationsServiceDeregisterRequest {
150155
string id = 1 [(validate.rules).string.uuid = true];
151156
}
152157

153-
message IntegrationsServiceDeregisterResponse {}
158+
message IntegrationsServiceDeregisterResponse {}

0 commit comments

Comments
 (0)