diff --git a/.dockerignore b/.dockerignore
index e3a9fdfeb..2612530ed 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,5 +1,10 @@
*
!bin/dev/porter-linux-amd64
+!bin/dev/porter-linux-arm64
+!bin/dev/porter-api-server-linux-amd64
+!bin/dev/porter-api-server-linux-arm64
!bin/dev/agent-linux-amd64
+!bin/dev/agent-linux-arm64
!bin/mixins/exec/dev/exec-linux-amd64
+!bin/mixins/exec/dev/exec-linux-arm64
diff --git a/.github/workflows/build-publish-from-fork.yaml b/.github/workflows/build-publish-from-fork.yaml
new file mode 100644
index 000000000..7a2ff2b9f
--- /dev/null
+++ b/.github/workflows/build-publish-from-fork.yaml
@@ -0,0 +1,36 @@
+name: build-publish-from-fork
+on:
+ workflow_dispatch: {}
+ push: {}
+ pull_request: {}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: github.repository != 'getporter/porter'
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Login to DockerHub
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+ - uses: actions/setup-go@v3
+ with:
+ go-version-file: go.mod
+ cache: true
+ cache-dependency-path: go.sum
+ - name: Set up Mage
+ run: go run mage.go EnsureMage
+ - name: Publish
+ if: ${{ github.event_name != 'pull_request' }}
+ env:
+ PORTER_REGISTRY: ghcr.io/${{ github.repository }}
+ run: |
+ mage -v XBuildAll
+ mage -v PublishServerMultiArchImages
diff --git a/.gitignore b/.gitignore
index 3e72e2382..f23f81a9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,5 +16,11 @@ examples/**/Dockerfile
workshop/**/Dockerfile
.vscode
+*.code-workspace
.idea
kind.config
+grpc-porter-tls.crt
+grpc-porter-tls.key
+grpc-porter.csr
+.grpcurl/
+config.yaml
diff --git a/build/images/server/Dockerfile b/build/images/server/Dockerfile
new file mode 100644
index 000000000..f9a19bf0b
--- /dev/null
+++ b/build/images/server/Dockerfile
@@ -0,0 +1,28 @@
+FROM alpine:3 as builder
+ARG TARGETARCH
+WORKDIR /app/.porter
+
+RUN mkdir runtimes && \
+ mkdir -p mixins/exec/runtimes
+
+# Install porter-api-server, agent, and the exec mixin, everything else
+COPY bin/dev/porter-api-server-linux-$TARGETARCH porter
+COPY bin/dev/agent-linux-$TARGETARCH agent
+COPY bin/mixins/exec/dev/exec-linux-$TARGETARCH mixins/exec/exec
+RUN ln -s /app/.porter/porter runtimes/porter-runtime && \
+ ln -s /app/.porter/mixins/exec/exec mixins/exec/runtimes/exec-runtime
+
+# Copy the porter installation into a distroless container
+# Explicitly not using the nonroot tag because we don't want the user to exist so it is placed in the root group
+# This allows us to run with a random UID, and access a mounted docker socket (which is only accessible via the root group)
+FROM gcr.io/distroless/static
+WORKDIR /app
+COPY --from=builder --chown=65532:0 --chmod=770 /app/.porter /app/.porter
+ENV PATH "$PATH:/app/.porter"
+# This is where files that need to be copied into /app/.porter/ should be mounted
+VOLUME /porter-config
+ENV PORTER_HOME /app/.porter
+
+# Run as a nonroot user
+USER 65532
+ENTRYPOINT ["/app/.porter/agent"]
\ No newline at end of file
diff --git a/build/protoc.Dockerfile b/build/protoc.Dockerfile
new file mode 100644
index 000000000..495047491
--- /dev/null
+++ b/build/protoc.Dockerfile
@@ -0,0 +1,5 @@
+FROM golang:1.19.0
+RUN apt-get update && apt-get -y install protobuf-compiler
+RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
+RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
+WORKDIR /proto
diff --git a/cmd/porter/main.go b/cmd/porter/main.go
index 0f4d1c6a1..388a42e75 100644
--- a/cmd/porter/main.go
+++ b/cmd/porter/main.go
@@ -7,6 +7,7 @@ import (
"os"
"os/signal"
"runtime/debug"
+ "strconv"
"strings"
"get.porter.sh/porter/pkg/cli"
@@ -19,6 +20,8 @@ import (
var includeDocsCommand = false
+var includeGRPCServer string = "false"
+
//go:embed helptext/usage.txt
var usageText string
@@ -226,6 +229,11 @@ Try our QuickStart https://getporter.org/quickstart to learn how to use Porter.
cmd.AddCommand(buildCredentialsCommands(p))
cmd.AddCommand(buildParametersCommands(p))
cmd.AddCommand(buildCompletionCommand(p))
+ //use -ldflags "-X main.includeGRPCServer=true" during build to include
+ grpcServer, _ := strconv.ParseBool(includeGRPCServer)
+ if grpcServer {
+ cmd.AddCommand(buildGRPCServerCommands(p))
+ }
for _, alias := range buildAliasCommands(p) {
cmd.AddCommand(alias)
diff --git a/cmd/porter/server.go b/cmd/porter/server.go
new file mode 100644
index 000000000..de0cbda00
--- /dev/null
+++ b/cmd/porter/server.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+ "time"
+
+ grpc "get.porter.sh/porter/pkg/grpc"
+ "get.porter.sh/porter/pkg/porter"
+ "get.porter.sh/porter/pkg/signals"
+ "github.com/spf13/cobra"
+)
+
+func buildGRPCServerCommands(p *porter.Porter) *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "api-server",
+ Short: "API server",
+ Long: "Launch API server for porter",
+ Hidden: true, // This is a hidden command and is currently only meant to be used by the porter operator
+ }
+ cmd.Annotations = map[string]string{
+ "group": "api-server",
+ }
+ cmd.AddCommand(buildServerRunCommand(p))
+ return cmd
+}
+
+func buildServerRunCommand(p *porter.Porter) *cobra.Command {
+ opts := porter.ServiceOptions{}
+ cmd := &cobra.Command{
+ Use: "run",
+ Short: "Run the gRPC server",
+ Long: `Run the gRPC server for porter.
+
+This command starts the gRPC server for porter which is able to expose limited porter functionality via RPC.
+Currently only data operations are supported, creation of resources such as installations, credential sets, or parameter sets is not supported.
+
+A list of the supported RPCs can be found at
+`,
+ PreRunE: func(cmd *cobra.Command, args []string) error {
+ return opts.Validate()
+ },
+ RunE: func(cmd *cobra.Command, args []string) error {
+ srv, err := grpc.NewServer(cmd.Context(), &opts)
+ if err != nil {
+ return err
+ }
+ grpcServer, err := srv.ListenAndServe()
+ stopCh := signals.SetupSignalHandler()
+ serverShutdownTimeout := time.Duration(time.Second * 30)
+ sd, _ := signals.NewShutdown(serverShutdownTimeout, cmd.Context())
+ sd.Graceful(stopCh, grpcServer, cmd.Context())
+ return err
+ },
+ }
+ f := cmd.Flags()
+ f.Int64VarP(&opts.Port, "port", "p", 3001, "Port to run the server on")
+ f.StringVarP(&opts.ServiceName, "service-name", "s", "api-server", "Server service name")
+ return cmd
+}
diff --git a/docker-bake.json b/docker-bake.json
new file mode 100644
index 000000000..a06a3e01d
--- /dev/null
+++ b/docker-bake.json
@@ -0,0 +1,19 @@
+{
+ "group": {
+ "default": {
+ "targets": [
+ "server"
+ ]
+ }
+ },
+ "target": {
+ "server": {
+ "platforms": [
+ "linux/amd64",
+ "linux/arm64"
+ ],
+ "dockerfile": "build/images/server/Dockerfile",
+ "context": "./"
+ }
+ }
+}
\ No newline at end of file
diff --git a/gen/proto/go/porterapis/installation/v1alpha1/installation.pb.go b/gen/proto/go/porterapis/installation/v1alpha1/installation.pb.go
new file mode 100644
index 000000000..0b35ddd8f
--- /dev/null
+++ b/gen/proto/go/porterapis/installation/v1alpha1/installation.pb.go
@@ -0,0 +1,1385 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc (unknown)
+// source: installation/v1alpha1/installation.proto
+
+package installationv1alpha1
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ _ "google.golang.org/protobuf/types/known/anypb"
+ structpb "google.golang.org/protobuf/types/known/structpb"
+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+ 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 Bundle struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Repository string `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"`
+ Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
+}
+
+func (x *Bundle) Reset() {
+ *x = Bundle{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Bundle) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Bundle) ProtoMessage() {}
+
+func (x *Bundle) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_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 Bundle.ProtoReflect.Descriptor instead.
+func (*Bundle) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Bundle) GetRepository() string {
+ if x != nil {
+ return x.Repository
+ }
+ return ""
+}
+
+func (x *Bundle) GetVersion() string {
+ if x != nil {
+ return x.Version
+ }
+ return ""
+}
+
+type InstallationStatus struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RunId string `protobuf:"bytes,1,opt,name=runId,proto3" json:"runId,omitempty"`
+ Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"`
+ ResultId string `protobuf:"bytes,3,opt,name=resultId,proto3" json:"resultId,omitempty"`
+ ResultStatus string `protobuf:"bytes,4,opt,name=resultStatus,proto3" json:"resultStatus,omitempty"`
+ Created *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created,proto3" json:"created,omitempty"`
+ Modified *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=modified,proto3" json:"modified,omitempty"`
+ Installed *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=installed,proto3" json:"installed,omitempty"`
+ Uninstalled *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=uninstalled,proto3" json:"uninstalled,omitempty"`
+ BundleReference string `protobuf:"bytes,9,opt,name=bundleReference,proto3" json:"bundleReference,omitempty"`
+ BundleVersion string `protobuf:"bytes,10,opt,name=bundleVersion,proto3" json:"bundleVersion,omitempty"`
+ BundleDigest string `protobuf:"bytes,11,opt,name=bundleDigest,proto3" json:"bundleDigest,omitempty"`
+}
+
+func (x *InstallationStatus) Reset() {
+ *x = InstallationStatus{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *InstallationStatus) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*InstallationStatus) ProtoMessage() {}
+
+func (x *InstallationStatus) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_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 InstallationStatus.ProtoReflect.Descriptor instead.
+func (*InstallationStatus) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *InstallationStatus) GetRunId() string {
+ if x != nil {
+ return x.RunId
+ }
+ return ""
+}
+
+func (x *InstallationStatus) GetAction() string {
+ if x != nil {
+ return x.Action
+ }
+ return ""
+}
+
+func (x *InstallationStatus) GetResultId() string {
+ if x != nil {
+ return x.ResultId
+ }
+ return ""
+}
+
+func (x *InstallationStatus) GetResultStatus() string {
+ if x != nil {
+ return x.ResultStatus
+ }
+ return ""
+}
+
+func (x *InstallationStatus) GetCreated() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Created
+ }
+ return nil
+}
+
+func (x *InstallationStatus) GetModified() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Modified
+ }
+ return nil
+}
+
+func (x *InstallationStatus) GetInstalled() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Installed
+ }
+ return nil
+}
+
+func (x *InstallationStatus) GetUninstalled() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Uninstalled
+ }
+ return nil
+}
+
+func (x *InstallationStatus) GetBundleReference() string {
+ if x != nil {
+ return x.BundleReference
+ }
+ return ""
+}
+
+func (x *InstallationStatus) GetBundleVersion() string {
+ if x != nil {
+ return x.BundleVersion
+ }
+ return ""
+}
+
+func (x *InstallationStatus) GetBundleDigest() string {
+ if x != nil {
+ return x.BundleDigest
+ }
+ return ""
+}
+
+type Calculated struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DisplayInstallationState string `protobuf:"bytes,1,opt,name=displayInstallationState,proto3" json:"displayInstallationState,omitempty"`
+ DisplayInstallationStatus string `protobuf:"bytes,2,opt,name=displayInstallationStatus,proto3" json:"displayInstallationStatus,omitempty"`
+ ResolvedParameters structpb.NullValue `protobuf:"varint,3,opt,name=resolvedParameters,proto3,enum=google.protobuf.NullValue" json:"resolvedParameters,omitempty"`
+}
+
+func (x *Calculated) Reset() {
+ *x = Calculated{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Calculated) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Calculated) ProtoMessage() {}
+
+func (x *Calculated) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[2]
+ 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 Calculated.ProtoReflect.Descriptor instead.
+func (*Calculated) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Calculated) GetDisplayInstallationState() string {
+ if x != nil {
+ return x.DisplayInstallationState
+ }
+ return ""
+}
+
+func (x *Calculated) GetDisplayInstallationStatus() string {
+ if x != nil {
+ return x.DisplayInstallationStatus
+ }
+ return ""
+}
+
+func (x *Calculated) GetResolvedParameters() structpb.NullValue {
+ if x != nil {
+ return x.ResolvedParameters
+ }
+ return structpb.NullValue(0)
+}
+
+type Installation struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Unique installation ID
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ SchemaType string `protobuf:"bytes,2,opt,name=schemaType,proto3" json:"schemaType,omitempty"`
+ SchemaVersion string `protobuf:"bytes,3,opt,name=schemaVersion,proto3" json:"schemaVersion,omitempty"`
+ Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
+ Namespace string `protobuf:"bytes,5,opt,name=namespace,proto3" json:"namespace,omitempty"`
+ Bundle *Bundle `protobuf:"bytes,6,opt,name=bundle,proto3" json:"bundle,omitempty"`
+ CredentialSets []string `protobuf:"bytes,7,rep,name=credentialSets,proto3" json:"credentialSets,omitempty"`
+ ParameterSets []string `protobuf:"bytes,8,rep,name=parameterSets,proto3" json:"parameterSets,omitempty"`
+ Status *InstallationStatus `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"`
+ Calculated *Calculated `protobuf:"bytes,10,opt,name=calculated,json=_calculated,proto3" json:"calculated,omitempty"`
+}
+
+func (x *Installation) Reset() {
+ *x = Installation{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Installation) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Installation) ProtoMessage() {}
+
+func (x *Installation) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[3]
+ 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 Installation.ProtoReflect.Descriptor instead.
+func (*Installation) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Installation) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *Installation) GetSchemaType() string {
+ if x != nil {
+ return x.SchemaType
+ }
+ return ""
+}
+
+func (x *Installation) GetSchemaVersion() string {
+ if x != nil {
+ return x.SchemaVersion
+ }
+ return ""
+}
+
+func (x *Installation) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *Installation) GetNamespace() string {
+ if x != nil {
+ return x.Namespace
+ }
+ return ""
+}
+
+func (x *Installation) GetBundle() *Bundle {
+ if x != nil {
+ return x.Bundle
+ }
+ return nil
+}
+
+func (x *Installation) GetCredentialSets() []string {
+ if x != nil {
+ return x.CredentialSets
+ }
+ return nil
+}
+
+func (x *Installation) GetParameterSets() []string {
+ if x != nil {
+ return x.ParameterSets
+ }
+ return nil
+}
+
+func (x *Installation) GetStatus() *InstallationStatus {
+ if x != nil {
+ return x.Status
+ }
+ return nil
+}
+
+func (x *Installation) GetCalculated() *Calculated {
+ if x != nil {
+ return x.Calculated
+ }
+ return nil
+}
+
+// Installations
+type ListInstallationsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Namespace *string `protobuf:"bytes,2,opt,name=namespace,proto3,oneof" json:"namespace,omitempty"`
+ Limit *int64 `protobuf:"varint,3,opt,name=limit,proto3,oneof" json:"limit,omitempty"`
+ Skip *int64 `protobuf:"varint,4,opt,name=skip,proto3,oneof" json:"skip,omitempty"`
+ Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ AllNamespaces *bool `protobuf:"varint,6,opt,name=allNamespaces,proto3,oneof" json:"allNamespaces,omitempty"`
+}
+
+func (x *ListInstallationsRequest) Reset() {
+ *x = ListInstallationsRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListInstallationsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListInstallationsRequest) ProtoMessage() {}
+
+func (x *ListInstallationsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[4]
+ 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 ListInstallationsRequest.ProtoReflect.Descriptor instead.
+func (*ListInstallationsRequest) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ListInstallationsRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *ListInstallationsRequest) GetNamespace() string {
+ if x != nil && x.Namespace != nil {
+ return *x.Namespace
+ }
+ return ""
+}
+
+func (x *ListInstallationsRequest) GetLimit() int64 {
+ if x != nil && x.Limit != nil {
+ return *x.Limit
+ }
+ return 0
+}
+
+func (x *ListInstallationsRequest) GetSkip() int64 {
+ if x != nil && x.Skip != nil {
+ return *x.Skip
+ }
+ return 0
+}
+
+func (x *ListInstallationsRequest) GetLabels() map[string]string {
+ if x != nil {
+ return x.Labels
+ }
+ return nil
+}
+
+func (x *ListInstallationsRequest) GetAllNamespaces() bool {
+ if x != nil && x.AllNamespaces != nil {
+ return *x.AllNamespaces
+ }
+ return false
+}
+
+type ListInstallationsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Installation []*Installation `protobuf:"bytes,1,rep,name=installation,proto3" json:"installation,omitempty"`
+}
+
+func (x *ListInstallationsResponse) Reset() {
+ *x = ListInstallationsResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListInstallationsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListInstallationsResponse) ProtoMessage() {}
+
+func (x *ListInstallationsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[5]
+ 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 ListInstallationsResponse.ProtoReflect.Descriptor instead.
+func (*ListInstallationsResponse) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ListInstallationsResponse) GetInstallation() []*Installation {
+ if x != nil {
+ return x.Installation
+ }
+ return nil
+}
+
+// InstallationRuns
+type InstallationRun struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ Bundle string `protobuf:"bytes,2,opt,name=bundle,proto3" json:"bundle,omitempty"`
+ Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`
+ Action string `protobuf:"bytes,4,opt,name=action,proto3" json:"action,omitempty"`
+ Paramters map[string]string `protobuf:"bytes,5,rep,name=paramters,proto3" json:"paramters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ Started *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=started,proto3" json:"started,omitempty"`
+ Stopped *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=stopped,proto3" json:"stopped,omitempty"`
+ Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"`
+}
+
+func (x *InstallationRun) Reset() {
+ *x = InstallationRun{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *InstallationRun) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*InstallationRun) ProtoMessage() {}
+
+func (x *InstallationRun) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[6]
+ 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 InstallationRun.ProtoReflect.Descriptor instead.
+func (*InstallationRun) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *InstallationRun) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *InstallationRun) GetBundle() string {
+ if x != nil {
+ return x.Bundle
+ }
+ return ""
+}
+
+func (x *InstallationRun) GetVersion() string {
+ if x != nil {
+ return x.Version
+ }
+ return ""
+}
+
+func (x *InstallationRun) GetAction() string {
+ if x != nil {
+ return x.Action
+ }
+ return ""
+}
+
+func (x *InstallationRun) GetParamters() map[string]string {
+ if x != nil {
+ return x.Paramters
+ }
+ return nil
+}
+
+func (x *InstallationRun) GetStarted() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Started
+ }
+ return nil
+}
+
+func (x *InstallationRun) GetStopped() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Stopped
+ }
+ return nil
+}
+
+func (x *InstallationRun) GetStatus() string {
+ if x != nil {
+ return x.Status
+ }
+ return ""
+}
+
+type ListInstallationRunsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Installation *Installation `protobuf:"bytes,1,opt,name=installation,proto3" json:"installation,omitempty"`
+}
+
+func (x *ListInstallationRunsRequest) Reset() {
+ *x = ListInstallationRunsRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListInstallationRunsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListInstallationRunsRequest) ProtoMessage() {}
+
+func (x *ListInstallationRunsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[7]
+ 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 ListInstallationRunsRequest.ProtoReflect.Descriptor instead.
+func (*ListInstallationRunsRequest) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ListInstallationRunsRequest) GetInstallation() *Installation {
+ if x != nil {
+ return x.Installation
+ }
+ return nil
+}
+
+type ListInstallationRunsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Run []*InstallationRun `protobuf:"bytes,1,rep,name=run,proto3" json:"run,omitempty"`
+}
+
+func (x *ListInstallationRunsResponse) Reset() {
+ *x = ListInstallationRunsResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListInstallationRunsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListInstallationRunsResponse) ProtoMessage() {}
+
+func (x *ListInstallationRunsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[8]
+ 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 ListInstallationRunsResponse.ProtoReflect.Descriptor instead.
+func (*ListInstallationRunsResponse) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *ListInstallationRunsResponse) GetRun() []*InstallationRun {
+ if x != nil {
+ return x.Run
+ }
+ return nil
+}
+
+type PorterValue struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
+ Sensitive bool `protobuf:"varint,3,opt,name=sensitive,proto3" json:"sensitive,omitempty"`
+ Value *structpb.Value `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (x *PorterValue) Reset() {
+ *x = PorterValue{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PorterValue) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PorterValue) ProtoMessage() {}
+
+func (x *PorterValue) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_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 PorterValue.ProtoReflect.Descriptor instead.
+func (*PorterValue) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *PorterValue) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *PorterValue) GetType() string {
+ if x != nil {
+ return x.Type
+ }
+ return ""
+}
+
+func (x *PorterValue) GetSensitive() bool {
+ if x != nil {
+ return x.Sensitive
+ }
+ return false
+}
+
+func (x *PorterValue) GetValue() *structpb.Value {
+ if x != nil {
+ return x.Value
+ }
+ return nil
+}
+
+type InstallationOutputs struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Output []*PorterValue `protobuf:"bytes,1,rep,name=output,proto3" json:"output,omitempty"`
+}
+
+func (x *InstallationOutputs) Reset() {
+ *x = InstallationOutputs{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *InstallationOutputs) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*InstallationOutputs) ProtoMessage() {}
+
+func (x *InstallationOutputs) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[10]
+ 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 InstallationOutputs.ProtoReflect.Descriptor instead.
+func (*InstallationOutputs) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *InstallationOutputs) GetOutput() []*PorterValue {
+ if x != nil {
+ return x.Output
+ }
+ return nil
+}
+
+type ListInstallationLatestOutputRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Namespace *string `protobuf:"bytes,2,opt,name=namespace,proto3,oneof" json:"namespace,omitempty"`
+}
+
+func (x *ListInstallationLatestOutputRequest) Reset() {
+ *x = ListInstallationLatestOutputRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListInstallationLatestOutputRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListInstallationLatestOutputRequest) ProtoMessage() {}
+
+func (x *ListInstallationLatestOutputRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[11]
+ 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 ListInstallationLatestOutputRequest.ProtoReflect.Descriptor instead.
+func (*ListInstallationLatestOutputRequest) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *ListInstallationLatestOutputRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *ListInstallationLatestOutputRequest) GetNamespace() string {
+ if x != nil && x.Namespace != nil {
+ return *x.Namespace
+ }
+ return ""
+}
+
+// InstallationRunOutputs
+type ListInstallationLatestOutputResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Outputs []*PorterValue `protobuf:"bytes,1,rep,name=outputs,proto3" json:"outputs,omitempty"`
+}
+
+func (x *ListInstallationLatestOutputResponse) Reset() {
+ *x = ListInstallationLatestOutputResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListInstallationLatestOutputResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListInstallationLatestOutputResponse) ProtoMessage() {}
+
+func (x *ListInstallationLatestOutputResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_installation_v1alpha1_installation_proto_msgTypes[12]
+ 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 ListInstallationLatestOutputResponse.ProtoReflect.Descriptor instead.
+func (*ListInstallationLatestOutputResponse) Descriptor() ([]byte, []int) {
+ return file_installation_v1alpha1_installation_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *ListInstallationLatestOutputResponse) GetOutputs() []*PorterValue {
+ if x != nil {
+ return x.Outputs
+ }
+ return nil
+}
+
+var File_installation_v1alpha1_installation_proto protoreflect.FileDescriptor
+
+var file_installation_v1alpha1_installation_proto_rawDesc = []byte{
+ 0x0a, 0x28, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76,
+ 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
+ 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73,
+ 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x42, 0x0a, 0x06, 0x42,
+ 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22,
+ 0xdc, 0x03, 0x0a, 0x12, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06,
+ 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x64,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x64,
+ 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18,
+ 0x05, 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, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x08, 0x6d, 0x6f,
+ 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x06, 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, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18,
+ 0x07, 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, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x3c, 0x0a, 0x0b,
+ 0x75, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x08, 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, 0x75,
+ 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x75,
+ 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72,
+ 0x65, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x65,
+ 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x75, 0x6e,
+ 0x64, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x62, 0x75,
+ 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0c, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0xd2,
+ 0x01, 0x0a, 0x0a, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x12, 0x3a, 0x0a,
+ 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x64, 0x69, 0x73,
+ 0x70, 0x6c, 0x61, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x64, 0x69,
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4a, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c,
+ 0x76, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
+ 0x12, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
+ 0x65, 0x72, 0x73, 0x22, 0xa2, 0x03, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65,
+ 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x63, 0x68,
+ 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c,
+ 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x06,
+ 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69,
+ 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c,
+ 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, 0x62, 0x75, 0x6e,
+ 0x64, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
+ 0x6c, 0x53, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x72, 0x65,
+ 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x65, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x70,
+ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x65, 0x74,
+ 0x73, 0x12, 0x41, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x29, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+ 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74,
+ 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61,
+ 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
+ 0x2e, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52, 0x0b, 0x5f, 0x63, 0x61,
+ 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x22, 0xf3, 0x02, 0x0a, 0x18, 0x4c, 0x69, 0x73,
+ 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x09, 0x6e, 0x61, 0x6d,
+ 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09,
+ 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05,
+ 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x05, 0x6c,
+ 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x73, 0x6b, 0x69, 0x70, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x04, 0x73, 0x6b, 0x69, 0x70, 0x88, 0x01, 0x01,
+ 0x12, 0x53, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x3b, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c,
+ 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x29, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x0d,
+ 0x61, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x88, 0x01, 0x01,
+ 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6c, 0x69,
+ 0x6d, 0x69, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x10, 0x0a, 0x0e,
+ 0x5f, 0x61, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x22, 0x64,
+ 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x69,
+ 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+ 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x82, 0x03, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x6e, 0x64,
+ 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65,
+ 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x74, 0x65, 0x72, 0x73, 0x18,
+ 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e,
+ 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x2e, 0x50, 0x61,
+ 0x72, 0x61, 0x6d, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x70, 0x61,
+ 0x72, 0x61, 0x6d, 0x74, 0x65, 0x72, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x65, 0x64, 0x18, 0x06, 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, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x34, 0x0a,
+ 0x07, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x18, 0x07, 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, 0x07, 0x73, 0x74, 0x6f, 0x70,
+ 0x70, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x3c, 0x0a, 0x0e, 0x50,
+ 0x61, 0x72, 0x61, 0x6d, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
+ 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
+ 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x66, 0x0a, 0x1b, 0x4c, 0x69, 0x73,
+ 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e,
+ 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x0c, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
+ 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
+ 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x22, 0x58, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x12, 0x38, 0x0a, 0x03, 0x72, 0x75, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26,
+ 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
+ 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x52, 0x03, 0x72, 0x75, 0x6e, 0x22, 0x81, 0x01, 0x0a, 0x0b,
+ 0x50, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+ 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
+ 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76,
+ 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+ 0x51, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f,
+ 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50,
+ 0x6f, 0x72, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70,
+ 0x75, 0x74, 0x22, 0x6a, 0x0a, 0x23, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+ 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x70,
+ 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a,
+ 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x48, 0x00, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x88, 0x01, 0x01,
+ 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x64,
+ 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+ 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
+ 0x50, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74,
+ 0x70, 0x75, 0x74, 0x73, 0x42, 0xfc, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
+ 0x61, 0x31, 0x42, 0x11, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x57, 0x67, 0x65, 0x74, 0x2e, 0x70, 0x6f, 0x72,
+ 0x74, 0x65, 0x72, 0x2e, 0x73, 0x68, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x67, 0x65,
+ 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x65,
+ 0x72, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
+ 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x15, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02,
+ 0x15, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31,
+ 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x21, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47,
+ 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x49, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70,
+ 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_installation_v1alpha1_installation_proto_rawDescOnce sync.Once
+ file_installation_v1alpha1_installation_proto_rawDescData = file_installation_v1alpha1_installation_proto_rawDesc
+)
+
+func file_installation_v1alpha1_installation_proto_rawDescGZIP() []byte {
+ file_installation_v1alpha1_installation_proto_rawDescOnce.Do(func() {
+ file_installation_v1alpha1_installation_proto_rawDescData = protoimpl.X.CompressGZIP(file_installation_v1alpha1_installation_proto_rawDescData)
+ })
+ return file_installation_v1alpha1_installation_proto_rawDescData
+}
+
+var file_installation_v1alpha1_installation_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
+var file_installation_v1alpha1_installation_proto_goTypes = []interface{}{
+ (*Bundle)(nil), // 0: installation.v1alpha1.Bundle
+ (*InstallationStatus)(nil), // 1: installation.v1alpha1.InstallationStatus
+ (*Calculated)(nil), // 2: installation.v1alpha1.Calculated
+ (*Installation)(nil), // 3: installation.v1alpha1.Installation
+ (*ListInstallationsRequest)(nil), // 4: installation.v1alpha1.ListInstallationsRequest
+ (*ListInstallationsResponse)(nil), // 5: installation.v1alpha1.ListInstallationsResponse
+ (*InstallationRun)(nil), // 6: installation.v1alpha1.InstallationRun
+ (*ListInstallationRunsRequest)(nil), // 7: installation.v1alpha1.ListInstallationRunsRequest
+ (*ListInstallationRunsResponse)(nil), // 8: installation.v1alpha1.ListInstallationRunsResponse
+ (*PorterValue)(nil), // 9: installation.v1alpha1.PorterValue
+ (*InstallationOutputs)(nil), // 10: installation.v1alpha1.InstallationOutputs
+ (*ListInstallationLatestOutputRequest)(nil), // 11: installation.v1alpha1.ListInstallationLatestOutputRequest
+ (*ListInstallationLatestOutputResponse)(nil), // 12: installation.v1alpha1.ListInstallationLatestOutputResponse
+ nil, // 13: installation.v1alpha1.ListInstallationsRequest.LabelsEntry
+ nil, // 14: installation.v1alpha1.InstallationRun.ParamtersEntry
+ (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
+ (structpb.NullValue)(0), // 16: google.protobuf.NullValue
+ (*structpb.Value)(nil), // 17: google.protobuf.Value
+}
+var file_installation_v1alpha1_installation_proto_depIdxs = []int32{
+ 15, // 0: installation.v1alpha1.InstallationStatus.created:type_name -> google.protobuf.Timestamp
+ 15, // 1: installation.v1alpha1.InstallationStatus.modified:type_name -> google.protobuf.Timestamp
+ 15, // 2: installation.v1alpha1.InstallationStatus.installed:type_name -> google.protobuf.Timestamp
+ 15, // 3: installation.v1alpha1.InstallationStatus.uninstalled:type_name -> google.protobuf.Timestamp
+ 16, // 4: installation.v1alpha1.Calculated.resolvedParameters:type_name -> google.protobuf.NullValue
+ 0, // 5: installation.v1alpha1.Installation.bundle:type_name -> installation.v1alpha1.Bundle
+ 1, // 6: installation.v1alpha1.Installation.status:type_name -> installation.v1alpha1.InstallationStatus
+ 2, // 7: installation.v1alpha1.Installation.calculated:type_name -> installation.v1alpha1.Calculated
+ 13, // 8: installation.v1alpha1.ListInstallationsRequest.labels:type_name -> installation.v1alpha1.ListInstallationsRequest.LabelsEntry
+ 3, // 9: installation.v1alpha1.ListInstallationsResponse.installation:type_name -> installation.v1alpha1.Installation
+ 14, // 10: installation.v1alpha1.InstallationRun.paramters:type_name -> installation.v1alpha1.InstallationRun.ParamtersEntry
+ 15, // 11: installation.v1alpha1.InstallationRun.started:type_name -> google.protobuf.Timestamp
+ 15, // 12: installation.v1alpha1.InstallationRun.stopped:type_name -> google.protobuf.Timestamp
+ 3, // 13: installation.v1alpha1.ListInstallationRunsRequest.installation:type_name -> installation.v1alpha1.Installation
+ 6, // 14: installation.v1alpha1.ListInstallationRunsResponse.run:type_name -> installation.v1alpha1.InstallationRun
+ 17, // 15: installation.v1alpha1.PorterValue.value:type_name -> google.protobuf.Value
+ 9, // 16: installation.v1alpha1.InstallationOutputs.output:type_name -> installation.v1alpha1.PorterValue
+ 9, // 17: installation.v1alpha1.ListInstallationLatestOutputResponse.outputs:type_name -> installation.v1alpha1.PorterValue
+ 18, // [18:18] is the sub-list for method output_type
+ 18, // [18:18] is the sub-list for method input_type
+ 18, // [18:18] is the sub-list for extension type_name
+ 18, // [18:18] is the sub-list for extension extendee
+ 0, // [0:18] is the sub-list for field type_name
+}
+
+func init() { file_installation_v1alpha1_installation_proto_init() }
+func file_installation_v1alpha1_installation_proto_init() {
+ if File_installation_v1alpha1_installation_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_installation_v1alpha1_installation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Bundle); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*InstallationStatus); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Calculated); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Installation); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListInstallationsRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListInstallationsResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*InstallationRun); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListInstallationRunsRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListInstallationRunsResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PorterValue); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*InstallationOutputs); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListInstallationLatestOutputRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListInstallationLatestOutputResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ file_installation_v1alpha1_installation_proto_msgTypes[4].OneofWrappers = []interface{}{}
+ file_installation_v1alpha1_installation_proto_msgTypes[11].OneofWrappers = []interface{}{}
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_installation_v1alpha1_installation_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 15,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_installation_v1alpha1_installation_proto_goTypes,
+ DependencyIndexes: file_installation_v1alpha1_installation_proto_depIdxs,
+ MessageInfos: file_installation_v1alpha1_installation_proto_msgTypes,
+ }.Build()
+ File_installation_v1alpha1_installation_proto = out.File
+ file_installation_v1alpha1_installation_proto_rawDesc = nil
+ file_installation_v1alpha1_installation_proto_goTypes = nil
+ file_installation_v1alpha1_installation_proto_depIdxs = nil
+}
diff --git a/gen/proto/go/porterapis/porter/v1alpha1/porter.pb.go b/gen/proto/go/porterapis/porter/v1alpha1/porter.pb.go
new file mode 100644
index 000000000..5e7c10a57
--- /dev/null
+++ b/gen/proto/go/porterapis/porter/v1alpha1/porter.pb.go
@@ -0,0 +1,108 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc (unknown)
+// source: porter/v1alpha1/porter.proto
+
+//option go_package = "get.porter.sh/porter/gen/proto/go/installation/v1alpha1";
+
+package porterv1alpha1
+
+import (
+ v1alpha1 "get.porter.sh/porter/gen/proto/go/porterapis/installation/v1alpha1"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+)
+
+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)
+)
+
+var File_porter_v1alpha1_porter_proto protoreflect.FileDescriptor
+
+var file_porter_v1alpha1_porter_proto_rawDesc = []byte{
+ 0x0a, 0x1c, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
+ 0x31, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+ 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a,
+ 0x28, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31,
+ 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x9f, 0x02, 0x0a, 0x06, 0x50, 0x6f,
+ 0x72, 0x74, 0x65, 0x72, 0x12, 0x78, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74,
+ 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2f, 0x2e, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
+ 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x69, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
+ 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x9a,
+ 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73,
+ 0x12, 0x3a, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4f,
+ 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x69,
+ 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c,
+ 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75,
+ 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xcc, 0x01, 0x0a, 0x13,
+ 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
+ 0x68, 0x61, 0x31, 0x42, 0x0b, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+ 0x50, 0x01, 0x5a, 0x4b, 0x67, 0x65, 0x74, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x73,
+ 0x68, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x61, 0x70, 0x69, 0x73,
+ 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
+ 0x3b, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2,
+ 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0f, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x56,
+ 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x0f, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x72,
+ 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1b, 0x50, 0x6f, 0x72, 0x74,
+ 0x65, 0x72, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x72,
+ 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x33,
+}
+
+var file_porter_v1alpha1_porter_proto_goTypes = []interface{}{
+ (*v1alpha1.ListInstallationsRequest)(nil), // 0: installation.v1alpha1.ListInstallationsRequest
+ (*v1alpha1.ListInstallationLatestOutputRequest)(nil), // 1: installation.v1alpha1.ListInstallationLatestOutputRequest
+ (*v1alpha1.ListInstallationsResponse)(nil), // 2: installation.v1alpha1.ListInstallationsResponse
+ (*v1alpha1.ListInstallationLatestOutputResponse)(nil), // 3: installation.v1alpha1.ListInstallationLatestOutputResponse
+}
+var file_porter_v1alpha1_porter_proto_depIdxs = []int32{
+ 0, // 0: porter.v1alpha1.Porter.ListInstallations:input_type -> installation.v1alpha1.ListInstallationsRequest
+ 1, // 1: porter.v1alpha1.Porter.ListInstallationLatestOutputs:input_type -> installation.v1alpha1.ListInstallationLatestOutputRequest
+ 2, // 2: porter.v1alpha1.Porter.ListInstallations:output_type -> installation.v1alpha1.ListInstallationsResponse
+ 3, // 3: porter.v1alpha1.Porter.ListInstallationLatestOutputs:output_type -> installation.v1alpha1.ListInstallationLatestOutputResponse
+ 2, // [2:4] is the sub-list for method output_type
+ 0, // [0:2] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_porter_v1alpha1_porter_proto_init() }
+func file_porter_v1alpha1_porter_proto_init() {
+ if File_porter_v1alpha1_porter_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_porter_v1alpha1_porter_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 0,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_porter_v1alpha1_porter_proto_goTypes,
+ DependencyIndexes: file_porter_v1alpha1_porter_proto_depIdxs,
+ }.Build()
+ File_porter_v1alpha1_porter_proto = out.File
+ file_porter_v1alpha1_porter_proto_rawDesc = nil
+ file_porter_v1alpha1_porter_proto_goTypes = nil
+ file_porter_v1alpha1_porter_proto_depIdxs = nil
+}
diff --git a/gen/proto/go/porterapis/porter/v1alpha1/porter_grpc.pb.go b/gen/proto/go/porterapis/porter/v1alpha1/porter_grpc.pb.go
new file mode 100644
index 000000000..9b91558a2
--- /dev/null
+++ b/gen/proto/go/porterapis/porter/v1alpha1/porter_grpc.pb.go
@@ -0,0 +1,146 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc (unknown)
+// source: porter/v1alpha1/porter.proto
+
+package porterv1alpha1
+
+import (
+ context "context"
+ v1alpha1 "get.porter.sh/porter/gen/proto/go/porterapis/installation/v1alpha1"
+ 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
+
+// PorterClient is the client API for Porter 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 PorterClient interface {
+ // Returns a list of all installations
+ ListInstallations(ctx context.Context, in *v1alpha1.ListInstallationsRequest, opts ...grpc.CallOption) (*v1alpha1.ListInstallationsResponse, error)
+ // Returns a list of all outputs for the latest installation run
+ ListInstallationLatestOutputs(ctx context.Context, in *v1alpha1.ListInstallationLatestOutputRequest, opts ...grpc.CallOption) (*v1alpha1.ListInstallationLatestOutputResponse, error)
+}
+
+type porterClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewPorterClient(cc grpc.ClientConnInterface) PorterClient {
+ return &porterClient{cc}
+}
+
+func (c *porterClient) ListInstallations(ctx context.Context, in *v1alpha1.ListInstallationsRequest, opts ...grpc.CallOption) (*v1alpha1.ListInstallationsResponse, error) {
+ out := new(v1alpha1.ListInstallationsResponse)
+ err := c.cc.Invoke(ctx, "/porter.v1alpha1.Porter/ListInstallations", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *porterClient) ListInstallationLatestOutputs(ctx context.Context, in *v1alpha1.ListInstallationLatestOutputRequest, opts ...grpc.CallOption) (*v1alpha1.ListInstallationLatestOutputResponse, error) {
+ out := new(v1alpha1.ListInstallationLatestOutputResponse)
+ err := c.cc.Invoke(ctx, "/porter.v1alpha1.Porter/ListInstallationLatestOutputs", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// PorterServer is the server API for Porter service.
+// All implementations must embed UnimplementedPorterServer
+// for forward compatibility
+type PorterServer interface {
+ // Returns a list of all installations
+ ListInstallations(context.Context, *v1alpha1.ListInstallationsRequest) (*v1alpha1.ListInstallationsResponse, error)
+ // Returns a list of all outputs for the latest installation run
+ ListInstallationLatestOutputs(context.Context, *v1alpha1.ListInstallationLatestOutputRequest) (*v1alpha1.ListInstallationLatestOutputResponse, error)
+ mustEmbedUnimplementedPorterServer()
+}
+
+// UnimplementedPorterServer must be embedded to have forward compatible implementations.
+type UnimplementedPorterServer struct {
+}
+
+func (UnimplementedPorterServer) ListInstallations(context.Context, *v1alpha1.ListInstallationsRequest) (*v1alpha1.ListInstallationsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListInstallations not implemented")
+}
+func (UnimplementedPorterServer) ListInstallationLatestOutputs(context.Context, *v1alpha1.ListInstallationLatestOutputRequest) (*v1alpha1.ListInstallationLatestOutputResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListInstallationLatestOutputs not implemented")
+}
+func (UnimplementedPorterServer) mustEmbedUnimplementedPorterServer() {}
+
+// UnsafePorterServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to PorterServer will
+// result in compilation errors.
+type UnsafePorterServer interface {
+ mustEmbedUnimplementedPorterServer()
+}
+
+func RegisterPorterServer(s grpc.ServiceRegistrar, srv PorterServer) {
+ s.RegisterService(&Porter_ServiceDesc, srv)
+}
+
+func _Porter_ListInstallations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(v1alpha1.ListInstallationsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(PorterServer).ListInstallations(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/porter.v1alpha1.Porter/ListInstallations",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(PorterServer).ListInstallations(ctx, req.(*v1alpha1.ListInstallationsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Porter_ListInstallationLatestOutputs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(v1alpha1.ListInstallationLatestOutputRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(PorterServer).ListInstallationLatestOutputs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/porter.v1alpha1.Porter/ListInstallationLatestOutputs",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(PorterServer).ListInstallationLatestOutputs(ctx, req.(*v1alpha1.ListInstallationLatestOutputRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// Porter_ServiceDesc is the grpc.ServiceDesc for Porter service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Porter_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "porter.v1alpha1.Porter",
+ HandlerType: (*PorterServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "ListInstallations",
+ Handler: _Porter_ListInstallations_Handler,
+ },
+ {
+ MethodName: "ListInstallationLatestOutputs",
+ Handler: _Porter_ListInstallationLatestOutputs_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "porter/v1alpha1/porter.proto",
+}
diff --git a/go.mod b/go.mod
index 739df6df6..5c6c56a99 100644
--- a/go.mod
+++ b/go.mod
@@ -33,8 +33,10 @@ require (
github.com/dustin/go-humanize v1.0.1
github.com/ghodss/yaml v1.0.0
github.com/google/go-cmp v0.5.9
- github.com/google/go-containerregistry v0.13.0
+ github.com/google/go-containerregistry v0.15.2
+ github.com/google/uuid v1.3.0
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
+ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/hashicorp/go-hclog v1.5.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-plugin v1.4.0
@@ -45,16 +47,19 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/mmcdole/gofeed v1.2.1
github.com/moby/buildkit v0.11.5
- github.com/moby/term v0.0.0-20221120202655-abb19827d345
+ github.com/moby/term v0.0.0-20221205130635-1aeaba878587
github.com/olekukonko/tablewriter v0.0.5
github.com/opencontainers/go-digest v1.0.0
github.com/osteele/liquid v1.3.0
github.com/pelletier/go-toml v1.9.5
+ github.com/prometheus/client_golang v1.14.0
github.com/spf13/afero v1.9.5
- github.com/spf13/cobra v1.6.1
+ github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.14.0
github.com/stretchr/testify v1.8.2
+ github.com/tidwall/gjson v1.14.4
+ github.com/tidwall/sjson v1.2.5
github.com/xeipuuv/gojsonschema v1.2.0
go.mongodb.org/mongo-driver v1.11.4
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.40.0
@@ -72,13 +77,14 @@ require (
gopkg.in/AlecAivazis/survey.v1 v1.8.8
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
gopkg.in/yaml.v3 v3.0.1
+ k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5
)
require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
- github.com/Microsoft/go-winio v0.6.0 // indirect
+ github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/PaesslerAG/gval v1.0.0 // indirect
github.com/PuerkitoBio/goquery v1.8.0 // indirect
github.com/Shopify/logrus-bugsnag v0.0.0-20230117174420-439a4b8ba167 // indirect
@@ -146,7 +152,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/klauspost/compress v1.16.0 // indirect
+ github.com/klauspost/compress v1.16.5 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kr/pty v1.1.5 // indirect
github.com/magiconair/properties v1.8.1 // indirect
@@ -175,13 +181,12 @@ require (
github.com/nxadm/tail v1.4.8 // indirect
github.com/oklog/run v1.0.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
- github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
+ github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/osteele/tuesday v1.0.3 // indirect
github.com/pierrec/lz4/v4 v4.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
@@ -193,11 +198,13 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/theupdateframework/notary v0.6.1 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
- github.com/vbatts/tar-split v0.11.2 // indirect
+ github.com/vbatts/tar-split v0.11.3 // indirect
github.com/weppos/publicsuffix-go v0.5.0 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
@@ -216,14 +223,14 @@ require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.2.0 // indirect
- golang.org/x/mod v0.9.0 // indirect
- golang.org/x/net v0.8.0 // indirect
- golang.org/x/oauth2 v0.6.0 // indirect
+ golang.org/x/mod v0.10.0 // indirect
+ golang.org/x/net v0.9.0 // indirect
+ golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sys v0.7.0 // indirect
- golang.org/x/term v0.6.0 // indirect
- golang.org/x/text v0.8.0 // indirect
+ golang.org/x/term v0.7.0 // indirect
+ golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.1.0 // indirect
- golang.org/x/tools v0.7.0 // indirect
+ golang.org/x/tools v0.8.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
@@ -235,8 +242,9 @@ require (
k8s.io/client-go v0.26.2 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
- k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
+
+//replace get.porter.sh/magefiles v0.3.3 => ../magefiles
diff --git a/go.sum b/go.sum
index 935073272..5e4173dbc 100644
--- a/go.sum
+++ b/go.sum
@@ -25,7 +25,7 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
+cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
@@ -52,6 +52,7 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
@@ -60,8 +61,8 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
-github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
-github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.10.0-rc.7 h1:HBytQPxcv8Oy4244zbQbe6hnOnx544eL5QPUqhJldz8=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
@@ -210,7 +211,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 h1:vU+EP9ZuFUCYE0NYLwTSob+3LNEJATzNfP/DC7SWGWI=
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
@@ -395,8 +396,8 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.0.0-20191015185424-71da34e4d9b3/go.mod h1:ZXFeSndFcK4vB1NR4voH1Zm38K7ViUNiYtfIBDxrwf0=
-github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k=
-github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo=
+github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
+github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -420,6 +421,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
@@ -437,6 +439,7 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
@@ -485,7 +488,6 @@ github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
@@ -526,8 +528,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
-github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
+github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@@ -627,8 +629,8 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
-github.com/moby/term v0.0.0-20221120202655-abb19827d345 h1:J9c53/kxIH+2nTKBEfZYFMlhghtHpIHSXpm5VRGHSnU=
-github.com/moby/term v0.0.0-20221120202655-abb19827d345/go.mod h1:15ce4BGCFxt7I5NQKT+HV0yEDxmf6fSysfEDiVo3zFM=
+github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
+github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -679,8 +681,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
-github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
+github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
+github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -788,7 +790,6 @@ github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
-github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@@ -810,8 +811,8 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
-github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@@ -837,6 +838,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
@@ -844,8 +846,16 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/theupdateframework/notary v0.6.1 h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz+cjWoom6l0=
github.com/theupdateframework/notary v0.6.1/go.mod h1:MOfgIfmox8s7/7fduvB2xyPPMJCrjRLRizA8OFwpnKY=
-github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
+github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
+github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa h1:XOFp/3aBXlqmOFAg3r6e0qQjPnK5I970LilqX+Is1W8=
@@ -860,9 +870,9 @@ github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
-github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
+github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
+github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=
+github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/weppos/publicsuffix-go v0.4.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
@@ -1002,8 +1012,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
-golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
+golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1050,8 +1060,8 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1065,8 +1075,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
-golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
+golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
+golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1155,6 +1165,7 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1162,8 +1173,8 @@ golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1173,8 +1184,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1239,8 +1250,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
-golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
+golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
+golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/mage/setup/tools.go b/mage/setup/tools.go
index d19e05dcf..189f78883 100644
--- a/mage/setup/tools.go
+++ b/mage/setup/tools.go
@@ -1,11 +1,23 @@
package setup
import (
+ "os/exec"
+ "runtime"
+
"github.com/carolynvs/magex/mgx"
"github.com/carolynvs/magex/pkg"
+ "github.com/carolynvs/magex/pkg/archive"
+ "github.com/carolynvs/magex/pkg/downloads"
+ "github.com/magefile/mage/mg"
)
func EnsureProtobufTools() {
+ //TODO: add more tools
+ // https://github.com/bufbuild/buf/releases protoc-gen-buf-breaking, protoc-gen-buf-lint
+ // protoc https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-x86_64.zip``
+ //TODO: add more tools
+ // https://github.com/bufbuild/buf/releases protoc-gen-buf-breaking, protoc-gen-buf-lint
+ // protoc https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-x86_64.zip``
mgx.Must(pkg.EnsurePackageWith(pkg.EnsurePackageOptions{
Name: "google.golang.org/protobuf/cmd/protoc-gen-go",
DefaultVersion: "v1.28",
@@ -17,3 +29,67 @@ func EnsureProtobufTools() {
VersionCommand: "--version",
}))
}
+
+// IsCommandInPath determines if a command can be called based on the current PATH.
+func IsCommandInPath(cmd string) (bool, error) {
+ _, err := exec.LookPath(cmd)
+ if err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+func EnsureBufBuild() {
+ mg.Deps(EnsureProtobufTools)
+ if ok, _ := pkg.IsCommandAvailable("buf", "--version", "1.11.0"); ok {
+ return
+ }
+ opts := downloads.DownloadOptions{
+ UrlTemplate: "https://github.com/bufbuild/buf/releases/download/v{{.VERSION}}/buf-{{.GOOS}}-{{.GOARCH}}{{.EXT}}",
+ Name: "buf",
+ Version: "1.11.0",
+ OsReplacement: map[string]string{
+ "darwin": "Darwin",
+ "linux": "Linux",
+ "windows": "Windows",
+ },
+ ArchReplacement: map[string]string{
+ "amd64": "x86_64",
+ },
+ }
+ err := downloads.DownloadToGopathBin(opts)
+ mgx.Must(err)
+}
+
+func EnsureGRPCurl() {
+ if ok, _ := IsCommandInPath("grpcurl"); ok {
+ return
+ }
+
+ target := "grpcurl{{.EXT}}"
+ if runtime.GOOS == "windows" {
+ target = "grpcurl.exe"
+ }
+
+ opts := archive.DownloadArchiveOptions{
+ DownloadOptions: downloads.DownloadOptions{
+ UrlTemplate: "https://github.com/fullstorydev/grpcurl/releases/download/v{{.VERSION}}/grpcurl_{{.VERSION}}_{{.GOOS}}_{{.GOARCH}}{{.EXT}}",
+ Name: "grpcurl",
+ Version: "1.8.7",
+ OsReplacement: map[string]string{
+ "darwin": "osx",
+ },
+ ArchReplacement: map[string]string{
+ "amd64": "x86_64",
+ },
+ },
+ ArchiveExtensions: map[string]string{
+ "linux": ".tar.gz",
+ "darwin": ".tar.gz",
+ "windows": ".zip",
+ },
+ TargetFileTemplate: target,
+ }
+ err := archive.DownloadToGopathBin(opts)
+ mgx.Must(err)
+}
diff --git a/magefile.go b/magefile.go
index d8cf2871b..039261c4d 100644
--- a/magefile.go
+++ b/magefile.go
@@ -56,6 +56,12 @@ func CheckGoVersion() {
tools.EnforceGoVersion(GoVersion)
}
+func GenerateGRPCProtobufs() {
+ mg.Deps(setup.EnsureBufBuild)
+ must.Command("buf", "build").In("proto").RunV()
+ must.Command("buf", "generate").In("proto").RunV()
+}
+
// Builds all code artifacts in the repository
func Build() {
mg.SerialDeps(InstallBuildTools, BuildPorter, BuildExecMixin, BuildAgent, DocsGen)
@@ -63,7 +69,7 @@ func Build() {
}
func InstallBuildTools() {
- mg.Deps(setup.EnsureProtobufTools)
+ mg.Deps(setup.EnsureProtobufTools, setup.EnsureGRPCurl, setup.EnsureBufBuild)
}
// Build the porter client and runtime
@@ -73,6 +79,38 @@ func BuildPorter() {
mgx.Must(releases.BuildAll(PKG, "porter", "bin"))
}
+// TODO: add support to decouple dir and command name to magefile repo
+// TODO: add support for additional ldflags to magefile repo
+// Build the porter client and runtime with gRPC server enabled
+func XBuildPorterGRPCServer() {
+ var g errgroup.Group
+ supportedClientGOOS := []string{"linux", "darwin", "windows"}
+ supportedClientGOARCH := []string{"amd64", "arm64"}
+ srcCmd := "porter"
+ srcPath := "./cmd/" + srcCmd
+ outPath := "bin/dev"
+ info := releases.LoadMetadata()
+ ldflags := fmt.Sprintf("-w -X main.includeGRPCServer=true -X %s/pkg.Version=%s -X %s/pkg.Commit=%s", PKG, info.Version, PKG, info.Commit)
+ os.MkdirAll(filepath.Dir(outPath), 0770)
+ for _, goos := range supportedClientGOOS {
+ goos := goos
+ for _, goarch := range supportedClientGOARCH {
+ goarch := goarch
+ g.Go(func() error {
+ cmdName := fmt.Sprintf("%s-api-server-%s-%s", srcCmd, goos, goarch)
+ if goos == "windows" {
+ cmdName = cmdName + ".exe"
+ }
+ out := filepath.Join(outPath, cmdName)
+ return shx.Command("go", "build", "-ldflags", ldflags, "-o", out, srcPath).
+ Env("CGO_ENABLED=0", "GO111MODULE=on", "GOOS="+goos, "GOARCH="+goarch).
+ RunV()
+ })
+ }
+ }
+ mgx.Must(g.Wait())
+}
+
func copySchema() {
// Copy the porter manifest schema into our templates directory with the other schema
// We can't use symbolic links because that doesn't work on windows
@@ -95,9 +133,16 @@ func BuildAgent() {
releases.XBuild(PKG, "agent", "bin", "linux", "amd64")
}
+// Cross compile agent for multiple archs in linux
+func XBuildAgent() {
+ mg.Deps(BuildAgent)
+ releases.XBuild(PKG, "agent", "bin", "linux", "arm64")
+}
+
// Cross-compile porter and the exec mixin
func XBuildAll() {
- mg.Deps(XBuildPorter, XBuildMixins, BuildAgent)
+ mg.Deps(XBuildPorter, XBuildMixins, XBuildAgent)
+ mg.SerialDeps(XBuildPorterGRPCServer)
}
// Cross-compile porter
@@ -251,6 +296,21 @@ func TestSmoke() error {
return shx.Command("go", "test", "-count=1", "-timeout=20m", "-tags", "smoke", v, "./tests/smoke/...").CollapseArgs().RunV()
}
+// Run grpc service tests
+func TestGRPCService() {
+ var run string
+ runTest := os.Getenv("PORTER_RUN_TEST")
+ if runTest != "" {
+ run = "-run=" + runTest
+ }
+
+ verbose := ""
+ if mg.Verbose() {
+ verbose = "-v"
+ }
+ must.Command("go", "test", verbose, "-timeout=5m", run, "./tests/grpc/...").CollapseArgs().RunV()
+}
+
func getRegistry() string {
registry := os.Getenv("PORTER_REGISTRY")
if registry == "" {
@@ -266,6 +326,22 @@ func BuildImages() {
buildImages(registry, info)
}
+func buildGRPCProtocImage() {
+ var g errgroup.Group
+
+ enableBuildKit := "DOCKER_BUILDKIT=1"
+ g.Go(func() error {
+ img := "protoc:local"
+ err := shx.Command("docker", "build", "-t", img, "-f", "build/protoc.Dockerfile", ".").
+ Env(enableBuildKit).RunV()
+ if err != nil {
+ return err
+ }
+ return nil
+ })
+ mgx.Must(g.Wait())
+}
+
func buildImages(registry string, info releases.GitMetadata) {
var g errgroup.Group
@@ -304,7 +380,6 @@ func buildImages(registry string, info releases.GitMetadata) {
return shx.Run("docker", "tag", img, fmt.Sprintf("%s/workshop:%s", registry, info.Permalink))
})
-
mgx.Must(g.Wait())
}
@@ -340,6 +415,41 @@ func pushImagesTo(registry string, info releases.GitMetadata) {
}
}
+func PublishServerMultiArchImages() {
+ registry := getRegistry()
+ info := releases.LoadMetadata()
+ buildAndPushServerMultiArch(registry, info)
+}
+
+func buildAndPushServerMultiArch(registry string, info releases.GitMetadata) {
+ img := fmt.Sprintf("%s/server:%s", registry, info.Version)
+ must.RunV("docker", "buildx", "create", "--use")
+ must.RunV("docker", "buildx", "bake", "-f", "docker-bake.json", "--push", "--set", "server.tags="+img, "server")
+}
+
+// Build a local image for the server based off of local architecture
+func BuildLocalServerImage() {
+ registry := getRegistry()
+ info := releases.LoadMetadata()
+ goarch := runtime.GOARCH
+ buildServerImage(registry, info, goarch)
+}
+
+// Builds an image for the server based off of the goarch
+func buildServerImage(registry string, info releases.GitMetadata, goarch string) {
+ var platform string
+ switch goarch {
+ case "arm64":
+ platform = "linux/arm64"
+ case "amd64":
+ platform = "linux/amd64"
+ default:
+ platform = "linux/amd64"
+ }
+ img := fmt.Sprintf("%s/server:%s", registry, info.Version)
+ must.RunV("docker", "build", "-f", "build/images/server/Dockerfile", "-t", img, "--platform="+platform, ".")
+}
+
func pushImages(registry string, tag string) {
pushImage(fmt.Sprintf("%s/porter:%s", registry, tag))
pushImage(fmt.Sprintf("%s/porter-agent:%s", registry, tag))
diff --git a/pkg/grpc/portergrpc/context.go b/pkg/grpc/portergrpc/context.go
new file mode 100644
index 000000000..acd80ba34
--- /dev/null
+++ b/pkg/grpc/portergrpc/context.go
@@ -0,0 +1,28 @@
+package portergrpc
+
+import (
+ "context"
+ "errors"
+
+ "get.porter.sh/porter/pkg/porter"
+)
+
+type ctxKey int
+
+const porterConnCtxKey ctxKey = 0
+
+// GetPorterConnectionFromContext returns the porter connection from the give context.
+// Use AddPorterConnectionToContext to add one.
+func GetPorterConnectionFromContext(ctx context.Context) (*porter.Porter, error) {
+ p, ok := ctx.Value(porterConnCtxKey).(*porter.Porter)
+ if !ok {
+ return nil, errors.New("Unable to find porter connection in context")
+ }
+ return p, nil
+}
+
+// AddPorterConnectionToContext adds the porter connection to the given context
+// use GetPorterConnectionFromContext to read it back out
+func AddPorterConnectionToContext(p *porter.Porter, ctx context.Context) context.Context {
+ return context.WithValue(ctx, porterConnCtxKey, p)
+}
diff --git a/pkg/grpc/portergrpc/context_test.go b/pkg/grpc/portergrpc/context_test.go
new file mode 100644
index 000000000..1502eb07b
--- /dev/null
+++ b/pkg/grpc/portergrpc/context_test.go
@@ -0,0 +1,33 @@
+package portergrpc
+
+import (
+ "context"
+ "testing"
+
+ "get.porter.sh/porter/pkg/porter"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetPorterConnectionFromContextReturnsErrIfNoConnectionInContext(t *testing.T) {
+ ctx := context.Background()
+ p, err := GetPorterConnectionFromContext(ctx)
+ assert.Nil(t, p)
+ assert.EqualError(t, err, "Unable to find porter connection in context")
+}
+
+func TestGetPorterConnectionFromContextReturnsPorterConnection(t *testing.T) {
+ p := porter.New()
+ ctx := context.Background()
+ ctx = context.WithValue(ctx, porterConnCtxKey, p)
+ newP, err := GetPorterConnectionFromContext(ctx)
+ assert.Nil(t, err)
+ assert.Equal(t, p, newP)
+}
+func TestAddPorterConnectionToContextReturnsContextUpdatedWithPorterConnection(t *testing.T) {
+ p := porter.New()
+ ctx := context.Background()
+ ctx = AddPorterConnectionToContext(p, ctx)
+ newP, ok := ctx.Value(porterConnCtxKey).(*porter.Porter)
+ assert.True(t, ok)
+ assert.Equal(t, p, newP)
+}
diff --git a/pkg/grpc/portergrpc/installation.go b/pkg/grpc/portergrpc/installation.go
new file mode 100644
index 000000000..174f0f333
--- /dev/null
+++ b/pkg/grpc/portergrpc/installation.go
@@ -0,0 +1,125 @@
+package portergrpc
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+
+ iGRPCv1alpha1 "get.porter.sh/porter/gen/proto/go/porterapis/installation/v1alpha1"
+ "get.porter.sh/porter/pkg/porter"
+ "get.porter.sh/porter/pkg/tracing"
+ "google.golang.org/protobuf/encoding/protojson"
+)
+
+func newInstallationOptsFromLabels(labels map[string]string) []string {
+ var retLabels []string
+ for k, v := range labels {
+ retLabels = append(retLabels, fmt.Sprintf("%s=%s", k, v))
+ }
+ return retLabels
+}
+
+// populateGRPCInstallation populates a GRPC Installation (generated from protobuf)
+// a native porter DisplayInstallation
+func populateGRPCInstallation(ctx context.Context, inst porter.DisplayInstallation, gInst *iGRPCv1alpha1.Installation) error {
+ _, log := tracing.StartSpan(ctx)
+ defer log.EndSpan()
+ bInst, err := json.Marshal(inst)
+ if err != nil {
+ return log.Errorf("porter.DisplayInstallation marshal error: %e", err)
+ }
+ pjum := protojson.UnmarshalOptions{}
+ err = pjum.Unmarshal(bInst, gInst)
+ if err != nil {
+ return log.Errorf("installation GRPC Installation unmarshal error: %e", err)
+ }
+ return nil
+}
+
+// populateGRPCPorterValue populates a GRPC PorterValue (generated from protobuf)
+// from a native porter DisplayValue
+func populateGRPCPorterValue(ctx context.Context, dv porter.DisplayValue, gInstOut *iGRPCv1alpha1.PorterValue) error {
+ _, log := tracing.StartSpan(ctx)
+ defer log.EndSpan()
+ bInstOut, err := json.Marshal(dv)
+ if err != nil {
+ return log.Errorf("PorterValue marshal error: %e", err)
+ }
+ pjum := protojson.UnmarshalOptions{}
+ err = pjum.Unmarshal(bInstOut, gInstOut)
+ if err != nil {
+ return log.Errorf("installation GRPC InstallationOutputs unmarshal error: %e", err)
+ }
+ return nil
+}
+
+// ListInstallations takes a GRPC ListInstallationsRequest and returns a filtered list of
+// porter installations as a GRPC ListInstallationsResponse
+func (s *PorterServer) ListInstallations(ctx context.Context, req *iGRPCv1alpha1.ListInstallationsRequest) (*iGRPCv1alpha1.ListInstallationsResponse, error) {
+ ctx, log := tracing.StartSpan(ctx)
+ defer log.EndSpan()
+ p, err := GetPorterConnectionFromContext(ctx)
+ // Maybe try to setup a new porter connection instead of erring?
+ if err != nil {
+ return nil, err
+ }
+ opts := porter.ListOptions{
+ Name: req.GetName(),
+ Namespace: req.GetNamespace(),
+ Labels: newInstallationOptsFromLabels(req.GetLabels()),
+ AllNamespaces: req.GetAllNamespaces(),
+ Skip: req.GetSkip(),
+ Limit: req.GetLimit(),
+ }
+ installations, err := p.ListInstallations(ctx, opts)
+ if err != nil {
+ return nil, err
+ }
+ insts := []*iGRPCv1alpha1.Installation{}
+ for _, pInst := range installations {
+ gInst := &iGRPCv1alpha1.Installation{}
+ err := populateGRPCInstallation(ctx, pInst, gInst)
+ if err != nil {
+ return nil, err
+ }
+ insts = append(insts, gInst)
+ }
+ res := iGRPCv1alpha1.ListInstallationsResponse{
+ Installation: insts,
+ }
+ return &res, nil
+}
+
+// ListInstallationLatestOutputs takes a GRPC ListInstallationLatestOutputRequest and returns
+// the most recent outputs for the porter installation as a GRPC ListInstallationLatestOutputResponse
+func (s *PorterServer) ListInstallationLatestOutputs(ctx context.Context, req *iGRPCv1alpha1.ListInstallationLatestOutputRequest) (*iGRPCv1alpha1.ListInstallationLatestOutputResponse, error) {
+ ctx, log := tracing.StartSpan(ctx)
+ defer log.EndSpan()
+ p, err := GetPorterConnectionFromContext(ctx)
+ // Maybe try to setup a new porter connection instead of erring?
+ if err != nil {
+ return nil, err
+ }
+
+ opts := porter.OutputListOptions{}
+ opts.Name = req.GetName()
+ opts.Namespace = req.GetNamespace()
+ opts.Format = "json"
+ pdv, err := p.ListBundleOutputs(ctx, &opts)
+ if err != nil {
+ return nil, err
+ }
+ gInstOuts := []*iGRPCv1alpha1.PorterValue{}
+ for _, dv := range pdv {
+ gInstOut := &iGRPCv1alpha1.PorterValue{}
+ err = populateGRPCPorterValue(ctx, dv, gInstOut)
+ if err != nil {
+ return nil, err
+ }
+ gInstOuts = append(gInstOuts, gInstOut)
+ }
+ res := &iGRPCv1alpha1.ListInstallationLatestOutputResponse{
+ Outputs: gInstOuts,
+ }
+ return res, nil
+}
diff --git a/pkg/grpc/portergrpc/installation_test.go b/pkg/grpc/portergrpc/installation_test.go
new file mode 100644
index 000000000..3d257a028
--- /dev/null
+++ b/pkg/grpc/portergrpc/installation_test.go
@@ -0,0 +1,139 @@
+package portergrpc
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "testing"
+
+ iGRPC "get.porter.sh/porter/gen/proto/go/porterapis/installation/v1alpha1"
+ "get.porter.sh/porter/pkg/cnab"
+ "get.porter.sh/porter/pkg/porter"
+ "get.porter.sh/porter/pkg/storage"
+ "get.porter.sh/porter/tests"
+ "github.com/google/uuid"
+ "github.com/stretchr/testify/assert"
+ "google.golang.org/protobuf/encoding/protojson"
+ "k8s.io/utils/pointer"
+)
+
+type instInfo struct {
+ namespace string
+ name string
+}
+
+func TestListInstallationReturnsListOfCorrectPorterInstallations(t *testing.T) {
+ testNamespace := "test"
+ testInstallationName := "foo"
+ filterOpts := []struct {
+ name string
+ opts *iGRPC.ListInstallationsRequest
+ }{
+ {
+ name: "FilterByAllNamespaces",
+ opts: &iGRPC.ListInstallationsRequest{AllNamespaces: pointer.Bool(true)},
+ },
+ {
+ name: "FilterByNamespace",
+ opts: &iGRPC.ListInstallationsRequest{Namespace: &testNamespace},
+ },
+ {
+ name: "FilterByInstallationNameAndNamespace",
+ opts: &iGRPC.ListInstallationsRequest{Namespace: &testNamespace, Name: testInstallationName},
+ },
+ }
+ tests := []struct {
+ name string
+ instInfo []instInfo
+ // Number of expected installations when filtering by all namespaces, all installations in a single namespace, and a single installation in a namespace
+ numExpInsts []int
+ }{
+ {
+ name: "NoInstallations",
+ instInfo: []instInfo{},
+ numExpInsts: []int{0, 0, 0},
+ },
+ {
+ name: "SingleInstallationDefaultNamespace",
+ instInfo: []instInfo{
+ {namespace: "", name: "test"},
+ },
+ numExpInsts: []int{1, 0, 0},
+ },
+ {
+ name: "SingleInstallationInMultipleNamespaces",
+ instInfo: []instInfo{
+ {namespace: testNamespace, name: testInstallationName},
+ {namespace: "bar", name: "test"},
+ },
+ numExpInsts: []int{2, 1, 1},
+ },
+ {
+ name: "MultipleInstallationSInMultipleNamespaces",
+ instInfo: []instInfo{
+ {namespace: "foo", name: "test1"},
+ {namespace: "foo", name: "test2"},
+ {namespace: testNamespace, name: testInstallationName},
+ {namespace: testNamespace, name: "test4"},
+ },
+ numExpInsts: []int{4, 2, 1},
+ },
+ }
+ for _, test := range tests {
+ ctx, insts := setupTestPorterWithInstallations(t, test.instInfo)
+ for i, opts := range filterOpts {
+ t.Run(fmt.Sprintf("%s%s", test.name, opts.name), func(t *testing.T) {
+ instSvc := PorterServer{}
+ resp, err := instSvc.ListInstallations(ctx, opts.opts)
+ installations := resp.GetInstallation()
+ assert.Nil(t, err)
+ assert.Len(t, installations, test.numExpInsts[i])
+ verifyInstallations(t, installations, insts)
+ })
+ }
+ }
+}
+
+func TestListInstallationsReturnsErrorIfUnableToGetPorterConnectionFromRequestContext(t *testing.T) {
+ instSvc := PorterServer{}
+ req := &iGRPC.ListInstallationsRequest{}
+ ctx := context.TODO()
+ resp, err := instSvc.ListInstallations(ctx, req)
+ assert.Error(t, err)
+ assert.Nil(t, resp)
+
+}
+
+func setupTestPorterWithInstallations(t *testing.T, installations []instInfo) (context.Context, map[string]porter.DisplayInstallation) {
+ p := porter.NewTestPorter(t)
+ insts := map[string]porter.DisplayInstallation{}
+ for _, inst := range installations {
+ installation := storage.NewInstallation(inst.namespace, inst.name)
+ storeInst := p.TestInstallations.CreateInstallation(installation, p.TestInstallations.SetMutableInstallationValues, func(i *storage.Installation) {
+ // Overwrite the default ID set by SetMutableInstallationValues because it is always the same
+ i.ID = uuid.NewString()
+ i.Status.BundleVersion = "v0.1.0"
+ i.Status.ResultStatus = cnab.StatusSucceeded
+ i.Bundle.Repository = "test-bundle"
+ i.Bundle.Version = "v0.1.0"
+ })
+ insts[storeInst.ID] = porter.NewDisplayInstallation(storeInst)
+ }
+ ctx := AddPorterConnectionToContext(p.Porter, context.TODO())
+ return ctx, insts
+}
+
+func verifyInstallations(t *testing.T, installations []*iGRPC.Installation, allInsts map[string]porter.DisplayInstallation) {
+ for _, inst := range installations {
+ i, ok := allInsts[inst.Id]
+ assert.True(t, ok)
+ bExpInst, err := json.Marshal(i)
+ assert.NoError(t, err)
+ grpcExpInst, err := tests.GRPCDisplayInstallationExpectedJSON(bExpInst)
+ assert.NoError(t, err)
+ pjm := protojson.MarshalOptions{EmitUnpopulated: true}
+ bActInst, err := pjm.Marshal(inst)
+ assert.NoError(t, err)
+ assert.JSONEq(t, string(grpcExpInst), string(bActInst))
+ }
+}
diff --git a/pkg/grpc/portergrpc/portergrpc.go b/pkg/grpc/portergrpc/portergrpc.go
new file mode 100644
index 000000000..53f6201a9
--- /dev/null
+++ b/pkg/grpc/portergrpc/portergrpc.go
@@ -0,0 +1,41 @@
+package portergrpc
+
+import (
+ "context"
+
+ pGRPC "get.porter.sh/porter/gen/proto/go/porterapis/porter/v1alpha1"
+ "get.porter.sh/porter/pkg/config"
+ "get.porter.sh/porter/pkg/porter"
+ "get.porter.sh/porter/pkg/secrets"
+ secretsplugin "get.porter.sh/porter/pkg/secrets/pluginstore"
+ "get.porter.sh/porter/pkg/storage"
+ storageplugin "get.porter.sh/porter/pkg/storage/pluginstore"
+ "google.golang.org/grpc"
+)
+
+// PorterServer defines the struct for managing a porter GRPC server
+type PorterServer struct {
+ PorterConfig *config.Config
+ pGRPC.UnimplementedPorterServer
+}
+
+// NewPorterServer creates a new instance of the PorterServer for a config
+func NewPorterServer(cfg *config.Config) (*PorterServer, error) {
+ return &PorterServer{PorterConfig: cfg}, nil
+}
+
+// NewConnectionInterceptor creates a middleware interceptor for the GRPC server that manages creating a porter connection for each requested RPC stream.
+// If the connection is unable to be created for the RPC then the RPC fails, otherwise the connection is added to the RPC context and the next handler in the
+// chain is called
+func (s *PorterServer) NewConnectionInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ storage := storage.NewPluginAdapter(storageplugin.NewStore(s.PorterConfig))
+ secretStorage := secrets.NewPluginAdapter(secretsplugin.NewStore(s.PorterConfig))
+ p := porter.NewFor(s.PorterConfig, storage, secretStorage)
+ if _, err := p.Connect(ctx); err != nil {
+ return nil, err
+ }
+ defer p.Close()
+
+ ctx = AddPorterConnectionToContext(p, ctx)
+ return handler(ctx, req)
+}
diff --git a/pkg/grpc/portergrpc/portergrpc_test.go b/pkg/grpc/portergrpc/portergrpc_test.go
new file mode 100644
index 000000000..d25641e2b
--- /dev/null
+++ b/pkg/grpc/portergrpc/portergrpc_test.go
@@ -0,0 +1,29 @@
+package portergrpc
+
+import (
+ "context"
+ "testing"
+
+ "get.porter.sh/porter/pkg/config"
+ "get.porter.sh/porter/pkg/porter"
+ grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
+ "github.com/stretchr/testify/assert"
+ "google.golang.org/grpc"
+)
+
+func TestNewConnectionInterceptorCallsNextHandlerInTheChainWithThePorterConnectionInTheContext(t *testing.T) {
+ cfg := config.NewTestConfig(t)
+ srv := PorterServer{PorterConfig: cfg.Config}
+ parentUnaryInfo := &grpc.UnaryServerInfo{FullMethod: "SomeService.StreamMethod"}
+ input := "input"
+ testHandler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ p, err := GetPorterConnectionFromContext(ctx)
+ return p, err
+ }
+ ctx := context.Background()
+ chain := grpc_middleware.ChainUnaryServer(srv.NewConnectionInterceptor)
+ newP, err := chain(ctx, input, parentUnaryInfo, testHandler)
+ assert.Nil(t, err)
+ assert.NotNil(t, newP)
+ assert.IsType(t, &porter.Porter{}, newP)
+}
diff --git a/pkg/grpc/server.go b/pkg/grpc/server.go
new file mode 100644
index 000000000..20920f3ce
--- /dev/null
+++ b/pkg/grpc/server.go
@@ -0,0 +1,124 @@
+package grpc
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "net/http"
+ "os"
+
+ pGRPCv1alpha1 "get.porter.sh/porter/gen/proto/go/porterapis/porter/v1alpha1"
+ "get.porter.sh/porter/pkg/config"
+ pserver "get.porter.sh/porter/pkg/grpc/portergrpc"
+ "get.porter.sh/porter/pkg/porter"
+ "get.porter.sh/porter/pkg/tracing"
+
+ grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
+ grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/health"
+ "google.golang.org/grpc/health/grpc_health_v1"
+ "google.golang.org/grpc/reflection"
+)
+
+var (
+ reg = prometheus.NewRegistry()
+ // Create some standard server metrics.
+ grpcMetrics = grpc_prometheus.NewServerMetrics()
+
+ // Create a customized counter metric.
+ customizedCounterMetric = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "demo_server_say_hello_method_handle_count",
+ Help: "Total number of RPCs handled on the server.",
+ }, []string{"name"})
+)
+
+func init() {
+ reg.MustRegister(grpcMetrics, customizedCounterMetric)
+ customizedCounterMetric.WithLabelValues("Test")
+}
+
+type PorterGRPCService struct {
+ PorterConfig *config.Config
+ opts *porter.ServiceOptions
+ ctx context.Context
+}
+
+func NewServer(ctx context.Context, opts *porter.ServiceOptions) (*PorterGRPCService, error) {
+ pCfg := config.New()
+ srv := &PorterGRPCService{
+ PorterConfig: pCfg,
+ opts: opts,
+ ctx: ctx,
+ }
+ return srv, nil
+}
+
+func (s *PorterGRPCService) ListenAndServe() (*grpc.Server, error) {
+ _, log := tracing.StartSpan(s.ctx)
+ defer log.EndSpan()
+ log.Infof("Starting gRPC on %v", s.opts.Port)
+ listener, err := net.Listen("tcp", fmt.Sprintf(":%v", s.opts.Port))
+ if err != nil {
+ return nil, fmt.Errorf("failed to listen on %d: %s", s.opts.Port, err)
+ }
+ httpServer := &http.Server{Handler: promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), Addr: fmt.Sprintf("0.0.0.0:%d", 9092)}
+
+ healthServer := health.NewServer()
+ psrv, err := pserver.NewPorterServer(s.PorterConfig)
+ if err != nil {
+ return nil, err
+ }
+ srv := grpc.NewServer(
+ grpc.StreamInterceptor(grpcMetrics.StreamServerInterceptor()),
+ grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
+ grpcMetrics.UnaryServerInterceptor(),
+ psrv.NewConnectionInterceptor),
+ ),
+ )
+ reflection.Register(srv)
+
+ pGRPCv1alpha1.RegisterPorterServer(srv, psrv)
+ healthServer.SetServingStatus(s.opts.ServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
+ grpc_prometheus.Register(srv)
+
+ srvErrCh := make(chan error, 1)
+ go func() {
+ if err := srv.Serve(listener); err != nil {
+ srvErrCh <- err
+ }
+ }()
+
+ select {
+ case err := <-srvErrCh:
+ if err != nil {
+ log.Errorf("failed to serve GRPC listener: %w", err)
+ os.Exit(1)
+ }
+ default:
+ // Continue if no error is received yet
+ }
+
+ http.Handle("/metrics", promhttp.Handler())
+
+ // Start your http server for prometheus.
+ go func() {
+ if err := httpServer.ListenAndServe(); err != nil {
+ srvErrCh <- err
+ }
+ }()
+ select {
+ case err := <-srvErrCh:
+ if err != nil {
+ log.Errorf("Unable to start a http server. %w", err)
+ os.Exit(1)
+ }
+ default:
+ // Continue if no error is received yet
+ }
+
+ grpcMetrics.InitializeMetrics(srv)
+ return srv, nil
+}
diff --git a/pkg/grpc/server_test.go b/pkg/grpc/server_test.go
new file mode 100644
index 000000000..21e034e4c
--- /dev/null
+++ b/pkg/grpc/server_test.go
@@ -0,0 +1 @@
+package grpc
diff --git a/pkg/porter/service.go b/pkg/porter/service.go
new file mode 100644
index 000000000..a842629a7
--- /dev/null
+++ b/pkg/porter/service.go
@@ -0,0 +1,10 @@
+package porter
+
+type ServiceOptions struct {
+ Port int64
+ ServiceName string
+}
+
+func (o *ServiceOptions) Validate() error {
+ return nil
+}
diff --git a/pkg/service/service.go b/pkg/service/service.go
new file mode 100644
index 000000000..687ab278b
--- /dev/null
+++ b/pkg/service/service.go
@@ -0,0 +1,4 @@
+package service
+
+type ServiceOpts struct {
+}
diff --git a/pkg/signals/shutdown.go b/pkg/signals/shutdown.go
new file mode 100644
index 000000000..475b29e8d
--- /dev/null
+++ b/pkg/signals/shutdown.go
@@ -0,0 +1,53 @@
+package signals
+
+import (
+ "context"
+ "time"
+
+ "get.porter.sh/porter/pkg/tracing"
+ "github.com/spf13/viper"
+ oteltrace "go.opentelemetry.io/otel/sdk/trace"
+ "google.golang.org/grpc"
+)
+
+type Shutdown struct {
+ tracerProvider *oteltrace.TracerProvider
+ serverShutdownTimeout time.Duration
+}
+
+func NewShutdown(serverShutdownTimeout time.Duration, ctx context.Context) (*Shutdown, error) {
+ srv := &Shutdown{
+ serverShutdownTimeout: serverShutdownTimeout,
+ }
+
+ return srv, nil
+}
+
+func (s *Shutdown) Graceful(stopCh <-chan struct{}, grpcServer *grpc.Server, ctx context.Context) {
+ ctx, log := tracing.StartSpan(ctx)
+
+ // wait for SIGTERM or SIGINT
+ <-stopCh
+ ctx, cancel := context.WithTimeout(ctx, s.serverShutdownTimeout)
+ defer cancel()
+
+ // wait for Kubernetes readiness probe to remove this instance from the load balancer
+ // the readiness check interval must be lower than the timeout
+ if viper.GetString("level") != "debug" {
+ time.Sleep(3 * time.Second)
+ }
+
+ // stop OpenTelemetry tracer provider
+ if s.tracerProvider != nil {
+ if err := s.tracerProvider.Shutdown(ctx); err != nil {
+ log.Warnf("stopping tracer provider: ", err)
+ }
+ }
+
+ // determine if the GRPC was started
+ if grpcServer != nil {
+ log.Infof("Shutting down GRPC server: ", s.serverShutdownTimeout)
+ grpcServer.GracefulStop()
+ }
+
+}
diff --git a/pkg/signals/signal.go b/pkg/signals/signal.go
new file mode 100644
index 000000000..f82aafbbd
--- /dev/null
+++ b/pkg/signals/signal.go
@@ -0,0 +1,27 @@
+package signals
+
+import (
+ "os"
+ "os/signal"
+)
+
+var onlyOneSignalHandler = make(chan struct{})
+
+// SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned
+// which is closed on one of these signals. If a second signal is caught, the program
+// is terminated with exit code 1.
+func SetupSignalHandler() (stopCh <-chan struct{}) {
+ close(onlyOneSignalHandler) // panics when called twice
+
+ stop := make(chan struct{})
+ c := make(chan os.Signal, 2)
+ signal.Notify(c, shutdownSignals...)
+ go func() {
+ <-c
+ close(stop)
+ <-c
+ os.Exit(1) // second signal. Exit directly.
+ }()
+
+ return stop
+}
diff --git a/pkg/signals/signal_posix.go b/pkg/signals/signal_posix.go
new file mode 100644
index 000000000..80d74d277
--- /dev/null
+++ b/pkg/signals/signal_posix.go
@@ -0,0 +1,11 @@
+//go:build !windows
+// +build !windows
+
+package signals
+
+import (
+ "os"
+ "syscall"
+)
+
+var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGINT}
diff --git a/pkg/signals/signal_windows.go b/pkg/signals/signal_windows.go
new file mode 100644
index 000000000..f2015c1a3
--- /dev/null
+++ b/pkg/signals/signal_windows.go
@@ -0,0 +1,7 @@
+package signals
+
+import (
+ "os"
+)
+
+var shutdownSignals = []os.Signal{os.Interrupt}
diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml
new file mode 100644
index 000000000..dbaf1372f
--- /dev/null
+++ b/proto/buf.gen.yaml
@@ -0,0 +1,14 @@
+version: v1
+managed:
+ enabled: true
+ go_package_prefix:
+ default: get.porter.sh/porter/gen/proto/go/porterapis
+ except:
+ - buf.build/googleapis/googleapis
+plugins:
+ - plugin: go
+ out: ../gen/proto/go/porterapis
+ opt: module=get.porter.sh/porter/gen/proto/go/porterapis
+ - plugin: go-grpc
+ out: ../gen/proto/go/porterapis
+ opt: module=get.porter.sh/porter/gen/proto/go/porterapis
diff --git a/proto/buf.work.yaml b/proto/buf.work.yaml
new file mode 100644
index 000000000..94e6fe5ff
--- /dev/null
+++ b/proto/buf.work.yaml
@@ -0,0 +1,3 @@
+version: v1
+directories:
+ - porterapis
diff --git a/proto/porterapis/buf.lock b/proto/porterapis/buf.lock
new file mode 100644
index 000000000..19abf63fb
--- /dev/null
+++ b/proto/porterapis/buf.lock
@@ -0,0 +1,7 @@
+# Generated by buf. DO NOT EDIT.
+version: v1
+deps:
+ - remote: buf.build
+ owner: googleapis
+ repository: googleapis
+ commit: 75b4300737fb4efca0831636be94e517
diff --git a/proto/porterapis/buf.md b/proto/porterapis/buf.md
new file mode 100644
index 000000000..e69de29bb
diff --git a/proto/porterapis/buf.yaml b/proto/porterapis/buf.yaml
new file mode 100644
index 000000000..97bac4a1a
--- /dev/null
+++ b/proto/porterapis/buf.yaml
@@ -0,0 +1,10 @@
+version: v1
+name: buf.build/porter/porter
+deps:
+ - buf.build/googleapis/googleapis
+breaking:
+ use:
+ - FILE
+lint:
+ use:
+ - DEFAULT
diff --git a/proto/porterapis/installation/buf.yaml b/proto/porterapis/installation/buf.yaml
new file mode 100644
index 000000000..54de6a058
--- /dev/null
+++ b/proto/porterapis/installation/buf.yaml
@@ -0,0 +1,8 @@
+version: v1
+name: buf.build/porter/installationsapi
+breaking:
+ use:
+ - FILE
+lint:
+ use:
+ - DEFAULT
diff --git a/proto/porterapis/installation/v1alpha1/installation.proto b/proto/porterapis/installation/v1alpha1/installation.proto
new file mode 100644
index 000000000..d18c0be01
--- /dev/null
+++ b/proto/porterapis/installation/v1alpha1/installation.proto
@@ -0,0 +1,99 @@
+syntax = "proto3";
+//option go_package = "get.porter.sh/porter/gen/proto/go/installation/v1alpha1";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+package installation.v1alpha1;
+
+message Bundle {
+ string repository = 1;
+ string version = 2;
+}
+
+message InstallationStatus {
+ string runId = 1;
+ string action = 2;
+ string resultId = 3;
+ string resultStatus = 4;
+ google.protobuf.Timestamp created = 5;
+ google.protobuf.Timestamp modified = 6;
+ google.protobuf.Timestamp installed = 7;
+ google.protobuf.Timestamp uninstalled = 8;
+ string bundleReference = 9;
+ string bundleVersion = 10;
+ string bundleDigest = 11;
+}
+
+message Calculated {
+ string displayInstallationState = 1;
+ string displayInstallationStatus = 2;
+ google.protobuf.NullValue resolvedParameters = 3;
+}
+message Installation {
+ // Unique installation ID
+ string id = 1;
+ string schemaType = 2;
+ string schemaVersion = 3;
+ string name = 4;
+ string namespace = 5;
+ Bundle bundle = 6;
+ repeated string credentialSets = 7;
+ repeated string parameterSets = 8;
+ InstallationStatus status = 9;
+ Calculated calculated = 10 [json_name="_calculated"];
+}
+
+//Installations
+message ListInstallationsRequest {
+ string name = 1;
+ optional string namespace = 2;
+ optional int64 limit = 3;
+ optional int64 skip = 4;
+ map labels = 5;
+ optional bool allNamespaces = 6;
+}
+
+message ListInstallationsResponse {
+ repeated Installation installation = 1;
+}
+
+//InstallationRuns
+message InstallationRun {
+ int64 id = 1;
+ string bundle = 2;
+ string version = 3;
+ string action = 4;
+ map paramters = 5;
+ google.protobuf.Timestamp started = 6;
+ google.protobuf.Timestamp stopped = 7;
+ string status = 8;
+}
+
+message ListInstallationRunsRequest {
+ Installation installation = 1;
+}
+
+message ListInstallationRunsResponse {
+ repeated InstallationRun run = 1;
+}
+
+message PorterValue {
+ string name = 1;
+ string type = 2;
+ bool sensitive = 3;
+ google.protobuf.Value value = 4;
+}
+
+message InstallationOutputs {
+ repeated PorterValue output = 1;
+}
+
+message ListInstallationLatestOutputRequest {
+ string name = 1;
+ optional string namespace = 2;
+}
+
+//InstallationRunOutputs
+message ListInstallationLatestOutputResponse {
+ repeated PorterValue outputs = 1;
+}
\ No newline at end of file
diff --git a/proto/porterapis/porter/buf.yaml b/proto/porterapis/porter/buf.yaml
new file mode 100644
index 000000000..cf86b8789
--- /dev/null
+++ b/proto/porterapis/porter/buf.yaml
@@ -0,0 +1,8 @@
+version: v1
+name: buf.build/porter/porter
+breaking:
+ use:
+ - FILE
+lint:
+ use:
+ - DEFAULT
diff --git a/proto/porterapis/porter/v1alpha1/porter.proto b/proto/porterapis/porter/v1alpha1/porter.proto
new file mode 100644
index 000000000..a7621c021
--- /dev/null
+++ b/proto/porterapis/porter/v1alpha1/porter.proto
@@ -0,0 +1,13 @@
+syntax = "proto3";
+//option go_package = "get.porter.sh/porter/gen/proto/go/installation/v1alpha1";
+package porter.v1alpha1;
+
+import "installation/v1alpha1/installation.proto";
+
+service Porter {
+ //Returns a list of all installations
+ rpc ListInstallations (installation.v1alpha1.ListInstallationsRequest) returns (installation.v1alpha1.ListInstallationsResponse) {}
+
+ //Returns a list of all outputs for the latest installation run
+ rpc ListInstallationLatestOutputs(installation.v1alpha1.ListInstallationLatestOutputRequest) returns(installation.v1alpha1.ListInstallationLatestOutputResponse) {}
+}
\ No newline at end of file
diff --git a/tests/grpc/installation_test.go b/tests/grpc/installation_test.go
new file mode 100644
index 000000000..1d48e183f
--- /dev/null
+++ b/tests/grpc/installation_test.go
@@ -0,0 +1,187 @@
+package grpc
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "strconv"
+ "testing"
+
+ iGRPC "get.porter.sh/porter/gen/proto/go/porterapis/installation/v1alpha1"
+ pGRPC "get.porter.sh/porter/gen/proto/go/porterapis/porter/v1alpha1"
+ "get.porter.sh/porter/pkg/cnab"
+ "get.porter.sh/porter/pkg/porter"
+ "get.porter.sh/porter/pkg/storage"
+ "get.porter.sh/porter/tests"
+ "github.com/cnabio/cnab-go/bundle"
+ "github.com/cnabio/cnab-go/bundle/definition"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+ "google.golang.org/protobuf/encoding/protojson"
+)
+
+type testOutputOpt struct {
+ name string
+ value string
+ bundleOutput bundle.Output
+}
+type testInstallationOpts struct {
+ bundleDefs *map[string]*definition.Schema
+ outputs *[]testOutputOpt
+}
+
+// TODO: add opts structure for different installation options
+func newTestInstallation(t *testing.T, namespace, name string, grpcSvr *TestPorterGRPCServer, opts testInstallationOpts) storage.Installation {
+ //Bundle Definition with required porter-state
+ bd := definition.Definitions{
+ "porter-state": &definition.Schema{
+ Type: "string",
+ Comment: "porter-internal",
+ },
+ }
+ for name, schema := range *opts.bundleDefs {
+ bd[name] = schema
+ }
+ //Bundle Output with required porter-state
+ bo := map[string]bundle.Output{
+ "porter-state": {
+ Definition: "porter-state",
+ Path: "/cnab/app/outputs/porter-state.tgz",
+ },
+ }
+ for _, out := range *opts.outputs {
+ bo[out.name] = out.bundleOutput
+ }
+ b := bundle.Bundle{
+ Definitions: bd,
+ Outputs: bo,
+ }
+ extB := cnab.NewBundle(b)
+ storeInst := grpcSvr.TestPorter.TestInstallations.CreateInstallation(storage.NewInstallation(namespace, name), grpcSvr.TestPorter.TestInstallations.SetMutableInstallationValues, func(i *storage.Installation) {
+ i.Status.BundleVersion = "v0.1.0"
+ i.Status.ResultStatus = cnab.StatusSucceeded
+ i.Bundle.Repository = "test-bundle"
+ i.Bundle.Version = "v0.1.0"
+ })
+ c := grpcSvr.TestPorter.TestInstallations.CreateRun(storeInst.NewRun(cnab.ActionInstall, cnab.ExtendedBundle{}), func(sRun *storage.Run) {
+ sRun.Bundle = b
+ sRun.ParameterOverrides.Parameters = grpcSvr.TestPorter.SanitizeParameters(sRun.ParameterOverrides.Parameters, sRun.ID, extB)
+ })
+ sRes := grpcSvr.TestPorter.TestInstallations.CreateResult(c.NewResult(cnab.StatusSucceeded))
+ for _, out := range *opts.outputs {
+ grpcSvr.TestPorter.CreateOutput(sRes.NewOutput(out.name, []byte(out.value)), extB)
+ }
+ return storeInst
+}
+
+func TestInstall_installationMessage(t *testing.T) {
+ writeOnly := true
+ basicInstOpts := testInstallationOpts{
+ bundleDefs: &map[string]*definition.Schema{
+ "foo": {Type: "string", WriteOnly: &writeOnly},
+ "bar": {Type: "string", WriteOnly: &writeOnly},
+ },
+ outputs: &[]testOutputOpt{
+ {
+ name: "foo",
+ value: "foo-data",
+ bundleOutput: bundle.Output{Definition: "foo", Path: "/path/to/foo"},
+ },
+ {
+ name: "bar",
+ value: "bar-data",
+ bundleOutput: bundle.Output{Definition: "bar", Path: "/path/to/bar"},
+ },
+ },
+ }
+ tests := []struct {
+ testName string
+ instName string
+ instNamespace string ""
+ instOpts testInstallationOpts
+ }{
+ {
+ testName: "basic installation",
+ instName: "test",
+ instOpts: basicInstOpts,
+ },
+ {
+ testName: "another installation",
+ instName: "another-test",
+ instOpts: basicInstOpts,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.testName, func(t *testing.T) {
+ //Server setup
+ grpcSvr, err := NewTestGRPCServer(t)
+ require.NoError(t, err)
+ server := grpcSvr.ListenAndServe()
+ defer server.Stop()
+
+ //Client setup
+ ctx := context.TODO()
+ client, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ require.NoError(t, err)
+ defer client.Close()
+ instClient := pGRPC.NewPorterClient(client)
+
+ inst := newTestInstallation(t, test.instNamespace, test.instName, grpcSvr, test.instOpts)
+
+ //Call ListInstallations
+ resp, err := instClient.ListInstallations(ctx, &iGRPC.ListInstallationsRequest{})
+ require.NoError(t, err)
+ assert.Len(t, resp.Installation, 1)
+ // Validation
+ validateInstallations(t, inst, resp.GetInstallation()[0])
+
+ //Call ListInstallationLatestOutputRequest
+ req := &iGRPC.ListInstallationLatestOutputRequest{Name: test.instName, Namespace: &test.instNamespace}
+ oresp, err := instClient.ListInstallationLatestOutputs(ctx, req)
+ require.NoError(t, err)
+ assert.Len(t, oresp.GetOutputs(), len(*test.instOpts.outputs))
+
+ oOpts := &porter.OutputListOptions{}
+ oOpts.Name = test.instName
+ oOpts.Namespace = test.instNamespace
+ oOpts.Format = "json"
+ dvs, err := grpcSvr.TestPorter.ListBundleOutputs(ctx, oOpts)
+ require.NoError(t, err)
+
+ //Validation
+ validateOutputs(t, dvs, oresp)
+ })
+ }
+}
+
+func validateInstallations(t *testing.T, expected storage.Installation, actual *iGRPC.Installation) {
+ assert.Equal(t, actual.Name, expected.Name)
+ bExpInst, err := json.Marshal(porter.NewDisplayInstallation(expected))
+ require.NoError(t, err)
+ bExpInst, err = tests.GRPCDisplayInstallationExpectedJSON(bExpInst)
+ require.NoError(t, err)
+ pjm := protojson.MarshalOptions{EmitUnpopulated: true}
+ bActInst, err := pjm.Marshal(actual)
+ require.NoError(t, err)
+ var pJson bytes.Buffer
+ json.Indent(&pJson, bActInst, "", " ")
+ assert.JSONEq(t, string(bExpInst), string(bActInst))
+}
+
+func validateOutputs(t *testing.T, dvs porter.DisplayValues, actual *iGRPC.ListInstallationLatestOutputResponse) {
+ //Get expected json
+ bExpOuts, err := json.MarshalIndent(dvs, "", " ")
+ require.NoError(t, err)
+ pjm := protojson.MarshalOptions{EmitUnpopulated: true, Multiline: true, Indent: " "}
+ //Get actual json response
+ for i, gPV := range actual.GetOutputs() {
+ bActOut, err := pjm.Marshal(gPV)
+ require.NoError(t, err)
+ //TODO: make this not dependant on order
+ bExpOut := gjson.GetBytes(bExpOuts, strconv.Itoa(i)).String()
+ assert.JSONEq(t, bExpOut, string(bActOut))
+ }
+}
diff --git a/tests/grpc/test_utils.go b/tests/grpc/test_utils.go
new file mode 100644
index 000000000..52013c551
--- /dev/null
+++ b/tests/grpc/test_utils.go
@@ -0,0 +1,73 @@
+package grpc
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "testing"
+
+ pGRPC "get.porter.sh/porter/gen/proto/go/porterapis/porter/v1alpha1"
+ "get.porter.sh/porter/pkg/config"
+ pServer "get.porter.sh/porter/pkg/grpc/portergrpc"
+ "get.porter.sh/porter/pkg/porter"
+ grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
+
+ //"go.opentelemetry.io/otel/attribute"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/health"
+ "google.golang.org/grpc/health/grpc_health_v1"
+ "google.golang.org/grpc/reflection"
+ "google.golang.org/grpc/test/bufconn"
+)
+
+type TestPorterGRPCServer struct {
+ TestPorter *porter.TestPorter
+ TestPorterConfig *config.TestConfig
+}
+
+var lis *bufconn.Listener
+
+func NewTestGRPCServer(t *testing.T) (*TestPorterGRPCServer, error) {
+ srv := &TestPorterGRPCServer{
+ TestPorter: porter.NewTestPorter(t),
+ TestPorterConfig: config.NewTestConfig(t),
+ }
+ return srv, nil
+}
+
+func (s *TestPorterGRPCServer) newTestInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ ctx = pServer.AddPorterConnectionToContext(s.TestPorter.Porter, ctx)
+ h, err := handler(ctx, req)
+ return h, err
+}
+
+func (s *TestPorterGRPCServer) ListenAndServe() *grpc.Server {
+ bufSize := 1024 * 1024
+ lis = bufconn.Listen(bufSize)
+
+ srv := grpc.NewServer(
+ grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
+ s.newTestInterceptor,
+ )))
+
+ healthServer := health.NewServer()
+ reflection.Register(srv)
+ grpc_health_v1.RegisterHealthServer(srv, healthServer)
+ pSvc, err := pServer.NewPorterServer(s.TestPorter.Config)
+ if err != nil {
+ panic(err)
+ }
+ pGRPC.RegisterPorterServer(srv, pSvc)
+ healthServer.SetServingStatus("test-health", grpc_health_v1.HealthCheckResponse_SERVING)
+
+ go func() {
+ if err := srv.Serve(lis); err != nil {
+ panic(fmt.Errorf("failed to serve: %w", err))
+ }
+ }()
+ return srv
+}
+
+func bufDialer(context.Context, string) (net.Conn, error) {
+ return lis.Dial()
+}
diff --git a/tests/helpers.go b/tests/helpers.go
index c93508472..f35053418 100644
--- a/tests/helpers.go
+++ b/tests/helpers.go
@@ -10,6 +10,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
)
// RequireErrorContains fails the test when the error doesn't contain
@@ -70,3 +72,23 @@ func RequireOutputContains(t *testing.T, output string, substring string, msgAnd
t.FailNow()
}
}
+
+// GRPCDisplayInstallationExpectedJSON converts a json byte string from
+// a porter.DisplayInstallation to one expected from a GRPC Installation
+func GRPCDisplayInstallationExpectedJSON(bExpInst []byte) ([]byte, error) {
+ // if no credentialSets or parameterSets add as empty list to
+ // match GRPCInstallation expectations
+ var err error
+ empty := make([]string, 0)
+ emptySets := []string{"credentialSets", "parameterSets"}
+ for _, es := range emptySets {
+ res := gjson.GetBytes(bExpInst, es)
+ if !res.Exists() {
+ bExpInst, err = sjson.SetBytes(bExpInst, es, empty)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return bExpInst, nil
+}
diff --git a/tests/integration/archive_test.go b/tests/integration/archive_test.go
index 8a2bfdb4d..ca0604c23 100644
--- a/tests/integration/archive_test.go
+++ b/tests/integration/archive_test.go
@@ -57,7 +57,7 @@ func TestArchive_StableDigest(t *testing.T) {
assert.Equal(p.T(), hash1, getHash(p, archiveFile2), "shasum of archive did not stay the same on the second call to archive")
// the archive should match the hash below regardless of OS architecture, user and execution time
- consistentHash := "27c2cf6ef0dfac6f120290a79def2e3417656d0d44adc80991d864d7c8c398ed"
+ consistentHash := "6f63a27bd8fa3886192ce9d4d561d9b2f5d5235b17a140af6d1608921fe00e7f"
assert.Equal(p.T(), consistentHash, hash1, "shasum of archive did not match expected hash")
// Publish bundle from archive, with new reference