From 326c422ca0d975119d16cc66a37e98df67108fa4 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 12 Jul 2023 16:00:19 +0200 Subject: [PATCH 1/4] feat(api): list cas-backends Signed-off-by: Miguel Martinez Trivino --- .golangci.yml | 15 + app/cli/cmd/attached_integration_list.go | 8 +- app/cli/cmd/casbackend.go | 30 ++ app/cli/cmd/casbackend_list.go | 75 +++++ app/cli/cmd/output.go | 3 +- app/cli/cmd/registered_integration_list.go | 6 +- app/cli/cmd/root.go | 5 +- app/cli/internal/action/casbackend_list.go | 89 +++++ .../internal/action/config_current_context.go | 7 - .../api/controlplane/v1/cas_backends.pb.go | 234 +++++++++++++ .../v1/cas_backends.pb.validate.go | 276 +++++++++++++++ .../api/controlplane/v1/cas_backends.proto | 32 ++ .../controlplane/v1/cas_backends_grpc.pb.go | 124 +++++++ .../controlplane/v1/response_messages.pb.go | 313 ++++++++++++++---- .../v1/response_messages.pb.validate.go | 168 ++++++++++ .../controlplane/v1/response_messages.proto | 20 ++ .../frontend/controlplane/v1/cas_backends.ts | 272 +++++++++++++++ .../controlplane/v1/response_messages.ts | 199 +++++++++++ app/controlplane/cmd/wire_gen.go | 2 + app/controlplane/internal/biz/casbackend.go | 10 + app/controlplane/internal/data/casbackend.go | 15 + app/controlplane/internal/server/grpc.go | 2 + .../internal/service/casbackend.go | 77 +++++ app/controlplane/internal/service/service.go | 1 + 24 files changed, 1908 insertions(+), 75 deletions(-) create mode 100644 app/cli/cmd/casbackend.go create mode 100644 app/cli/cmd/casbackend_list.go create mode 100644 app/cli/internal/action/casbackend_list.go create mode 100644 app/controlplane/api/controlplane/v1/cas_backends.pb.go create mode 100644 app/controlplane/api/controlplane/v1/cas_backends.pb.validate.go create mode 100644 app/controlplane/api/controlplane/v1/cas_backends.proto create mode 100644 app/controlplane/api/controlplane/v1/cas_backends_grpc.pb.go create mode 100644 app/controlplane/api/gen/frontend/controlplane/v1/cas_backends.ts create mode 100644 app/controlplane/internal/service/casbackend.go diff --git a/.golangci.yml b/.golangci.yml index 197a22f4b..6f82bf6fd 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -57,3 +57,18 @@ linters-settings: - ^print.*$ - '^t\.Error.*$(# forbid t.Error in favor of using testify\.)?' - '^t\.Fatal.*$(# forbid t.Fatal in favor of using testify\.)?' + staticcheck: + # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Disable deprecation checks, note that we need to deprecate it because golangci-lint doesn't support + # setting a non-error exit code on info severity (setup below) + # https://github.com/golangci/golangci-lint/issues/1981 + checks: ["all", "-SA1019"] +severity: + default-severity: error + # NOTE: this still makes the CLI exit with 1 hence the fact that we disabled the rule above as well + # https://github.com/golangci/golangci-lint/issues/1981 + rules: + - linters: + - staticcheck + text: "SA1019:" + severity: info \ No newline at end of file diff --git a/app/cli/cmd/attached_integration_list.go b/app/cli/cmd/attached_integration_list.go index b10de5cde..9e69ca3fa 100644 --- a/app/cli/cmd/attached_integration_list.go +++ b/app/cli/cmd/attached_integration_list.go @@ -45,12 +45,14 @@ func newAttachedIntegrationListCmd() *cobra.Command { } func attachedIntegrationListTableOutput(attachments []*action.AttachedIntegrationItem) error { - if len(attachments) == 0 { - fmt.Println("there are no integration attached") + switch n := len(attachments); { + case n == 0: + fmt.Println("there are no integrations attached") return nil + case n > 1: + fmt.Println("Integrations attached to workflows") } - fmt.Println("Integrations attached to workflows") t := newTableWriter() t.AppendHeader(table.Row{"ID", "Kind", "Config", "Attached At", "Workflow"}) for _, attachment := range attachments { diff --git a/app/cli/cmd/casbackend.go b/app/cli/cmd/casbackend.go new file mode 100644 index 000000000..dfa818000 --- /dev/null +++ b/app/cli/cmd/casbackend.go @@ -0,0 +1,30 @@ +// +// Copyright 2023 The Chainloop 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 ( + "github.com/spf13/cobra" +) + +func newCASBackendCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "cas-backend", + Short: "Operations on Artifact CAS backends", + } + + cmd.AddCommand(newCASBackendListCmd()) + return cmd +} diff --git a/app/cli/cmd/casbackend_list.go b/app/cli/cmd/casbackend_list.go new file mode 100644 index 000000000..c3e92a452 --- /dev/null +++ b/app/cli/cmd/casbackend_list.go @@ -0,0 +1,75 @@ +// +// Copyright 2023 The Chainloop 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 ( + "fmt" + "time" + + "github.com/chainloop-dev/chainloop/app/cli/internal/action" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" +) + +func newCASBackendListCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List CAS Backends from your organization", + RunE: func(cmd *cobra.Command, args []string) error { + res, err := action.NewCASBackendList(actionOpts).Run() + if err != nil { + return err + } + + return encodeOutput(res, casBackendListTableOutput) + }, + } + + cmd.Flags().BoolVar(&full, "full", false, "show the full output") + return cmd +} + +func casBackendListTableOutput(backends []*action.CASBackendItem) error { + if len(backends) == 0 { + fmt.Println("there are no cas backends associated") + return nil + } + + t := newTableWriter() + header := table.Row{"ID", "Name", "Provider", "Default"} + if full { + header = append(header, "Validation Status", "Created At", "Validated At") + } + + t.AppendHeader(header) + for _, b := range backends { + r := table.Row{b.ID, b.Name, b.Provider, b.Default} + if full { + r = append(r, b.ValidationStatus, + b.CreatedAt.Format(time.RFC822), + b.ValidatedAt.Format(time.RFC822), + ) + } + + t.AppendRow(r) + t.AppendSeparator() + } + + t.Render() + + return nil +} diff --git a/app/cli/cmd/output.go b/app/cli/cmd/output.go index 24fca31e7..2fbcbf7e5 100644 --- a/app/cli/cmd/output.go +++ b/app/cli/cmd/output.go @@ -42,7 +42,8 @@ type tabulatedData interface { []*action.RegisteredIntegrationItem | []*action.AvailableIntegrationItem | []*action.AttachedIntegrationItem | - []*action.MembershipItem + []*action.MembershipItem | + []*action.CASBackendItem } var ErrOutputFormatNotImplemented = errors.New("format not implemented") diff --git a/app/cli/cmd/registered_integration_list.go b/app/cli/cmd/registered_integration_list.go index 0cc59646c..025227fcf 100644 --- a/app/cli/cmd/registered_integration_list.go +++ b/app/cli/cmd/registered_integration_list.go @@ -44,12 +44,14 @@ func newRegisteredIntegrationListCmd() *cobra.Command { } func registeredIntegrationListTableOutput(items []*action.RegisteredIntegrationItem) error { - if len(items) == 0 { + switch n := len(items); { + case n == 0: fmt.Println("there are no third party integrations configured in your organization yet") return nil + case n > 1: + fmt.Println("Integrations registered and configured in your organization") } - fmt.Println("Integrations registered and configured in your organization") t := newTableWriter() t.AppendHeader(table.Row{"ID", "Description", "Kind", "Config", "Created At"}) for _, i := range items { diff --git a/app/cli/cmd/root.go b/app/cli/cmd/root.go index 254588ac8..6bb6bd5c5 100644 --- a/app/cli/cmd/root.go +++ b/app/cli/cmd/root.go @@ -107,7 +107,10 @@ func NewRootCmd(l zerolog.Logger) *cobra.Command { rootCmd.PersistentFlags().BoolVar(&flagDebug, "debug", false, "Enable debug/verbose logging mode") rootCmd.PersistentFlags().StringVarP(&flagOutputFormat, "output", "o", "table", "Output format, valid options are json and table") - rootCmd.AddCommand(newWorkflowCmd(), newAuthCmd(), NewVersionCmd(), newAttestationCmd(), newArtifactCmd(), newConfigCmd(), newIntegrationCmd(), newOrganizationCmd()) + rootCmd.AddCommand(newWorkflowCmd(), newAuthCmd(), NewVersionCmd(), + newAttestationCmd(), newArtifactCmd(), newConfigCmd(), + newIntegrationCmd(), newOrganizationCmd(), newCASBackendCmd(), + ) return rootCmd } diff --git a/app/cli/internal/action/casbackend_list.go b/app/cli/internal/action/casbackend_list.go new file mode 100644 index 000000000..a16f801b8 --- /dev/null +++ b/app/cli/internal/action/casbackend_list.go @@ -0,0 +1,89 @@ +// +// Copyright 2023 The Chainloop 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 action + +import ( + "context" + "time" + + pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" +) + +type CASBackendList struct { + cfg *ActionsOpts +} + +type CASBackendItem struct { + ID string `json:"id"` + Name string `json:"name"` + Provider string `json:"provider"` + Default bool `json:"default"` + ValidationStatus ValidationStatus `json:"validationStatus"` + + CreatedAt *time.Time `json:"createdAt"` + ValidatedAt *time.Time `json:"validatedAt"` +} + +type ValidationStatus string + +const ( + Valid ValidationStatus = "valid" + Invalid ValidationStatus = "invalid" +) + +func NewCASBackendList(cfg *ActionsOpts) *CASBackendList { + return &CASBackendList{cfg} +} + +func (action *CASBackendList) Run() ([]*CASBackendItem, error) { + client := pb.NewCASBackendServiceClient(action.cfg.CPConnection) + resp, err := client.List(context.Background(), &pb.CASBackendServiceListRequest{}) + if err != nil { + return nil, err + } + + result := make([]*CASBackendItem, 0, len(resp.Result)) + for _, p := range resp.Result { + result = append(result, pbCASBackendItemToAction(p)) + } + + return result, nil +} + +func pbCASBackendItemToAction(in *pb.CASBackendItem) *CASBackendItem { + if in == nil { + return nil + } + + b := &CASBackendItem{ + ID: in.Id, + Name: in.Name, + Provider: in.Provider, + Default: in.Default, + CreatedAt: toTimePtr(in.CreatedAt.AsTime()), + ValidatedAt: toTimePtr(in.ValidatedAt.AsTime()), + } + + switch in.GetValidationStatus() { + case pb.CASBackendItem_VALIDATION_STATUS_OK: + b.ValidationStatus = Valid + case pb.CASBackendItem_VALIDATION_STATUS_INVALID: + b.ValidationStatus = Invalid + } + + return b + +} diff --git a/app/cli/internal/action/config_current_context.go b/app/cli/internal/action/config_current_context.go index 2972fcaa0..8ab9dea53 100644 --- a/app/cli/internal/action/config_current_context.go +++ b/app/cli/internal/action/config_current_context.go @@ -47,13 +47,6 @@ type ConfigContextItemOCIRepo struct { ValidationStatus ValidationStatus } -type ValidationStatus string - -const ( - Valid ValidationStatus = "valid" - Invalid ValidationStatus = "invalid" -) - func (action *ConfigCurrentContext) Run() (*ConfigContextItem, error) { client := pb.NewContextServiceClient(action.cfg.CPConnection) resp, err := client.Current(context.Background(), &pb.ContextServiceCurrentRequest{}) diff --git a/app/controlplane/api/controlplane/v1/cas_backends.pb.go b/app/controlplane/api/controlplane/v1/cas_backends.pb.go new file mode 100644 index 000000000..2f5258ce6 --- /dev/null +++ b/app/controlplane/api/controlplane/v1/cas_backends.pb.go @@ -0,0 +1,234 @@ +// +// Copyright 2023 The Chainloop 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: controlplane/v1/cas_backends.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CASBackendServiceListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CASBackendServiceListRequest) Reset() { + *x = CASBackendServiceListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_cas_backends_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CASBackendServiceListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CASBackendServiceListRequest) ProtoMessage() {} + +func (x *CASBackendServiceListRequest) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_cas_backends_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CASBackendServiceListRequest.ProtoReflect.Descriptor instead. +func (*CASBackendServiceListRequest) Descriptor() ([]byte, []int) { + return file_controlplane_v1_cas_backends_proto_rawDescGZIP(), []int{0} +} + +type CASBackendServiceListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result []*CASBackendItem `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` +} + +func (x *CASBackendServiceListResponse) Reset() { + *x = CASBackendServiceListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_cas_backends_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CASBackendServiceListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CASBackendServiceListResponse) ProtoMessage() {} + +func (x *CASBackendServiceListResponse) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_cas_backends_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CASBackendServiceListResponse.ProtoReflect.Descriptor instead. +func (*CASBackendServiceListResponse) Descriptor() ([]byte, []int) { + return file_controlplane_v1_cas_backends_proto_rawDescGZIP(), []int{1} +} + +func (x *CASBackendServiceListResponse) GetResult() []*CASBackendItem { + if x != nil { + return x.Result + } + return nil +} + +var File_controlplane_v1_cas_backends_proto protoreflect.FileDescriptor + +var file_controlplane_v1_cas_backends_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, + 0x31, 0x2f, 0x63, 0x61, 0x73, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x27, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1e, + 0x0a, 0x1c, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x58, + 0x0a, 0x1d, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x37, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x7a, 0x0a, 0x11, 0x43, 0x41, 0x53, 0x42, + 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x65, 0x0a, + 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, + 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, + 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_controlplane_v1_cas_backends_proto_rawDescOnce sync.Once + file_controlplane_v1_cas_backends_proto_rawDescData = file_controlplane_v1_cas_backends_proto_rawDesc +) + +func file_controlplane_v1_cas_backends_proto_rawDescGZIP() []byte { + file_controlplane_v1_cas_backends_proto_rawDescOnce.Do(func() { + file_controlplane_v1_cas_backends_proto_rawDescData = protoimpl.X.CompressGZIP(file_controlplane_v1_cas_backends_proto_rawDescData) + }) + return file_controlplane_v1_cas_backends_proto_rawDescData +} + +var file_controlplane_v1_cas_backends_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_controlplane_v1_cas_backends_proto_goTypes = []interface{}{ + (*CASBackendServiceListRequest)(nil), // 0: controlplane.v1.CASBackendServiceListRequest + (*CASBackendServiceListResponse)(nil), // 1: controlplane.v1.CASBackendServiceListResponse + (*CASBackendItem)(nil), // 2: controlplane.v1.CASBackendItem +} +var file_controlplane_v1_cas_backends_proto_depIdxs = []int32{ + 2, // 0: controlplane.v1.CASBackendServiceListResponse.result:type_name -> controlplane.v1.CASBackendItem + 0, // 1: controlplane.v1.CASBackendService.List:input_type -> controlplane.v1.CASBackendServiceListRequest + 1, // 2: controlplane.v1.CASBackendService.List:output_type -> controlplane.v1.CASBackendServiceListResponse + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_controlplane_v1_cas_backends_proto_init() } +func file_controlplane_v1_cas_backends_proto_init() { + if File_controlplane_v1_cas_backends_proto != nil { + return + } + file_controlplane_v1_response_messages_proto_init() + if !protoimpl.UnsafeEnabled { + file_controlplane_v1_cas_backends_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CASBackendServiceListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controlplane_v1_cas_backends_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CASBackendServiceListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_controlplane_v1_cas_backends_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_controlplane_v1_cas_backends_proto_goTypes, + DependencyIndexes: file_controlplane_v1_cas_backends_proto_depIdxs, + MessageInfos: file_controlplane_v1_cas_backends_proto_msgTypes, + }.Build() + File_controlplane_v1_cas_backends_proto = out.File + file_controlplane_v1_cas_backends_proto_rawDesc = nil + file_controlplane_v1_cas_backends_proto_goTypes = nil + file_controlplane_v1_cas_backends_proto_depIdxs = nil +} diff --git a/app/controlplane/api/controlplane/v1/cas_backends.pb.validate.go b/app/controlplane/api/controlplane/v1/cas_backends.pb.validate.go new file mode 100644 index 000000000..5146d4455 --- /dev/null +++ b/app/controlplane/api/controlplane/v1/cas_backends.pb.validate.go @@ -0,0 +1,276 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: controlplane/v1/cas_backends.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on CASBackendServiceListRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *CASBackendServiceListRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on CASBackendServiceListRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// CASBackendServiceListRequestMultiError, or nil if none found. +func (m *CASBackendServiceListRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *CASBackendServiceListRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return CASBackendServiceListRequestMultiError(errors) + } + + return nil +} + +// CASBackendServiceListRequestMultiError is an error wrapping multiple +// validation errors returned by CASBackendServiceListRequest.ValidateAll() if +// the designated constraints aren't met. +type CASBackendServiceListRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m CASBackendServiceListRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m CASBackendServiceListRequestMultiError) AllErrors() []error { return m } + +// CASBackendServiceListRequestValidationError is the validation error returned +// by CASBackendServiceListRequest.Validate if the designated constraints +// aren't met. +type CASBackendServiceListRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e CASBackendServiceListRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e CASBackendServiceListRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e CASBackendServiceListRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e CASBackendServiceListRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e CASBackendServiceListRequestValidationError) ErrorName() string { + return "CASBackendServiceListRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e CASBackendServiceListRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCASBackendServiceListRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = CASBackendServiceListRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = CASBackendServiceListRequestValidationError{} + +// Validate checks the field values on CASBackendServiceListResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *CASBackendServiceListResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on CASBackendServiceListResponse with +// the rules defined in the proto definition for this message. If any rules +// are violated, the result is a list of violation errors wrapped in +// CASBackendServiceListResponseMultiError, or nil if none found. +func (m *CASBackendServiceListResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *CASBackendServiceListResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetResult() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, CASBackendServiceListResponseValidationError{ + field: fmt.Sprintf("Result[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, CASBackendServiceListResponseValidationError{ + field: fmt.Sprintf("Result[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CASBackendServiceListResponseValidationError{ + field: fmt.Sprintf("Result[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return CASBackendServiceListResponseMultiError(errors) + } + + return nil +} + +// CASBackendServiceListResponseMultiError is an error wrapping multiple +// validation errors returned by CASBackendServiceListResponse.ValidateAll() +// if the designated constraints aren't met. +type CASBackendServiceListResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m CASBackendServiceListResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m CASBackendServiceListResponseMultiError) AllErrors() []error { return m } + +// CASBackendServiceListResponseValidationError is the validation error +// returned by CASBackendServiceListResponse.Validate if the designated +// constraints aren't met. +type CASBackendServiceListResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e CASBackendServiceListResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e CASBackendServiceListResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e CASBackendServiceListResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e CASBackendServiceListResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e CASBackendServiceListResponseValidationError) ErrorName() string { + return "CASBackendServiceListResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e CASBackendServiceListResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCASBackendServiceListResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = CASBackendServiceListResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = CASBackendServiceListResponseValidationError{} diff --git a/app/controlplane/api/controlplane/v1/cas_backends.proto b/app/controlplane/api/controlplane/v1/cas_backends.proto new file mode 100644 index 000000000..957fac516 --- /dev/null +++ b/app/controlplane/api/controlplane/v1/cas_backends.proto @@ -0,0 +1,32 @@ +// +// Copyright 2023 The Chainloop 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. + +syntax = "proto3"; + +package controlplane.v1; + +option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1"; + +import "controlplane/v1/response_messages.proto"; + +service CASBackendService { + rpc List (CASBackendServiceListRequest) returns (CASBackendServiceListResponse); +} + +message CASBackendServiceListRequest {} + +message CASBackendServiceListResponse { + repeated CASBackendItem result = 1; +} \ No newline at end of file diff --git a/app/controlplane/api/controlplane/v1/cas_backends_grpc.pb.go b/app/controlplane/api/controlplane/v1/cas_backends_grpc.pb.go new file mode 100644 index 000000000..9dcda5a72 --- /dev/null +++ b/app/controlplane/api/controlplane/v1/cas_backends_grpc.pb.go @@ -0,0 +1,124 @@ +// +// Copyright 2023 The Chainloop 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. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: controlplane/v1/cas_backends.proto + +package v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + CASBackendService_List_FullMethodName = "/controlplane.v1.CASBackendService/List" +) + +// CASBackendServiceClient is the client API for CASBackendService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type CASBackendServiceClient interface { + List(ctx context.Context, in *CASBackendServiceListRequest, opts ...grpc.CallOption) (*CASBackendServiceListResponse, error) +} + +type cASBackendServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewCASBackendServiceClient(cc grpc.ClientConnInterface) CASBackendServiceClient { + return &cASBackendServiceClient{cc} +} + +func (c *cASBackendServiceClient) List(ctx context.Context, in *CASBackendServiceListRequest, opts ...grpc.CallOption) (*CASBackendServiceListResponse, error) { + out := new(CASBackendServiceListResponse) + err := c.cc.Invoke(ctx, CASBackendService_List_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CASBackendServiceServer is the server API for CASBackendService service. +// All implementations must embed UnimplementedCASBackendServiceServer +// for forward compatibility +type CASBackendServiceServer interface { + List(context.Context, *CASBackendServiceListRequest) (*CASBackendServiceListResponse, error) + mustEmbedUnimplementedCASBackendServiceServer() +} + +// UnimplementedCASBackendServiceServer must be embedded to have forward compatible implementations. +type UnimplementedCASBackendServiceServer struct { +} + +func (UnimplementedCASBackendServiceServer) List(context.Context, *CASBackendServiceListRequest) (*CASBackendServiceListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method List not implemented") +} +func (UnimplementedCASBackendServiceServer) mustEmbedUnimplementedCASBackendServiceServer() {} + +// UnsafeCASBackendServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CASBackendServiceServer will +// result in compilation errors. +type UnsafeCASBackendServiceServer interface { + mustEmbedUnimplementedCASBackendServiceServer() +} + +func RegisterCASBackendServiceServer(s grpc.ServiceRegistrar, srv CASBackendServiceServer) { + s.RegisterService(&CASBackendService_ServiceDesc, srv) +} + +func _CASBackendService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CASBackendServiceListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CASBackendServiceServer).List(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CASBackendService_List_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CASBackendServiceServer).List(ctx, req.(*CASBackendServiceListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// CASBackendService_ServiceDesc is the grpc.ServiceDesc for CASBackendService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var CASBackendService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "controlplane.v1.CASBackendService", + HandlerType: (*CASBackendServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "List", + Handler: _CASBackendService_List_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "controlplane/v1/cas_backends.proto", +} diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.go b/app/controlplane/api/controlplane/v1/response_messages.pb.go index 7c06cfd66..cb9dbadd1 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.go @@ -133,6 +133,55 @@ func (OCIRepositoryItem_ValidationStatus) EnumDescriptor() ([]byte, []int) { return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{8, 0} } +type CASBackendItem_ValidationStatus int32 + +const ( + CASBackendItem_VALIDATION_STATUS_UNSPECIFIED CASBackendItem_ValidationStatus = 0 + CASBackendItem_VALIDATION_STATUS_OK CASBackendItem_ValidationStatus = 1 + CASBackendItem_VALIDATION_STATUS_INVALID CASBackendItem_ValidationStatus = 2 +) + +// Enum value maps for CASBackendItem_ValidationStatus. +var ( + CASBackendItem_ValidationStatus_name = map[int32]string{ + 0: "VALIDATION_STATUS_UNSPECIFIED", + 1: "VALIDATION_STATUS_OK", + 2: "VALIDATION_STATUS_INVALID", + } + CASBackendItem_ValidationStatus_value = map[string]int32{ + "VALIDATION_STATUS_UNSPECIFIED": 0, + "VALIDATION_STATUS_OK": 1, + "VALIDATION_STATUS_INVALID": 2, + } +) + +func (x CASBackendItem_ValidationStatus) Enum() *CASBackendItem_ValidationStatus { + p := new(CASBackendItem_ValidationStatus) + *p = x + return p +} + +func (x CASBackendItem_ValidationStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CASBackendItem_ValidationStatus) Descriptor() protoreflect.EnumDescriptor { + return file_controlplane_v1_response_messages_proto_enumTypes[2].Descriptor() +} + +func (CASBackendItem_ValidationStatus) Type() protoreflect.EnumType { + return &file_controlplane_v1_response_messages_proto_enumTypes[2] +} + +func (x CASBackendItem_ValidationStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CASBackendItem_ValidationStatus.Descriptor instead. +func (CASBackendItem_ValidationStatus) EnumDescriptor() ([]byte, []int) { + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{9, 0} +} + type WorkflowItem struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -805,6 +854,7 @@ func (x *Org) GetCreatedAt() *timestamppb.Timestamp { return nil } +// Deprecated: Marked as deprecated in controlplane/v1/response_messages.proto. type OCIRepositoryItem struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -876,6 +926,103 @@ func (x *OCIRepositoryItem) GetValidationStatus() OCIRepositoryItem_ValidationSt return OCIRepositoryItem_VALIDATION_STATUS_UNSPECIFIED } +type CASBackendItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + ValidatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=validated_at,json=validatedAt,proto3" json:"validated_at,omitempty"` + ValidationStatus CASBackendItem_ValidationStatus `protobuf:"varint,5,opt,name=validation_status,json=validationStatus,proto3,enum=controlplane.v1.CASBackendItem_ValidationStatus" json:"validation_status,omitempty"` + // OCI, S3, ... + Provider string `protobuf:"bytes,6,opt,name=provider,proto3" json:"provider,omitempty"` + // Wether it's the default backend in the organization + Default bool `protobuf:"varint,7,opt,name=default,proto3" json:"default,omitempty"` +} + +func (x *CASBackendItem) Reset() { + *x = CASBackendItem{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CASBackendItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CASBackendItem) ProtoMessage() {} + +func (x *CASBackendItem) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CASBackendItem.ProtoReflect.Descriptor instead. +func (*CASBackendItem) Descriptor() ([]byte, []int) { + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{9} +} + +func (x *CASBackendItem) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *CASBackendItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CASBackendItem) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *CASBackendItem) GetValidatedAt() *timestamppb.Timestamp { + if x != nil { + return x.ValidatedAt + } + return nil +} + +func (x *CASBackendItem) GetValidationStatus() CASBackendItem_ValidationStatus { + if x != nil { + return x.ValidationStatus + } + return CASBackendItem_VALIDATION_STATUS_UNSPECIFIED +} + +func (x *CASBackendItem) GetProvider() string { + if x != nil { + return x.Provider + } + return "" +} + +func (x *CASBackendItem) GetDefault() bool { + if x != nil { + return x.Default + } + return false +} + type AttestationItem_EnvVariable struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -888,7 +1035,7 @@ type AttestationItem_EnvVariable struct { func (x *AttestationItem_EnvVariable) Reset() { *x = AttestationItem_EnvVariable{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -901,7 +1048,7 @@ func (x *AttestationItem_EnvVariable) String() string { func (*AttestationItem_EnvVariable) ProtoMessage() {} func (x *AttestationItem_EnvVariable) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -945,7 +1092,7 @@ type AttestationItem_Material struct { func (x *AttestationItem_Material) Reset() { *x = AttestationItem_Material{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -958,7 +1105,7 @@ func (x *AttestationItem_Material) String() string { func (*AttestationItem_Material) ProtoMessage() {} func (x *AttestationItem_Material) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1131,7 +1278,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x22, 0xc4, 0x02, 0x0a, 0x11, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x64, 0x41, 0x74, 0x22, 0xc8, 0x02, 0x0a, 0x11, 0x4f, 0x43, 0x49, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x39, 0x0a, @@ -1151,19 +1298,46 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, - 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, - 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, - 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, - 0x1a, 0x04, 0xb0, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa8, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, - 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xb3, + 0x03, 0x0a, 0x0e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, + 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x3d, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x5d, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, + 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x22, 0x6e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x41, 0x4c, 0x49, + 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, + 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, + 0x49, 0x44, 0x10, 0x02, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, + 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, + 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, + 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, + 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xb0, 0x45, 0x93, 0x03, + 0x1a, 0x04, 0xa8, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, + 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, + 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1178,52 +1352,57 @@ func file_controlplane_v1_response_messages_proto_rawDescGZIP() []byte { return file_controlplane_v1_response_messages_proto_rawDescData } -var file_controlplane_v1_response_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_controlplane_v1_response_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_controlplane_v1_response_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_controlplane_v1_response_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_controlplane_v1_response_messages_proto_goTypes = []interface{}{ (AllowListError)(0), // 0: controlplane.v1.AllowListError (OCIRepositoryItem_ValidationStatus)(0), // 1: controlplane.v1.OCIRepositoryItem.ValidationStatus - (*WorkflowItem)(nil), // 2: controlplane.v1.WorkflowItem - (*WorkflowRunItem)(nil), // 3: controlplane.v1.WorkflowRunItem - (*AttestationItem)(nil), // 4: controlplane.v1.AttestationItem - (*WorkflowContractItem)(nil), // 5: controlplane.v1.WorkflowContractItem - (*WorkflowContractVersionItem)(nil), // 6: controlplane.v1.WorkflowContractVersionItem - (*User)(nil), // 7: controlplane.v1.User - (*OrgMembershipItem)(nil), // 8: controlplane.v1.OrgMembershipItem - (*Org)(nil), // 9: controlplane.v1.Org - (*OCIRepositoryItem)(nil), // 10: controlplane.v1.OCIRepositoryItem - (*AttestationItem_EnvVariable)(nil), // 11: controlplane.v1.AttestationItem.EnvVariable - (*AttestationItem_Material)(nil), // 12: controlplane.v1.AttestationItem.Material - (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp - (v1.CraftingSchema_Runner_RunnerType)(0), // 14: workflowcontract.v1.CraftingSchema.Runner.RunnerType - (*v1.CraftingSchema)(nil), // 15: workflowcontract.v1.CraftingSchema + (CASBackendItem_ValidationStatus)(0), // 2: controlplane.v1.CASBackendItem.ValidationStatus + (*WorkflowItem)(nil), // 3: controlplane.v1.WorkflowItem + (*WorkflowRunItem)(nil), // 4: controlplane.v1.WorkflowRunItem + (*AttestationItem)(nil), // 5: controlplane.v1.AttestationItem + (*WorkflowContractItem)(nil), // 6: controlplane.v1.WorkflowContractItem + (*WorkflowContractVersionItem)(nil), // 7: controlplane.v1.WorkflowContractVersionItem + (*User)(nil), // 8: controlplane.v1.User + (*OrgMembershipItem)(nil), // 9: controlplane.v1.OrgMembershipItem + (*Org)(nil), // 10: controlplane.v1.Org + (*OCIRepositoryItem)(nil), // 11: controlplane.v1.OCIRepositoryItem + (*CASBackendItem)(nil), // 12: controlplane.v1.CASBackendItem + (*AttestationItem_EnvVariable)(nil), // 13: controlplane.v1.AttestationItem.EnvVariable + (*AttestationItem_Material)(nil), // 14: controlplane.v1.AttestationItem.Material + (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp + (v1.CraftingSchema_Runner_RunnerType)(0), // 16: workflowcontract.v1.CraftingSchema.Runner.RunnerType + (*v1.CraftingSchema)(nil), // 17: workflowcontract.v1.CraftingSchema } var file_controlplane_v1_response_messages_proto_depIdxs = []int32{ - 13, // 0: controlplane.v1.WorkflowItem.created_at:type_name -> google.protobuf.Timestamp - 3, // 1: controlplane.v1.WorkflowItem.last_run:type_name -> controlplane.v1.WorkflowRunItem - 13, // 2: controlplane.v1.WorkflowRunItem.created_at:type_name -> google.protobuf.Timestamp - 13, // 3: controlplane.v1.WorkflowRunItem.finished_at:type_name -> google.protobuf.Timestamp - 2, // 4: controlplane.v1.WorkflowRunItem.workflow:type_name -> controlplane.v1.WorkflowItem - 14, // 5: controlplane.v1.WorkflowRunItem.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 6, // 6: controlplane.v1.WorkflowRunItem.contract_version:type_name -> controlplane.v1.WorkflowContractVersionItem - 13, // 7: controlplane.v1.AttestationItem.created_at:type_name -> google.protobuf.Timestamp - 11, // 8: controlplane.v1.AttestationItem.env_vars:type_name -> controlplane.v1.AttestationItem.EnvVariable - 12, // 9: controlplane.v1.AttestationItem.materials:type_name -> controlplane.v1.AttestationItem.Material - 13, // 10: controlplane.v1.WorkflowContractItem.created_at:type_name -> google.protobuf.Timestamp - 13, // 11: controlplane.v1.WorkflowContractVersionItem.created_at:type_name -> google.protobuf.Timestamp - 15, // 12: controlplane.v1.WorkflowContractVersionItem.v1:type_name -> workflowcontract.v1.CraftingSchema - 13, // 13: controlplane.v1.User.created_at:type_name -> google.protobuf.Timestamp - 9, // 14: controlplane.v1.OrgMembershipItem.org:type_name -> controlplane.v1.Org - 13, // 15: controlplane.v1.OrgMembershipItem.created_at:type_name -> google.protobuf.Timestamp - 13, // 16: controlplane.v1.OrgMembershipItem.updated_at:type_name -> google.protobuf.Timestamp - 13, // 17: controlplane.v1.Org.created_at:type_name -> google.protobuf.Timestamp - 13, // 18: controlplane.v1.OCIRepositoryItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 0: controlplane.v1.WorkflowItem.created_at:type_name -> google.protobuf.Timestamp + 4, // 1: controlplane.v1.WorkflowItem.last_run:type_name -> controlplane.v1.WorkflowRunItem + 15, // 2: controlplane.v1.WorkflowRunItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 3: controlplane.v1.WorkflowRunItem.finished_at:type_name -> google.protobuf.Timestamp + 3, // 4: controlplane.v1.WorkflowRunItem.workflow:type_name -> controlplane.v1.WorkflowItem + 16, // 5: controlplane.v1.WorkflowRunItem.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 7, // 6: controlplane.v1.WorkflowRunItem.contract_version:type_name -> controlplane.v1.WorkflowContractVersionItem + 15, // 7: controlplane.v1.AttestationItem.created_at:type_name -> google.protobuf.Timestamp + 13, // 8: controlplane.v1.AttestationItem.env_vars:type_name -> controlplane.v1.AttestationItem.EnvVariable + 14, // 9: controlplane.v1.AttestationItem.materials:type_name -> controlplane.v1.AttestationItem.Material + 15, // 10: controlplane.v1.WorkflowContractItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 11: controlplane.v1.WorkflowContractVersionItem.created_at:type_name -> google.protobuf.Timestamp + 17, // 12: controlplane.v1.WorkflowContractVersionItem.v1:type_name -> workflowcontract.v1.CraftingSchema + 15, // 13: controlplane.v1.User.created_at:type_name -> google.protobuf.Timestamp + 10, // 14: controlplane.v1.OrgMembershipItem.org:type_name -> controlplane.v1.Org + 15, // 15: controlplane.v1.OrgMembershipItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 16: controlplane.v1.OrgMembershipItem.updated_at:type_name -> google.protobuf.Timestamp + 15, // 17: controlplane.v1.Org.created_at:type_name -> google.protobuf.Timestamp + 15, // 18: controlplane.v1.OCIRepositoryItem.created_at:type_name -> google.protobuf.Timestamp 1, // 19: controlplane.v1.OCIRepositoryItem.validation_status:type_name -> controlplane.v1.OCIRepositoryItem.ValidationStatus - 20, // [20:20] is the sub-list for method output_type - 20, // [20:20] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name + 15, // 20: controlplane.v1.CASBackendItem.created_at:type_name -> google.protobuf.Timestamp + 15, // 21: controlplane.v1.CASBackendItem.validated_at:type_name -> google.protobuf.Timestamp + 2, // 22: controlplane.v1.CASBackendItem.validation_status:type_name -> controlplane.v1.CASBackendItem.ValidationStatus + 23, // [23:23] is the sub-list for method output_type + 23, // [23:23] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name } func init() { file_controlplane_v1_response_messages_proto_init() } @@ -1341,7 +1520,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttestationItem_EnvVariable); i { + switch v := v.(*CASBackendItem); i { case 0: return &v.state case 1: @@ -1353,6 +1532,18 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AttestationItem_EnvVariable); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controlplane_v1_response_messages_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationItem_Material); i { case 0: return &v.state @@ -1373,8 +1564,8 @@ func file_controlplane_v1_response_messages_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controlplane_v1_response_messages_proto_rawDesc, - NumEnums: 2, - NumMessages: 11, + NumEnums: 3, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go b/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go index 04143e852..f4574c3da 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.validate.go @@ -1546,6 +1546,174 @@ var _ interface { ErrorName() string } = OCIRepositoryItemValidationError{} +// Validate checks the field values on CASBackendItem with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *CASBackendItem) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on CASBackendItem with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in CASBackendItemMultiError, +// or nil if none found. +func (m *CASBackendItem) ValidateAll() error { + return m.validate(true) +} + +func (m *CASBackendItem) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Name + + if all { + switch v := interface{}(m.GetCreatedAt()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, CASBackendItemValidationError{ + field: "CreatedAt", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, CASBackendItemValidationError{ + field: "CreatedAt", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetCreatedAt()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CASBackendItemValidationError{ + field: "CreatedAt", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetValidatedAt()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, CASBackendItemValidationError{ + field: "ValidatedAt", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, CASBackendItemValidationError{ + field: "ValidatedAt", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetValidatedAt()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CASBackendItemValidationError{ + field: "ValidatedAt", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for ValidationStatus + + // no validation rules for Provider + + // no validation rules for Default + + if len(errors) > 0 { + return CASBackendItemMultiError(errors) + } + + return nil +} + +// CASBackendItemMultiError is an error wrapping multiple validation errors +// returned by CASBackendItem.ValidateAll() if the designated constraints +// aren't met. +type CASBackendItemMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m CASBackendItemMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m CASBackendItemMultiError) AllErrors() []error { return m } + +// CASBackendItemValidationError is the validation error returned by +// CASBackendItem.Validate if the designated constraints aren't met. +type CASBackendItemValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e CASBackendItemValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e CASBackendItemValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e CASBackendItemValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e CASBackendItemValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e CASBackendItemValidationError) ErrorName() string { return "CASBackendItemValidationError" } + +// Error satisfies the builtin error interface +func (e CASBackendItemValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCASBackendItem.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = CASBackendItemValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = CASBackendItemValidationError{} + // Validate checks the field values on AttestationItem_EnvVariable with the // rules defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. diff --git a/app/controlplane/api/controlplane/v1/response_messages.proto b/app/controlplane/api/controlplane/v1/response_messages.proto index 398937a08..1dd537f71 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.proto +++ b/app/controlplane/api/controlplane/v1/response_messages.proto @@ -110,6 +110,8 @@ message Org { } message OCIRepositoryItem { + option deprecated = true; // in favor of CASBackendItem + string id = 1; string repo = 2; google.protobuf.Timestamp created_at = 3; @@ -122,6 +124,24 @@ message OCIRepositoryItem { } } +message CASBackendItem { + string id = 1; + string name = 2; + google.protobuf.Timestamp created_at = 3; + google.protobuf.Timestamp validated_at = 4; + ValidationStatus validation_status = 5; + // OCI, S3, ... + string provider = 6; + // Wether it's the default backend in the organization + bool default = 7; + + enum ValidationStatus { + VALIDATION_STATUS_UNSPECIFIED = 0; + VALIDATION_STATUS_OK = 1; + VALIDATION_STATUS_INVALID = 2; + } +} + enum AllowListError { option (errors.v1.default_code) = 500; ALLOW_LIST_ERROR_UNSPECIFIED = 0; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/cas_backends.ts b/app/controlplane/api/gen/frontend/controlplane/v1/cas_backends.ts new file mode 100644 index 000000000..eaaf777e3 --- /dev/null +++ b/app/controlplane/api/gen/frontend/controlplane/v1/cas_backends.ts @@ -0,0 +1,272 @@ +/* eslint-disable */ +import { grpc } from "@improbable-eng/grpc-web"; +import { BrowserHeaders } from "browser-headers"; +import _m0 from "protobufjs/minimal"; +import { CASBackendItem } from "./response_messages"; + +export const protobufPackage = "controlplane.v1"; + +export interface CASBackendServiceListRequest { +} + +export interface CASBackendServiceListResponse { + result: CASBackendItem[]; +} + +function createBaseCASBackendServiceListRequest(): CASBackendServiceListRequest { + return {}; +} + +export const CASBackendServiceListRequest = { + encode(_: CASBackendServiceListRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): CASBackendServiceListRequest { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseCASBackendServiceListRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(_: any): CASBackendServiceListRequest { + return {}; + }, + + toJSON(_: CASBackendServiceListRequest): unknown { + const obj: any = {}; + return obj; + }, + + create, I>>(base?: I): CASBackendServiceListRequest { + return CASBackendServiceListRequest.fromPartial(base ?? {}); + }, + + fromPartial, I>>(_: I): CASBackendServiceListRequest { + const message = createBaseCASBackendServiceListRequest(); + return message; + }, +}; + +function createBaseCASBackendServiceListResponse(): CASBackendServiceListResponse { + return { result: [] }; +} + +export const CASBackendServiceListResponse = { + encode(message: CASBackendServiceListResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.result) { + CASBackendItem.encode(v!, writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): CASBackendServiceListResponse { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseCASBackendServiceListResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.result.push(CASBackendItem.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): CASBackendServiceListResponse { + return { result: Array.isArray(object?.result) ? object.result.map((e: any) => CASBackendItem.fromJSON(e)) : [] }; + }, + + toJSON(message: CASBackendServiceListResponse): unknown { + const obj: any = {}; + if (message.result) { + obj.result = message.result.map((e) => e ? CASBackendItem.toJSON(e) : undefined); + } else { + obj.result = []; + } + return obj; + }, + + create, I>>(base?: I): CASBackendServiceListResponse { + return CASBackendServiceListResponse.fromPartial(base ?? {}); + }, + + fromPartial, I>>( + object: I, + ): CASBackendServiceListResponse { + const message = createBaseCASBackendServiceListResponse(); + message.result = object.result?.map((e) => CASBackendItem.fromPartial(e)) || []; + return message; + }, +}; + +export interface CASBackendService { + List( + request: DeepPartial, + metadata?: grpc.Metadata, + ): Promise; +} + +export class CASBackendServiceClientImpl implements CASBackendService { + private readonly rpc: Rpc; + + constructor(rpc: Rpc) { + this.rpc = rpc; + this.List = this.List.bind(this); + } + + List( + request: DeepPartial, + metadata?: grpc.Metadata, + ): Promise { + return this.rpc.unary(CASBackendServiceListDesc, CASBackendServiceListRequest.fromPartial(request), metadata); + } +} + +export const CASBackendServiceDesc = { serviceName: "controlplane.v1.CASBackendService" }; + +export const CASBackendServiceListDesc: UnaryMethodDefinitionish = { + methodName: "List", + service: CASBackendServiceDesc, + requestStream: false, + responseStream: false, + requestType: { + serializeBinary() { + return CASBackendServiceListRequest.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + const value = CASBackendServiceListResponse.decode(data); + return { + ...value, + toObject() { + return value; + }, + }; + }, + } as any, +}; + +interface UnaryMethodDefinitionishR extends grpc.UnaryMethodDefinition { + requestStream: any; + responseStream: any; +} + +type UnaryMethodDefinitionish = UnaryMethodDefinitionishR; + +interface Rpc { + unary( + methodDesc: T, + request: any, + metadata: grpc.Metadata | undefined, + ): Promise; +} + +export class GrpcWebImpl { + private host: string; + private options: { + transport?: grpc.TransportFactory; + + debug?: boolean; + metadata?: grpc.Metadata; + upStreamRetryCodes?: number[]; + }; + + constructor( + host: string, + options: { + transport?: grpc.TransportFactory; + + debug?: boolean; + metadata?: grpc.Metadata; + upStreamRetryCodes?: number[]; + }, + ) { + this.host = host; + this.options = options; + } + + unary( + methodDesc: T, + _request: any, + metadata: grpc.Metadata | undefined, + ): Promise { + const request = { ..._request, ...methodDesc.requestType }; + const maybeCombinedMetadata = metadata && this.options.metadata + ? new BrowserHeaders({ ...this.options?.metadata.headersMap, ...metadata?.headersMap }) + : metadata || this.options.metadata; + return new Promise((resolve, reject) => { + grpc.unary(methodDesc, { + request, + host: this.host, + metadata: maybeCombinedMetadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (response.status === grpc.Code.OK) { + resolve(response.message!.toObject()); + } else { + const err = new GrpcWebError(response.statusMessage, response.status, response.trailers); + reject(err); + } + }, + }); + }); + } +} + +declare var self: any | undefined; +declare var window: any | undefined; +declare var global: any | undefined; +var tsProtoGlobalThis: any = (() => { + if (typeof globalThis !== "undefined") { + return globalThis; + } + if (typeof self !== "undefined") { + return self; + } + if (typeof window !== "undefined") { + return window; + } + if (typeof global !== "undefined") { + return global; + } + throw "Unable to locate global object"; +})(); + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +export class GrpcWebError extends tsProtoGlobalThis.Error { + constructor(message: string, public code: grpc.Code, public metadata: grpc.Metadata) { + super(message); + } +} diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts index acc7ee42c..f87da0170 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts @@ -125,6 +125,7 @@ export interface Org { createdAt?: Date; } +/** @deprecated */ export interface OCIRepositoryItem { id: string; repo: string; @@ -171,6 +172,57 @@ export function oCIRepositoryItem_ValidationStatusToJSON(object: OCIRepositoryIt } } +export interface CASBackendItem { + id: string; + name: string; + createdAt?: Date; + validatedAt?: Date; + validationStatus: CASBackendItem_ValidationStatus; + /** OCI, S3, ... */ + provider: string; + /** Wether it's the default backend in the organization */ + default: boolean; +} + +export enum CASBackendItem_ValidationStatus { + VALIDATION_STATUS_UNSPECIFIED = 0, + VALIDATION_STATUS_OK = 1, + VALIDATION_STATUS_INVALID = 2, + UNRECOGNIZED = -1, +} + +export function cASBackendItem_ValidationStatusFromJSON(object: any): CASBackendItem_ValidationStatus { + switch (object) { + case 0: + case "VALIDATION_STATUS_UNSPECIFIED": + return CASBackendItem_ValidationStatus.VALIDATION_STATUS_UNSPECIFIED; + case 1: + case "VALIDATION_STATUS_OK": + return CASBackendItem_ValidationStatus.VALIDATION_STATUS_OK; + case 2: + case "VALIDATION_STATUS_INVALID": + return CASBackendItem_ValidationStatus.VALIDATION_STATUS_INVALID; + case -1: + case "UNRECOGNIZED": + default: + return CASBackendItem_ValidationStatus.UNRECOGNIZED; + } +} + +export function cASBackendItem_ValidationStatusToJSON(object: CASBackendItem_ValidationStatus): string { + switch (object) { + case CASBackendItem_ValidationStatus.VALIDATION_STATUS_UNSPECIFIED: + return "VALIDATION_STATUS_UNSPECIFIED"; + case CASBackendItem_ValidationStatus.VALIDATION_STATUS_OK: + return "VALIDATION_STATUS_OK"; + case CASBackendItem_ValidationStatus.VALIDATION_STATUS_INVALID: + return "VALIDATION_STATUS_INVALID"; + case CASBackendItem_ValidationStatus.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + function createBaseWorkflowItem(): WorkflowItem { return { id: "", @@ -1380,6 +1432,153 @@ export const OCIRepositoryItem = { }, }; +function createBaseCASBackendItem(): CASBackendItem { + return { + id: "", + name: "", + createdAt: undefined, + validatedAt: undefined, + validationStatus: 0, + provider: "", + default: false, + }; +} + +export const CASBackendItem = { + encode(message: CASBackendItem, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.id !== "") { + writer.uint32(10).string(message.id); + } + if (message.name !== "") { + writer.uint32(18).string(message.name); + } + if (message.createdAt !== undefined) { + Timestamp.encode(toTimestamp(message.createdAt), writer.uint32(26).fork()).ldelim(); + } + if (message.validatedAt !== undefined) { + Timestamp.encode(toTimestamp(message.validatedAt), writer.uint32(34).fork()).ldelim(); + } + if (message.validationStatus !== 0) { + writer.uint32(40).int32(message.validationStatus); + } + if (message.provider !== "") { + writer.uint32(50).string(message.provider); + } + if (message.default === true) { + writer.uint32(56).bool(message.default); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): CASBackendItem { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseCASBackendItem(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.id = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.name = reader.string(); + continue; + case 3: + if (tag !== 26) { + break; + } + + message.createdAt = fromTimestamp(Timestamp.decode(reader, reader.uint32())); + continue; + case 4: + if (tag !== 34) { + break; + } + + message.validatedAt = fromTimestamp(Timestamp.decode(reader, reader.uint32())); + continue; + case 5: + if (tag !== 40) { + break; + } + + message.validationStatus = reader.int32() as any; + continue; + case 6: + if (tag !== 50) { + break; + } + + message.provider = reader.string(); + continue; + case 7: + if (tag !== 56) { + break; + } + + message.default = reader.bool(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): CASBackendItem { + return { + id: isSet(object.id) ? String(object.id) : "", + name: isSet(object.name) ? String(object.name) : "", + createdAt: isSet(object.createdAt) ? fromJsonTimestamp(object.createdAt) : undefined, + validatedAt: isSet(object.validatedAt) ? fromJsonTimestamp(object.validatedAt) : undefined, + validationStatus: isSet(object.validationStatus) + ? cASBackendItem_ValidationStatusFromJSON(object.validationStatus) + : 0, + provider: isSet(object.provider) ? String(object.provider) : "", + default: isSet(object.default) ? Boolean(object.default) : false, + }; + }, + + toJSON(message: CASBackendItem): unknown { + const obj: any = {}; + message.id !== undefined && (obj.id = message.id); + message.name !== undefined && (obj.name = message.name); + message.createdAt !== undefined && (obj.createdAt = message.createdAt.toISOString()); + message.validatedAt !== undefined && (obj.validatedAt = message.validatedAt.toISOString()); + message.validationStatus !== undefined && + (obj.validationStatus = cASBackendItem_ValidationStatusToJSON(message.validationStatus)); + message.provider !== undefined && (obj.provider = message.provider); + message.default !== undefined && (obj.default = message.default); + return obj; + }, + + create, I>>(base?: I): CASBackendItem { + return CASBackendItem.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): CASBackendItem { + const message = createBaseCASBackendItem(); + message.id = object.id ?? ""; + message.name = object.name ?? ""; + message.createdAt = object.createdAt ?? undefined; + message.validatedAt = object.validatedAt ?? undefined; + message.validationStatus = object.validationStatus ?? 0; + message.provider = object.provider ?? ""; + message.default = object.default ?? false; + return message; + }, +}; + declare var self: any | undefined; declare var window: any | undefined; declare var global: any | undefined; diff --git a/app/controlplane/cmd/wire_gen.go b/app/controlplane/cmd/wire_gen.go index 670de1940..7c5222a71 100644 --- a/app/controlplane/cmd/wire_gen.go +++ b/app/controlplane/cmd/wire_gen.go @@ -116,6 +116,7 @@ func wireApp(bootstrap *conf.Bootstrap, readerWriter credentials.ReaderWriter, l ociRepositoryService := service.NewOCIRepositoryService(casBackendUseCase, v2...) integrationsService := service.NewIntegrationsService(integrationUseCase, workflowUseCase, availablePlugins, v2...) organizationService := service.NewOrganizationService(membershipUseCase, v2...) + casBackendService := service.NewCASBackendService(casBackendUseCase, v2...) opts := &server.Opts{ UserUseCase: userUseCase, RobotAccountUseCase: robotAccountUseCase, @@ -134,6 +135,7 @@ func wireApp(bootstrap *conf.Bootstrap, readerWriter credentials.ReaderWriter, l OCIRepositorySvc: ociRepositoryService, IntegrationsSvc: integrationsService, OrganizationSvc: organizationService, + CASBackendSvc: casBackendService, Logger: logger, ServerConfig: confServer, AuthConfig: auth, diff --git a/app/controlplane/internal/biz/casbackend.go b/app/controlplane/internal/biz/casbackend.go index 1279d4436..572a572ed 100644 --- a/app/controlplane/internal/biz/casbackend.go +++ b/app/controlplane/internal/biz/casbackend.go @@ -70,6 +70,7 @@ type CASBackendUpdateOpts struct { type CASBackendRepo interface { FindDefaultBackend(ctx context.Context, orgID uuid.UUID) (*CASBackend, error) FindByID(ctx context.Context, ID uuid.UUID) (*CASBackend, error) + List(ctx context.Context, orgID uuid.UUID) ([]*CASBackend, error) UpdateValidationStatus(ctx context.Context, ID uuid.UUID, status CASBackendValidationStatus) error Create(context.Context, *CASBackendCreateOpts) (*CASBackend, error) Update(context.Context, *CASBackendUpdateOpts) (*CASBackend, error) @@ -97,6 +98,15 @@ func NewCASBackendUseCase(repo CASBackendRepo, credsRW credentials.ReaderWriter, return &CASBackendUseCase{repo, servicelogger.ScopedHelper(l, "biz/CASBackend"), credsRW, p} } +func (uc *CASBackendUseCase) List(ctx context.Context, orgID string) ([]*CASBackend, error) { + orgUUID, err := uuid.Parse(orgID) + if err != nil { + return nil, err + } + + return uc.repo.List(ctx, orgUUID) +} + func (uc *CASBackendUseCase) FindDefaultBackend(ctx context.Context, orgID string) (*CASBackend, error) { orgUUID, err := uuid.Parse(orgID) if err != nil { diff --git a/app/controlplane/internal/data/casbackend.go b/app/controlplane/internal/data/casbackend.go index 34cb9f41b..c9a923eb5 100644 --- a/app/controlplane/internal/data/casbackend.go +++ b/app/controlplane/internal/data/casbackend.go @@ -17,6 +17,7 @@ package data import ( "context" + "fmt" "time" "github.com/chainloop-dev/chainloop/app/controlplane/internal/biz" @@ -38,6 +39,20 @@ func NewCASBackendRepo(data *Data, logger log.Logger) biz.CASBackendRepo { } } +func (r *CASBackendRepo) List(ctx context.Context, orgID uuid.UUID) ([]*biz.CASBackend, error) { + backends, err := orgScopedQuery(r.data.db, orgID).QueryCasBackends().All(ctx) + if err != nil { + return nil, fmt.Errorf("failed to list cas backends: %w", err) + } + + var res []*biz.CASBackend + for _, backend := range backends { + res = append(res, entCASBackendToBiz(backend)) + } + + return res, nil +} + func (r *CASBackendRepo) FindDefaultBackend(ctx context.Context, orgID uuid.UUID) (*biz.CASBackend, error) { backend, err := orgScopedQuery(r.data.db, orgID).QueryCasBackends().Where(casbackend.Default(true)).Only(ctx) if err != nil && !ent.IsNotFound(err) { diff --git a/app/controlplane/internal/server/grpc.go b/app/controlplane/internal/server/grpc.go index 7b9629829..1f97add7f 100644 --- a/app/controlplane/internal/server/grpc.go +++ b/app/controlplane/internal/server/grpc.go @@ -63,6 +63,7 @@ type Opts struct { OCIRepositorySvc *service.OCIRepositoryService IntegrationsSvc *service.IntegrationsService OrganizationSvc *service.OrganizationService + CASBackendSvc *service.CASBackendService // Utils Logger log.Logger ServerConfig *conf.Server @@ -101,6 +102,7 @@ func NewGRPCServer(opts *Opts) *grpc.Server { v1.RegisterIntegrationsServiceServer(srv, opts.IntegrationsSvc) v1.RegisterOrganizationServiceServer(srv, opts.OrganizationSvc) v1.RegisterAuthServiceServer(srv, opts.AuthSvc) + v1.RegisterCASBackendServiceServer(srv, opts.CASBackendSvc) // Register Prometheus metrics grpc_prometheus.Register(srv.Server) diff --git a/app/controlplane/internal/service/casbackend.go b/app/controlplane/internal/service/casbackend.go new file mode 100644 index 000000000..a96bd3181 --- /dev/null +++ b/app/controlplane/internal/service/casbackend.go @@ -0,0 +1,77 @@ +// +// Copyright 2023 The Chainloop 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 service + +import ( + "context" + + pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" + "github.com/chainloop-dev/chainloop/app/controlplane/internal/biz" + sl "github.com/chainloop-dev/chainloop/internal/servicelogger" + "google.golang.org/protobuf/types/known/timestamppb" +) + +type CASBackendService struct { + pb.UnimplementedCASBackendServiceServer + *service + + uc *biz.CASBackendUseCase +} + +func NewCASBackendService(uc *biz.CASBackendUseCase, opts ...NewOpt) *CASBackendService { + return &CASBackendService{ + service: newService(opts...), + uc: uc, + } +} + +func (s *CASBackendService) List(ctx context.Context, _ *pb.CASBackendServiceListRequest) (*pb.CASBackendServiceListResponse, error) { + _, currentOrg, err := loadCurrentUserAndOrg(ctx) + if err != nil { + return nil, err + } + + backends, err := s.uc.List(ctx, currentOrg.ID) + if err != nil { + return nil, sl.LogAndMaskErr(err, s.log) + } + + res := []*pb.CASBackendItem{} + for _, backend := range backends { + res = append(res, bizOCASBackendToPb(backend)) + } + + return &pb.CASBackendServiceListResponse{Result: res}, nil +} + +func bizOCASBackendToPb(repo *biz.CASBackend) *pb.CASBackendItem { + r := &pb.CASBackendItem{ + Id: repo.ID.String(), Name: repo.Name, + CreatedAt: timestamppb.New(*repo.CreatedAt), + ValidatedAt: timestamppb.New(*repo.ValidatedAt), + Provider: string(repo.Provider), + Default: repo.Default, + } + + switch repo.ValidationStatus { + case biz.CASBackendValidationOK: + r.ValidationStatus = pb.CASBackendItem_VALIDATION_STATUS_OK + case biz.CASBackendValidationFailed: + r.ValidationStatus = pb.CASBackendItem_VALIDATION_STATUS_INVALID + } + + return r +} diff --git a/app/controlplane/internal/service/service.go b/app/controlplane/internal/service/service.go index 2e3bfdcdb..a8cc45270 100644 --- a/app/controlplane/internal/service/service.go +++ b/app/controlplane/internal/service/service.go @@ -39,6 +39,7 @@ var ProviderSet = wire.NewSet( NewContextService, NewOrgMetricsService, NewIntegrationsService, + NewCASBackendService, NewOrganizationService, wire.Struct(new(NewWorkflowRunServiceOpts), "*"), wire.Struct(new(NewAttestationServiceOpts), "*"), From 39300a5b1a5c54300ed9cf5e6a05598130d5df01 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 12 Jul 2023 16:14:00 +0200 Subject: [PATCH 2/4] feat(api): list cas-backends Signed-off-by: Miguel Martinez Trivino --- app/cli/internal/action/casbackend_list.go | 1 - .../internal/biz/mocks/CASBackendRepo.go | 26 +++++++++++++++++++ app/controlplane/internal/data/casbackend.go | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/cli/internal/action/casbackend_list.go b/app/cli/internal/action/casbackend_list.go index a16f801b8..f6d034626 100644 --- a/app/cli/internal/action/casbackend_list.go +++ b/app/cli/internal/action/casbackend_list.go @@ -85,5 +85,4 @@ func pbCASBackendItemToAction(in *pb.CASBackendItem) *CASBackendItem { } return b - } diff --git a/app/controlplane/internal/biz/mocks/CASBackendRepo.go b/app/controlplane/internal/biz/mocks/CASBackendRepo.go index aae205b65..8bdd89bd6 100644 --- a/app/controlplane/internal/biz/mocks/CASBackendRepo.go +++ b/app/controlplane/internal/biz/mocks/CASBackendRepo.go @@ -109,6 +109,32 @@ func (_m *CASBackendRepo) FindDefaultBackend(ctx context.Context, orgID uuid.UUI return r0, r1 } +// List provides a mock function with given fields: ctx, orgID +func (_m *CASBackendRepo) List(ctx context.Context, orgID uuid.UUID) ([]*biz.CASBackend, error) { + ret := _m.Called(ctx, orgID) + + var r0 []*biz.CASBackend + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) ([]*biz.CASBackend, error)); ok { + return rf(ctx, orgID) + } + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) []*biz.CASBackend); ok { + r0 = rf(ctx, orgID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*biz.CASBackend) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, orgID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Update provides a mock function with given fields: _a0, _a1 func (_m *CASBackendRepo) Update(_a0 context.Context, _a1 *biz.CASBackendUpdateOpts) (*biz.CASBackend, error) { ret := _m.Called(_a0, _a1) diff --git a/app/controlplane/internal/data/casbackend.go b/app/controlplane/internal/data/casbackend.go index c9a923eb5..9d87dcaf7 100644 --- a/app/controlplane/internal/data/casbackend.go +++ b/app/controlplane/internal/data/casbackend.go @@ -45,7 +45,7 @@ func (r *CASBackendRepo) List(ctx context.Context, orgID uuid.UUID) ([]*biz.CASB return nil, fmt.Errorf("failed to list cas backends: %w", err) } - var res []*biz.CASBackend + res := make([]*biz.CASBackend, 0, len(backends)) for _, backend := range backends { res = append(res, entCASBackendToBiz(backend)) } From b1e99d60b66dbcda8b34c5039002aaab0e781ce0 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 12 Jul 2023 16:56:31 +0200 Subject: [PATCH 3/4] feat(api): list cas-backends Signed-off-by: Miguel Martinez Trivino --- .../frontend/google/protobuf/descriptor.ts | 340 +++++++++++++++++- .../biz/casbackend_integration_test.go | 111 ++++++ .../biz/organization_integration_test.go | 6 +- .../internal/biz/testhelpers/database.go | 2 +- .../internal/biz/testhelpers/wire_gen.go | 2 +- .../biz/workflowrun_integration_test.go | 2 +- app/controlplane/internal/data/casbackend.go | 7 +- 7 files changed, 448 insertions(+), 22 deletions(-) create mode 100644 app/controlplane/internal/biz/casbackend_integration_test.go diff --git a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts index b961385bd..71df319e6 100644 --- a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts +++ b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts @@ -42,9 +42,13 @@ export interface FileDescriptorProto { sourceCodeInfo?: SourceCodeInfo; /** * The syntax of the proto file. - * The supported values are "proto2" and "proto3". + * The supported values are "proto2", "proto3", and "editions". + * + * If `edition` is present, this value must be "editions". */ syntax: string; + /** The edition of the proto file, which is an opaque string. */ + edition: string; } /** Describes a message type. */ @@ -619,6 +623,10 @@ export interface MessageOptions { */ deprecated: boolean; /** + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. + * * Whether the message is an automatically generated map entry type for the * maps field. * @@ -636,12 +644,23 @@ export interface MessageOptions { * use a native map in the target language to hold the keys and values. * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. - * - * NOTE: Do not set the option in .proto files. Always use the maps syntax - * instead. The option should only be implicitly set by the proto compiler - * parser. */ mapEntry: boolean; + /** + * Enable the legacy handling of JSON field name conflicts. This lowercases + * and strips underscored from the fields before comparison in proto3 only. + * The new behavior takes `json_name` into account and applies to proto2 as + * well. + * + * This should only be used as a temporary measure against broken builds due + * to the change in behavior for JSON field name conflicts. + * + * TODO(b/261750190) This is legacy behavior we plan to remove once downstream + * teams have had time to migrate. + * + * @deprecated + */ + deprecatedLegacyJsonFieldConflicts: boolean; /** The parser stores options it doesn't recognize here. See above. */ uninterpretedOption: UninterpretedOption[]; } @@ -705,11 +724,8 @@ export interface FieldOptions { * check its required fields, regardless of whether or not the message has * been parsed. * - * As of 2021, lazy does no correctness checks on the byte stream during - * parsing. This may lead to crashes if and when an invalid byte stream is - * finally parsed upon access. - * - * TODO(b/211906113): Enable validation on lazy fields. + * As of May 2022, lazy verifies the contents of the byte stream during + * parsing. An invalid byte stream will cause the overall parsing to fail. */ lazy: boolean; /** @@ -727,6 +743,13 @@ export interface FieldOptions { deprecated: boolean; /** For Google-internal migration only. Do not use. */ weak: boolean; + /** + * Indicate that the field value should not be printed out when using debug + * formats, e.g. when the field contains sensitive credentials. + */ + debugRedact: boolean; + retention: FieldOptions_OptionRetention; + target: FieldOptions_OptionTargetType; /** The parser stores options it doesn't recognize here. See above. */ uninterpretedOption: UninterpretedOption[]; } @@ -813,6 +836,137 @@ export function fieldOptions_JSTypeToJSON(object: FieldOptions_JSType): string { } } +/** + * If set to RETENTION_SOURCE, the option will be omitted from the binary. + * Note: as of January 2023, support for this is in progress and does not yet + * have an effect (b/264593489). + */ +export enum FieldOptions_OptionRetention { + RETENTION_UNKNOWN = 0, + RETENTION_RUNTIME = 1, + RETENTION_SOURCE = 2, + UNRECOGNIZED = -1, +} + +export function fieldOptions_OptionRetentionFromJSON(object: any): FieldOptions_OptionRetention { + switch (object) { + case 0: + case "RETENTION_UNKNOWN": + return FieldOptions_OptionRetention.RETENTION_UNKNOWN; + case 1: + case "RETENTION_RUNTIME": + return FieldOptions_OptionRetention.RETENTION_RUNTIME; + case 2: + case "RETENTION_SOURCE": + return FieldOptions_OptionRetention.RETENTION_SOURCE; + case -1: + case "UNRECOGNIZED": + default: + return FieldOptions_OptionRetention.UNRECOGNIZED; + } +} + +export function fieldOptions_OptionRetentionToJSON(object: FieldOptions_OptionRetention): string { + switch (object) { + case FieldOptions_OptionRetention.RETENTION_UNKNOWN: + return "RETENTION_UNKNOWN"; + case FieldOptions_OptionRetention.RETENTION_RUNTIME: + return "RETENTION_RUNTIME"; + case FieldOptions_OptionRetention.RETENTION_SOURCE: + return "RETENTION_SOURCE"; + case FieldOptions_OptionRetention.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * This indicates the types of entities that the field may apply to when used + * as an option. If it is unset, then the field may be freely used as an + * option on any kind of entity. Note: as of January 2023, support for this is + * in progress and does not yet have an effect (b/264593489). + */ +export enum FieldOptions_OptionTargetType { + TARGET_TYPE_UNKNOWN = 0, + TARGET_TYPE_FILE = 1, + TARGET_TYPE_EXTENSION_RANGE = 2, + TARGET_TYPE_MESSAGE = 3, + TARGET_TYPE_FIELD = 4, + TARGET_TYPE_ONEOF = 5, + TARGET_TYPE_ENUM = 6, + TARGET_TYPE_ENUM_ENTRY = 7, + TARGET_TYPE_SERVICE = 8, + TARGET_TYPE_METHOD = 9, + UNRECOGNIZED = -1, +} + +export function fieldOptions_OptionTargetTypeFromJSON(object: any): FieldOptions_OptionTargetType { + switch (object) { + case 0: + case "TARGET_TYPE_UNKNOWN": + return FieldOptions_OptionTargetType.TARGET_TYPE_UNKNOWN; + case 1: + case "TARGET_TYPE_FILE": + return FieldOptions_OptionTargetType.TARGET_TYPE_FILE; + case 2: + case "TARGET_TYPE_EXTENSION_RANGE": + return FieldOptions_OptionTargetType.TARGET_TYPE_EXTENSION_RANGE; + case 3: + case "TARGET_TYPE_MESSAGE": + return FieldOptions_OptionTargetType.TARGET_TYPE_MESSAGE; + case 4: + case "TARGET_TYPE_FIELD": + return FieldOptions_OptionTargetType.TARGET_TYPE_FIELD; + case 5: + case "TARGET_TYPE_ONEOF": + return FieldOptions_OptionTargetType.TARGET_TYPE_ONEOF; + case 6: + case "TARGET_TYPE_ENUM": + return FieldOptions_OptionTargetType.TARGET_TYPE_ENUM; + case 7: + case "TARGET_TYPE_ENUM_ENTRY": + return FieldOptions_OptionTargetType.TARGET_TYPE_ENUM_ENTRY; + case 8: + case "TARGET_TYPE_SERVICE": + return FieldOptions_OptionTargetType.TARGET_TYPE_SERVICE; + case 9: + case "TARGET_TYPE_METHOD": + return FieldOptions_OptionTargetType.TARGET_TYPE_METHOD; + case -1: + case "UNRECOGNIZED": + default: + return FieldOptions_OptionTargetType.UNRECOGNIZED; + } +} + +export function fieldOptions_OptionTargetTypeToJSON(object: FieldOptions_OptionTargetType): string { + switch (object) { + case FieldOptions_OptionTargetType.TARGET_TYPE_UNKNOWN: + return "TARGET_TYPE_UNKNOWN"; + case FieldOptions_OptionTargetType.TARGET_TYPE_FILE: + return "TARGET_TYPE_FILE"; + case FieldOptions_OptionTargetType.TARGET_TYPE_EXTENSION_RANGE: + return "TARGET_TYPE_EXTENSION_RANGE"; + case FieldOptions_OptionTargetType.TARGET_TYPE_MESSAGE: + return "TARGET_TYPE_MESSAGE"; + case FieldOptions_OptionTargetType.TARGET_TYPE_FIELD: + return "TARGET_TYPE_FIELD"; + case FieldOptions_OptionTargetType.TARGET_TYPE_ONEOF: + return "TARGET_TYPE_ONEOF"; + case FieldOptions_OptionTargetType.TARGET_TYPE_ENUM: + return "TARGET_TYPE_ENUM"; + case FieldOptions_OptionTargetType.TARGET_TYPE_ENUM_ENTRY: + return "TARGET_TYPE_ENUM_ENTRY"; + case FieldOptions_OptionTargetType.TARGET_TYPE_SERVICE: + return "TARGET_TYPE_SERVICE"; + case FieldOptions_OptionTargetType.TARGET_TYPE_METHOD: + return "TARGET_TYPE_METHOD"; + case FieldOptions_OptionTargetType.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + export interface OneofOptions { /** The parser stores options it doesn't recognize here. See above. */ uninterpretedOption: UninterpretedOption[]; @@ -831,6 +985,17 @@ export interface EnumOptions { * is a formalization for deprecating enums. */ deprecated: boolean; + /** + * Enable the legacy handling of JSON field name conflicts. This lowercases + * and strips underscored from the fields before comparison in proto3 only. + * The new behavior takes `json_name` into account and applies to proto2 as + * well. + * TODO(b/261750190) Remove this legacy behavior once downstream teams have + * had time to migrate. + * + * @deprecated + */ + deprecatedLegacyJsonFieldConflicts: boolean; /** The parser stores options it doesn't recognize here. See above. */ uninterpretedOption: UninterpretedOption[]; } @@ -1122,10 +1287,57 @@ export interface GeneratedCodeInfo_Annotation { begin: number; /** * Identifies the ending offset in bytes in the generated code that - * relates to the identified offset. The end offset should be one past + * relates to the identified object. The end offset should be one past * the last relevant byte (so the length of the text = end - begin). */ end: number; + semantic: GeneratedCodeInfo_Annotation_Semantic; +} + +/** + * Represents the identified object's effect on the element in the original + * .proto file. + */ +export enum GeneratedCodeInfo_Annotation_Semantic { + /** NONE - There is no effect or the effect is indescribable. */ + NONE = 0, + /** SET - The element is set or otherwise mutated. */ + SET = 1, + /** ALIAS - An alias to the element is returned. */ + ALIAS = 2, + UNRECOGNIZED = -1, +} + +export function generatedCodeInfo_Annotation_SemanticFromJSON(object: any): GeneratedCodeInfo_Annotation_Semantic { + switch (object) { + case 0: + case "NONE": + return GeneratedCodeInfo_Annotation_Semantic.NONE; + case 1: + case "SET": + return GeneratedCodeInfo_Annotation_Semantic.SET; + case 2: + case "ALIAS": + return GeneratedCodeInfo_Annotation_Semantic.ALIAS; + case -1: + case "UNRECOGNIZED": + default: + return GeneratedCodeInfo_Annotation_Semantic.UNRECOGNIZED; + } +} + +export function generatedCodeInfo_Annotation_SemanticToJSON(object: GeneratedCodeInfo_Annotation_Semantic): string { + switch (object) { + case GeneratedCodeInfo_Annotation_Semantic.NONE: + return "NONE"; + case GeneratedCodeInfo_Annotation_Semantic.SET: + return "SET"; + case GeneratedCodeInfo_Annotation_Semantic.ALIAS: + return "ALIAS"; + case GeneratedCodeInfo_Annotation_Semantic.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } } function createBaseFileDescriptorSet(): FileDescriptorSet { @@ -1202,6 +1414,7 @@ function createBaseFileDescriptorProto(): FileDescriptorProto { options: undefined, sourceCodeInfo: undefined, syntax: "", + edition: "", }; } @@ -1247,6 +1460,9 @@ export const FileDescriptorProto = { if (message.syntax !== "") { writer.uint32(98).string(message.syntax); } + if (message.edition !== "") { + writer.uint32(106).string(message.edition); + } return writer; }, @@ -1361,6 +1577,13 @@ export const FileDescriptorProto = { message.syntax = reader.string(); continue; + case 13: + if (tag !== 106) { + break; + } + + message.edition = reader.string(); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -1390,6 +1613,7 @@ export const FileDescriptorProto = { options: isSet(object.options) ? FileOptions.fromJSON(object.options) : undefined, sourceCodeInfo: isSet(object.sourceCodeInfo) ? SourceCodeInfo.fromJSON(object.sourceCodeInfo) : undefined, syntax: isSet(object.syntax) ? String(object.syntax) : "", + edition: isSet(object.edition) ? String(object.edition) : "", }; }, @@ -1436,6 +1660,7 @@ export const FileDescriptorProto = { message.sourceCodeInfo !== undefined && (obj.sourceCodeInfo = message.sourceCodeInfo ? SourceCodeInfo.toJSON(message.sourceCodeInfo) : undefined); message.syntax !== undefined && (obj.syntax = message.syntax); + message.edition !== undefined && (obj.edition = message.edition); return obj; }, @@ -1461,6 +1686,7 @@ export const FileDescriptorProto = { ? SourceCodeInfo.fromPartial(object.sourceCodeInfo) : undefined; message.syntax = object.syntax ?? ""; + message.edition = object.edition ?? ""; return message; }, }; @@ -3061,6 +3287,7 @@ function createBaseMessageOptions(): MessageOptions { noStandardDescriptorAccessor: false, deprecated: false, mapEntry: false, + deprecatedLegacyJsonFieldConflicts: false, uninterpretedOption: [], }; } @@ -3079,6 +3306,9 @@ export const MessageOptions = { if (message.mapEntry === true) { writer.uint32(56).bool(message.mapEntry); } + if (message.deprecatedLegacyJsonFieldConflicts === true) { + writer.uint32(88).bool(message.deprecatedLegacyJsonFieldConflicts); + } for (const v of message.uninterpretedOption) { UninterpretedOption.encode(v!, writer.uint32(7994).fork()).ldelim(); } @@ -3120,6 +3350,13 @@ export const MessageOptions = { message.mapEntry = reader.bool(); continue; + case 11: + if (tag !== 88) { + break; + } + + message.deprecatedLegacyJsonFieldConflicts = reader.bool(); + continue; case 999: if (tag !== 7994) { break; @@ -3144,6 +3381,9 @@ export const MessageOptions = { : false, deprecated: isSet(object.deprecated) ? Boolean(object.deprecated) : false, mapEntry: isSet(object.mapEntry) ? Boolean(object.mapEntry) : false, + deprecatedLegacyJsonFieldConflicts: isSet(object.deprecatedLegacyJsonFieldConflicts) + ? Boolean(object.deprecatedLegacyJsonFieldConflicts) + : false, uninterpretedOption: Array.isArray(object?.uninterpretedOption) ? object.uninterpretedOption.map((e: any) => UninterpretedOption.fromJSON(e)) : [], @@ -3157,6 +3397,8 @@ export const MessageOptions = { (obj.noStandardDescriptorAccessor = message.noStandardDescriptorAccessor); message.deprecated !== undefined && (obj.deprecated = message.deprecated); message.mapEntry !== undefined && (obj.mapEntry = message.mapEntry); + message.deprecatedLegacyJsonFieldConflicts !== undefined && + (obj.deprecatedLegacyJsonFieldConflicts = message.deprecatedLegacyJsonFieldConflicts); if (message.uninterpretedOption) { obj.uninterpretedOption = message.uninterpretedOption.map((e) => e ? UninterpretedOption.toJSON(e) : undefined); } else { @@ -3175,6 +3417,7 @@ export const MessageOptions = { message.noStandardDescriptorAccessor = object.noStandardDescriptorAccessor ?? false; message.deprecated = object.deprecated ?? false; message.mapEntry = object.mapEntry ?? false; + message.deprecatedLegacyJsonFieldConflicts = object.deprecatedLegacyJsonFieldConflicts ?? false; message.uninterpretedOption = object.uninterpretedOption?.map((e) => UninterpretedOption.fromPartial(e)) || []; return message; }, @@ -3189,6 +3432,9 @@ function createBaseFieldOptions(): FieldOptions { unverifiedLazy: false, deprecated: false, weak: false, + debugRedact: false, + retention: 0, + target: 0, uninterpretedOption: [], }; } @@ -3216,6 +3462,15 @@ export const FieldOptions = { if (message.weak === true) { writer.uint32(80).bool(message.weak); } + if (message.debugRedact === true) { + writer.uint32(128).bool(message.debugRedact); + } + if (message.retention !== 0) { + writer.uint32(136).int32(message.retention); + } + if (message.target !== 0) { + writer.uint32(144).int32(message.target); + } for (const v of message.uninterpretedOption) { UninterpretedOption.encode(v!, writer.uint32(7994).fork()).ldelim(); } @@ -3278,6 +3533,27 @@ export const FieldOptions = { message.weak = reader.bool(); continue; + case 16: + if (tag !== 128) { + break; + } + + message.debugRedact = reader.bool(); + continue; + case 17: + if (tag !== 136) { + break; + } + + message.retention = reader.int32() as any; + continue; + case 18: + if (tag !== 144) { + break; + } + + message.target = reader.int32() as any; + continue; case 999: if (tag !== 7994) { break; @@ -3303,6 +3579,9 @@ export const FieldOptions = { unverifiedLazy: isSet(object.unverifiedLazy) ? Boolean(object.unverifiedLazy) : false, deprecated: isSet(object.deprecated) ? Boolean(object.deprecated) : false, weak: isSet(object.weak) ? Boolean(object.weak) : false, + debugRedact: isSet(object.debugRedact) ? Boolean(object.debugRedact) : false, + retention: isSet(object.retention) ? fieldOptions_OptionRetentionFromJSON(object.retention) : 0, + target: isSet(object.target) ? fieldOptions_OptionTargetTypeFromJSON(object.target) : 0, uninterpretedOption: Array.isArray(object?.uninterpretedOption) ? object.uninterpretedOption.map((e: any) => UninterpretedOption.fromJSON(e)) : [], @@ -3318,6 +3597,9 @@ export const FieldOptions = { message.unverifiedLazy !== undefined && (obj.unverifiedLazy = message.unverifiedLazy); message.deprecated !== undefined && (obj.deprecated = message.deprecated); message.weak !== undefined && (obj.weak = message.weak); + message.debugRedact !== undefined && (obj.debugRedact = message.debugRedact); + message.retention !== undefined && (obj.retention = fieldOptions_OptionRetentionToJSON(message.retention)); + message.target !== undefined && (obj.target = fieldOptions_OptionTargetTypeToJSON(message.target)); if (message.uninterpretedOption) { obj.uninterpretedOption = message.uninterpretedOption.map((e) => e ? UninterpretedOption.toJSON(e) : undefined); } else { @@ -3339,6 +3621,9 @@ export const FieldOptions = { message.unverifiedLazy = object.unverifiedLazy ?? false; message.deprecated = object.deprecated ?? false; message.weak = object.weak ?? false; + message.debugRedact = object.debugRedact ?? false; + message.retention = object.retention ?? 0; + message.target = object.target ?? 0; message.uninterpretedOption = object.uninterpretedOption?.map((e) => UninterpretedOption.fromPartial(e)) || []; return message; }, @@ -3409,7 +3694,7 @@ export const OneofOptions = { }; function createBaseEnumOptions(): EnumOptions { - return { allowAlias: false, deprecated: false, uninterpretedOption: [] }; + return { allowAlias: false, deprecated: false, deprecatedLegacyJsonFieldConflicts: false, uninterpretedOption: [] }; } export const EnumOptions = { @@ -3420,6 +3705,9 @@ export const EnumOptions = { if (message.deprecated === true) { writer.uint32(24).bool(message.deprecated); } + if (message.deprecatedLegacyJsonFieldConflicts === true) { + writer.uint32(48).bool(message.deprecatedLegacyJsonFieldConflicts); + } for (const v of message.uninterpretedOption) { UninterpretedOption.encode(v!, writer.uint32(7994).fork()).ldelim(); } @@ -3447,6 +3735,13 @@ export const EnumOptions = { message.deprecated = reader.bool(); continue; + case 6: + if (tag !== 48) { + break; + } + + message.deprecatedLegacyJsonFieldConflicts = reader.bool(); + continue; case 999: if (tag !== 7994) { break; @@ -3467,6 +3762,9 @@ export const EnumOptions = { return { allowAlias: isSet(object.allowAlias) ? Boolean(object.allowAlias) : false, deprecated: isSet(object.deprecated) ? Boolean(object.deprecated) : false, + deprecatedLegacyJsonFieldConflicts: isSet(object.deprecatedLegacyJsonFieldConflicts) + ? Boolean(object.deprecatedLegacyJsonFieldConflicts) + : false, uninterpretedOption: Array.isArray(object?.uninterpretedOption) ? object.uninterpretedOption.map((e: any) => UninterpretedOption.fromJSON(e)) : [], @@ -3477,6 +3775,8 @@ export const EnumOptions = { const obj: any = {}; message.allowAlias !== undefined && (obj.allowAlias = message.allowAlias); message.deprecated !== undefined && (obj.deprecated = message.deprecated); + message.deprecatedLegacyJsonFieldConflicts !== undefined && + (obj.deprecatedLegacyJsonFieldConflicts = message.deprecatedLegacyJsonFieldConflicts); if (message.uninterpretedOption) { obj.uninterpretedOption = message.uninterpretedOption.map((e) => e ? UninterpretedOption.toJSON(e) : undefined); } else { @@ -3493,6 +3793,7 @@ export const EnumOptions = { const message = createBaseEnumOptions(); message.allowAlias = object.allowAlias ?? false; message.deprecated = object.deprecated ?? false; + message.deprecatedLegacyJsonFieldConflicts = object.deprecatedLegacyJsonFieldConflicts ?? false; message.uninterpretedOption = object.uninterpretedOption?.map((e) => UninterpretedOption.fromPartial(e)) || []; return message; }, @@ -4242,7 +4543,7 @@ export const GeneratedCodeInfo = { }; function createBaseGeneratedCodeInfo_Annotation(): GeneratedCodeInfo_Annotation { - return { path: [], sourceFile: "", begin: 0, end: 0 }; + return { path: [], sourceFile: "", begin: 0, end: 0, semantic: 0 }; } export const GeneratedCodeInfo_Annotation = { @@ -4261,6 +4562,9 @@ export const GeneratedCodeInfo_Annotation = { if (message.end !== 0) { writer.uint32(32).int32(message.end); } + if (message.semantic !== 0) { + writer.uint32(40).int32(message.semantic); + } return writer; }, @@ -4309,6 +4613,13 @@ export const GeneratedCodeInfo_Annotation = { message.end = reader.int32(); continue; + case 5: + if (tag !== 40) { + break; + } + + message.semantic = reader.int32() as any; + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -4324,6 +4635,7 @@ export const GeneratedCodeInfo_Annotation = { sourceFile: isSet(object.sourceFile) ? String(object.sourceFile) : "", begin: isSet(object.begin) ? Number(object.begin) : 0, end: isSet(object.end) ? Number(object.end) : 0, + semantic: isSet(object.semantic) ? generatedCodeInfo_Annotation_SemanticFromJSON(object.semantic) : 0, }; }, @@ -4337,6 +4649,7 @@ export const GeneratedCodeInfo_Annotation = { message.sourceFile !== undefined && (obj.sourceFile = message.sourceFile); message.begin !== undefined && (obj.begin = Math.round(message.begin)); message.end !== undefined && (obj.end = Math.round(message.end)); + message.semantic !== undefined && (obj.semantic = generatedCodeInfo_Annotation_SemanticToJSON(message.semantic)); return obj; }, @@ -4350,6 +4663,7 @@ export const GeneratedCodeInfo_Annotation = { message.sourceFile = object.sourceFile ?? ""; message.begin = object.begin ?? 0; message.end = object.end ?? 0; + message.semantic = object.semantic ?? 0; return message; }, }; diff --git a/app/controlplane/internal/biz/casbackend_integration_test.go b/app/controlplane/internal/biz/casbackend_integration_test.go new file mode 100644 index 000000000..45fa4d622 --- /dev/null +++ b/app/controlplane/internal/biz/casbackend_integration_test.go @@ -0,0 +1,111 @@ +// +// Copyright 2023 The Chainloop 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 biz_test + +import ( + "context" + "testing" + + "github.com/chainloop-dev/chainloop/app/controlplane/internal/biz" + "github.com/chainloop-dev/chainloop/app/controlplane/internal/biz/testhelpers" + creds "github.com/chainloop-dev/chainloop/internal/credentials/mocks" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" +) + +func (s *CASBackendIntegrationTestSuite) TestList() { + testCases := []struct { + name string + orgID string + expectedResult []*biz.CASBackend + }{ + { + name: "non-existent org", + orgID: uuid.New().String(), + expectedResult: []*biz.CASBackend{}, + }, + { + name: "no backends for org", + orgID: s.orgNoBackend.ID, + expectedResult: []*biz.CASBackend{}, + }, + { + name: "one backend for org", + orgID: s.orgOne.ID, + expectedResult: []*biz.CASBackend{ + s.casBackend1, + }, + }, + { + name: "backend 2 in org", + orgID: s.orgTwo.ID, + expectedResult: []*biz.CASBackend{ + s.casBackend2, + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + assert := assert.New(s.T()) + ctx := context.Background() + backends, err := s.TestingUseCases.CASBackend.List(ctx, tc.orgID) + assert.NoError(err) + assert.Equal(tc.expectedResult, backends) + }) + } +} + +func (s *CASBackendIntegrationTestSuite) SetupTest() { + var err error + assert := assert.New(s.T()) + ctx := context.Background() + // OCI repository credentials + credsWriter := creds.NewReaderWriter(s.T()) + credsWriter.On( + "SaveCredentials", ctx, mock.Anything, mock.Anything, + ).Return("stored-OCI-secret", nil) + + s.TestingUseCases = testhelpers.NewTestingUseCases(s.T(), testhelpers.WithCredsReaderWriter(credsWriter)) + + s.orgOne, err = s.Organization.Create(ctx, "testing org 1") + assert.NoError(err) + s.orgTwo, err = s.Organization.Create(ctx, "testing org 2") + assert.NoError(err) + s.orgNoBackend, err = s.Organization.Create(ctx, "testing org 3") + assert.NoError(err) + + s.casBackend1, err = s.CASBackend.CreateOrUpdate(ctx, s.orgOne.ID, "backend 1", "username", "pass", biz.CASBackendOCI, true) + assert.NoError(err) + s.casBackend2, err = s.CASBackend.CreateOrUpdate(ctx, s.orgTwo.ID, "backend 2", "username", "pass", biz.CASBackendOCI, true) + assert.NoError(err) +} + +func TestCASBackendUseCase(t *testing.T) { + suite.Run(t, new(CASBackendIntegrationTestSuite)) +} + +type CASBackendIntegrationTestSuite struct { + testhelpers.UseCasesEachTestSuite + orgTwo, orgOne, orgNoBackend *biz.Organization + casBackend1, casBackend2 *biz.CASBackend +} + +func TestIntegrationCASBackend(t *testing.T) { + suite.Run(t, new(CASBackendIntegrationTestSuite)) +} diff --git a/app/controlplane/internal/biz/organization_integration_test.go b/app/controlplane/internal/biz/organization_integration_test.go index e6b6f4ec3..387520fd9 100644 --- a/app/controlplane/internal/biz/organization_integration_test.go +++ b/app/controlplane/internal/biz/organization_integration_test.go @@ -66,7 +66,7 @@ func (s *OrgIntegrationTestSuite) TestDeleteOrg() { assert.NoError(err) assert.Empty(integrations) - ociRepo, err := s.CASBackendRepo.FindDefaultBackend(ctx, s.org.ID) + ociRepo, err := s.CASBackend.FindDefaultBackend(ctx, s.org.ID) assert.NoError(err) assert.Nil(ociRepo) @@ -128,7 +128,7 @@ func (s *OrgIntegrationTestSuite) SetupTest() { assert.NoError(err) // OCI repository - _, err = s.CASBackendRepo.CreateOrUpdate(ctx, s.org.ID, "repo", "username", "pass", biz.CASBackendOCI, true) + _, err = s.CASBackend.CreateOrUpdate(ctx, s.org.ID, "repo", "username", "pass", biz.CASBackendOCI, true) assert.NoError(err) // Workflow + contract @@ -140,7 +140,7 @@ func (s *OrgIntegrationTestSuite) SetupTest() { assert.NoError(err) assert.Len(integrations, 1) - ociRepo, err := s.CASBackendRepo.FindDefaultBackend(ctx, s.org.ID) + ociRepo, err := s.CASBackend.FindDefaultBackend(ctx, s.org.ID) assert.NoError(err) assert.NotNil(ociRepo) diff --git a/app/controlplane/internal/biz/testhelpers/database.go b/app/controlplane/internal/biz/testhelpers/database.go index 82f15a226..4ef117dae 100644 --- a/app/controlplane/internal/biz/testhelpers/database.go +++ b/app/controlplane/internal/biz/testhelpers/database.go @@ -52,7 +52,7 @@ type TestingUseCases struct { // Use cases Membership *biz.MembershipUseCase - CASBackendRepo *biz.CASBackendUseCase + CASBackend *biz.CASBackendUseCase Integration *biz.IntegrationUseCase Organization *biz.OrganizationUseCase WorkflowContract *biz.WorkflowContractUseCase diff --git a/app/controlplane/internal/biz/testhelpers/wire_gen.go b/app/controlplane/internal/biz/testhelpers/wire_gen.go index 81bc35888..784bbab31 100644 --- a/app/controlplane/internal/biz/testhelpers/wire_gen.go +++ b/app/controlplane/internal/biz/testhelpers/wire_gen.go @@ -73,7 +73,7 @@ func WireTestData(testDatabase *TestDatabase, t *testing.T, logger log.Logger, r Data: dataData, L: logger, Membership: membershipUseCase, - CASBackendRepo: casBackendUseCase, + CASBackend: casBackendUseCase, Integration: integrationUseCase, Organization: organizationUseCase, WorkflowContract: workflowContractUseCase, diff --git a/app/controlplane/internal/biz/workflowrun_integration_test.go b/app/controlplane/internal/biz/workflowrun_integration_test.go index 3eb5407b2..4b8ca9eb4 100644 --- a/app/controlplane/internal/biz/workflowrun_integration_test.go +++ b/app/controlplane/internal/biz/workflowrun_integration_test.go @@ -125,6 +125,6 @@ func (s *workflowRunIntegrationTestSuite) SetupTest() { s.contractVersion, err = s.WorkflowContract.Describe(ctx, s.org.ID, s.workflow.ContractID.String(), 0) assert.NoError(err) - s.casBackend, err = s.CASBackendRepo.CreateOrUpdate(ctx, s.org.ID, "repo", "username", "pass", biz.CASBackendOCI, true) + s.casBackend, err = s.CASBackend.CreateOrUpdate(ctx, s.org.ID, "repo", "username", "pass", biz.CASBackendOCI, true) assert.NoError(err) } diff --git a/app/controlplane/internal/data/casbackend.go b/app/controlplane/internal/data/casbackend.go index 9d87dcaf7..864c1d631 100644 --- a/app/controlplane/internal/data/casbackend.go +++ b/app/controlplane/internal/data/casbackend.go @@ -40,7 +40,7 @@ func NewCASBackendRepo(data *Data, logger log.Logger) biz.CASBackendRepo { } func (r *CASBackendRepo) List(ctx context.Context, orgID uuid.UUID) ([]*biz.CASBackend, error) { - backends, err := orgScopedQuery(r.data.db, orgID).QueryCasBackends().All(ctx) + backends, err := orgScopedQuery(r.data.db, orgID).QueryCasBackends().WithOrganization().All(ctx) if err != nil { return nil, fmt.Errorf("failed to list cas backends: %w", err) } @@ -74,7 +74,8 @@ func (r *CASBackendRepo) Create(ctx context.Context, opts *biz.CASBackendCreateO return nil, err } - return entCASBackendToBiz(backend), nil + // Return the backend from the DB to have consistent timestamp data + return r.FindByID(ctx, backend.ID) } func (r *CASBackendRepo) Update(ctx context.Context, opts *biz.CASBackendUpdateOpts) (*biz.CASBackend, error) { @@ -88,7 +89,7 @@ func (r *CASBackendRepo) Update(ctx context.Context, opts *biz.CASBackendUpdateO return nil, err } - return entCASBackendToBiz(backend), nil + return r.FindByID(ctx, backend.ID) } // FindByID finds a CAS backend by ID in the given organization. From 82b05865bafc6e9c6f1ae9b272fbf10320cf349e Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 12 Jul 2023 17:13:00 +0200 Subject: [PATCH 4/4] feat(api): list cas-backends Signed-off-by: Miguel Martinez Trivino --- app/controlplane/internal/biz/workflowrun_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controlplane/internal/biz/workflowrun_integration_test.go b/app/controlplane/internal/biz/workflowrun_integration_test.go index 4b8ca9eb4..8db68ab52 100644 --- a/app/controlplane/internal/biz/workflowrun_integration_test.go +++ b/app/controlplane/internal/biz/workflowrun_integration_test.go @@ -76,7 +76,7 @@ func (s *workflowRunIntegrationTestSuite) TestCreate() { CASBackends: []*biz.CASBackend{s.casBackend}, }, run, cmpopts.IgnoreFields(biz.WorkflowRun{}, "CreatedAt", "ID", "Workflow"), - cmpopts.IgnoreFields(biz.CASBackend{}, "CreatedAt", "ValidatedAt"), + cmpopts.IgnoreFields(biz.CASBackend{}, "CreatedAt", "ValidatedAt", "OrganizationID"), ); diff != "" { assert.Failf("mismatch (-want +got):\n%s", diff) }