From 3d52016507c96c021598d11cc4b3dc51b03d0429 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Fri, 18 Jun 2021 08:04:40 +0000 Subject: [PATCH 01/15] [ws-manager] Add support for workspace annotations --- components/ws-manager-api/core.proto | 32 +- components/ws-manager-api/go/core.pb.go | 1258 +++++++++-------- .../typescript/src/core_pb.d.ts | 46 + .../ws-manager-api/typescript/src/core_pb.js | 357 ++++- .../ws-manager/pkg/manager/annotations.go | 3 + components/ws-manager/pkg/manager/create.go | 7 + components/ws-manager/pkg/manager/manager.go | 54 +- components/ws-manager/pkg/manager/monitor.go | 5 +- .../manager/testdata/cdwp_imagebuild.golden | 229 +++ .../pkg/manager/testdata/cdwp_imagebuild.json | 36 + 10 files changed, 1466 insertions(+), 561 deletions(-) create mode 100644 components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden create mode 100644 components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.json diff --git a/components/ws-manager-api/core.proto b/components/ws-manager-api/core.proto index 044384bbf5cc67..1ed0d31c3e38ca 100644 --- a/components/ws-manager-api/core.proto +++ b/components/ws-manager-api/core.proto @@ -39,8 +39,25 @@ service WorkspaceManager { rpc ControlAdmission(ControlAdmissionRequest) returns (ControlAdmissionResponse) {} } +// MetadataFilter describes conditions for matching a set of workspaces. +// The values of the fields have to match exactly, and set values must match. +message MetadataFilter { + // owner is the ID of the Gitpod user to whom we'll bill this workspace and who we consider responsible for its content + string owner = 1; + + // meta_id is the workspace ID of this currently running workspace instance on the "meta pool" side + string meta_id = 2; + + // annotations must be a subset of the annotations of a workspace's metadata + map annotations = 3; +} + // GetWorkspacesRequest requests a list of running workspaces -message GetWorkspacesRequest {} +message GetWorkspacesRequest { + // MustMatch can specify an exactly matching filter for listing workspaces. + // If not set, or all fields are empty, all workspaces are returned. + MetadataFilter must_match = 1; +} // GetWorkspacesResponse is the response to a get w message GetWorkspacesResponse { @@ -109,7 +126,11 @@ message DescribeWorkspaceResponse { } // SubscribeRequest requests to be notified whenever the workspace status changes -message SubscribeRequest {} +message SubscribeRequest { + // MustMatch can specify an exactly matching filter for listening to workspaces. + // If not set, or all fields are empty, all workspace status updates or log output are returned. + MetadataFilter must_match = 1; +} // SubscribeResponse notifies a client when a workspace's status changes message SubscribeResponse { @@ -363,6 +384,10 @@ message WorkspaceMetadata { // started_at is the time when this workspace was started. Consider this field read-only, i.e. setting in a request will have no effect. google.protobuf.Timestamp started_at = 3; + + // Annotations are key/value pairs that gets attached to the workspace. + // This is primarily intended for annotating headless workspace loads. + map annotations = 4; } // WorkspaceRuntimeInfo details the workspace's runtime, e.g. executing system, node other information @@ -483,6 +508,9 @@ enum WorkspaceType { // Ghost workspaces are placeholders that pre-scale a cluster for faster workspace startup. They request the same amount of resources // as a regular workspace, but run no actual load. They're removed at will to make space for an actual workspace. GHOST = 3; + + // Imagebuild workspaces build a workspace, incl. their Gitpod layer. They run headless and have no direct user-interaction. + IMAGEBUILD = 4; } // HeadlessWorkspaceEvent is a log statement issued by a headless workspace diff --git a/components/ws-manager-api/go/core.pb.go b/components/ws-manager-api/go/core.pb.go index 76dc4ee2137651..24c0a235855664 100644 --- a/components/ws-manager-api/go/core.pb.go +++ b/components/ws-manager-api/go/core.pb.go @@ -374,6 +374,8 @@ const ( // Ghost workspaces are placeholders that pre-scale a cluster for faster workspace startup. They request the same amount of resources // as a regular workspace, but run no actual load. They're removed at will to make space for an actual workspace. WorkspaceType_GHOST WorkspaceType = 3 + // Imagebuild workspaces build a workspace, incl. their Gitpod layer. They run headless and have no direct user-interaction. + WorkspaceType_IMAGEBUILD WorkspaceType = 4 ) // Enum value maps for WorkspaceType. @@ -383,12 +385,14 @@ var ( 1: "PREBUILD", 2: "PROBE", 3: "GHOST", + 4: "IMAGEBUILD", } WorkspaceType_value = map[string]int32{ - "REGULAR": 0, - "PREBUILD": 1, - "PROBE": 2, - "GHOST": 3, + "REGULAR": 0, + "PREBUILD": 1, + "PROBE": 2, + "GHOST": 3, + "IMAGEBUILD": 4, } ) @@ -419,17 +423,89 @@ func (WorkspaceType) EnumDescriptor() ([]byte, []int) { return file_core_proto_rawDescGZIP(), []int{6} } +// MetadataFilter describes conditions for matching a set of workspaces. +// The values of the fields have to match exactly, and set values must match. +type MetadataFilter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // owner is the ID of the Gitpod user to whom we'll bill this workspace and who we consider responsible for its content + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + // meta_id is the workspace ID of this currently running workspace instance on the "meta pool" side + MetaId string `protobuf:"bytes,2,opt,name=meta_id,json=metaId,proto3" json:"meta_id,omitempty"` + // annotations must be a subset of the annotations of a workspace's metadata + Annotations map[string]string `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *MetadataFilter) Reset() { + *x = MetadataFilter{} + if protoimpl.UnsafeEnabled { + mi := &file_core_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetadataFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetadataFilter) ProtoMessage() {} + +func (x *MetadataFilter) ProtoReflect() protoreflect.Message { + mi := &file_core_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 MetadataFilter.ProtoReflect.Descriptor instead. +func (*MetadataFilter) Descriptor() ([]byte, []int) { + return file_core_proto_rawDescGZIP(), []int{0} +} + +func (x *MetadataFilter) GetOwner() string { + if x != nil { + return x.Owner + } + return "" +} + +func (x *MetadataFilter) GetMetaId() string { + if x != nil { + return x.MetaId + } + return "" +} + +func (x *MetadataFilter) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + // GetWorkspacesRequest requests a list of running workspaces type GetWorkspacesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // MustMatch can specify an exactly matching filter for listing workspaces. + // If not set, or all fields are empty, all workspaces are returned. + MustMatch *MetadataFilter `protobuf:"bytes,1,opt,name=must_match,json=mustMatch,proto3" json:"must_match,omitempty"` } func (x *GetWorkspacesRequest) Reset() { *x = GetWorkspacesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[0] + mi := &file_core_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -442,7 +518,7 @@ func (x *GetWorkspacesRequest) String() string { func (*GetWorkspacesRequest) ProtoMessage() {} func (x *GetWorkspacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[0] + mi := &file_core_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -455,7 +531,14 @@ func (x *GetWorkspacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkspacesRequest.ProtoReflect.Descriptor instead. func (*GetWorkspacesRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{0} + return file_core_proto_rawDescGZIP(), []int{1} +} + +func (x *GetWorkspacesRequest) GetMustMatch() *MetadataFilter { + if x != nil { + return x.MustMatch + } + return nil } // GetWorkspacesResponse is the response to a get w @@ -471,7 +554,7 @@ type GetWorkspacesResponse struct { func (x *GetWorkspacesResponse) Reset() { *x = GetWorkspacesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[1] + mi := &file_core_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -484,7 +567,7 @@ func (x *GetWorkspacesResponse) String() string { func (*GetWorkspacesResponse) ProtoMessage() {} func (x *GetWorkspacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[1] + mi := &file_core_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -497,7 +580,7 @@ func (x *GetWorkspacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkspacesResponse.ProtoReflect.Descriptor instead. func (*GetWorkspacesResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{1} + return file_core_proto_rawDescGZIP(), []int{2} } func (x *GetWorkspacesResponse) GetStatus() []*WorkspaceStatus { @@ -530,7 +613,7 @@ type StartWorkspaceRequest struct { func (x *StartWorkspaceRequest) Reset() { *x = StartWorkspaceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[2] + mi := &file_core_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -543,7 +626,7 @@ func (x *StartWorkspaceRequest) String() string { func (*StartWorkspaceRequest) ProtoMessage() {} func (x *StartWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[2] + mi := &file_core_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -556,7 +639,7 @@ func (x *StartWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartWorkspaceRequest.ProtoReflect.Descriptor instead. func (*StartWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{2} + return file_core_proto_rawDescGZIP(), []int{3} } func (x *StartWorkspaceRequest) GetId() string { @@ -606,7 +689,7 @@ type StartWorkspaceResponse struct { func (x *StartWorkspaceResponse) Reset() { *x = StartWorkspaceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[3] + mi := &file_core_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -619,7 +702,7 @@ func (x *StartWorkspaceResponse) String() string { func (*StartWorkspaceResponse) ProtoMessage() {} func (x *StartWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[3] + mi := &file_core_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -632,7 +715,7 @@ func (x *StartWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartWorkspaceResponse.ProtoReflect.Descriptor instead. func (*StartWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{3} + return file_core_proto_rawDescGZIP(), []int{4} } func (x *StartWorkspaceResponse) GetUrl() string { @@ -657,7 +740,7 @@ type StopWorkspaceRequest struct { func (x *StopWorkspaceRequest) Reset() { *x = StopWorkspaceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[4] + mi := &file_core_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -670,7 +753,7 @@ func (x *StopWorkspaceRequest) String() string { func (*StopWorkspaceRequest) ProtoMessage() {} func (x *StopWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[4] + mi := &file_core_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -683,7 +766,7 @@ func (x *StopWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopWorkspaceRequest.ProtoReflect.Descriptor instead. func (*StopWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{4} + return file_core_proto_rawDescGZIP(), []int{5} } func (x *StopWorkspaceRequest) GetId() string { @@ -710,7 +793,7 @@ type StopWorkspaceResponse struct { func (x *StopWorkspaceResponse) Reset() { *x = StopWorkspaceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[5] + mi := &file_core_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -723,7 +806,7 @@ func (x *StopWorkspaceResponse) String() string { func (*StopWorkspaceResponse) ProtoMessage() {} func (x *StopWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[5] + mi := &file_core_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -736,7 +819,7 @@ func (x *StopWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopWorkspaceResponse.ProtoReflect.Descriptor instead. func (*StopWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{5} + return file_core_proto_rawDescGZIP(), []int{6} } // DescribeWorkspaceRequest requests the status of a workspace @@ -752,7 +835,7 @@ type DescribeWorkspaceRequest struct { func (x *DescribeWorkspaceRequest) Reset() { *x = DescribeWorkspaceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[6] + mi := &file_core_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -765,7 +848,7 @@ func (x *DescribeWorkspaceRequest) String() string { func (*DescribeWorkspaceRequest) ProtoMessage() {} func (x *DescribeWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[6] + mi := &file_core_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -778,7 +861,7 @@ func (x *DescribeWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeWorkspaceRequest.ProtoReflect.Descriptor instead. func (*DescribeWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{6} + return file_core_proto_rawDescGZIP(), []int{7} } func (x *DescribeWorkspaceRequest) GetId() string { @@ -802,7 +885,7 @@ type DescribeWorkspaceResponse struct { func (x *DescribeWorkspaceResponse) Reset() { *x = DescribeWorkspaceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[7] + mi := &file_core_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -815,7 +898,7 @@ func (x *DescribeWorkspaceResponse) String() string { func (*DescribeWorkspaceResponse) ProtoMessage() {} func (x *DescribeWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[7] + mi := &file_core_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -828,7 +911,7 @@ func (x *DescribeWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DescribeWorkspaceResponse.ProtoReflect.Descriptor instead. func (*DescribeWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{7} + return file_core_proto_rawDescGZIP(), []int{8} } func (x *DescribeWorkspaceResponse) GetStatus() *WorkspaceStatus { @@ -850,12 +933,16 @@ type SubscribeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // MustMatch can specify an exactly matching filter for listening to workspaces. + // If not set, or all fields are empty, all workspace status updates or log output are returned. + MustMatch *MetadataFilter `protobuf:"bytes,1,opt,name=must_match,json=mustMatch,proto3" json:"must_match,omitempty"` } func (x *SubscribeRequest) Reset() { *x = SubscribeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[8] + mi := &file_core_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -868,7 +955,7 @@ func (x *SubscribeRequest) String() string { func (*SubscribeRequest) ProtoMessage() {} func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[8] + mi := &file_core_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -881,7 +968,14 @@ func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubscribeRequest.ProtoReflect.Descriptor instead. func (*SubscribeRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{8} + return file_core_proto_rawDescGZIP(), []int{9} +} + +func (x *SubscribeRequest) GetMustMatch() *MetadataFilter { + if x != nil { + return x.MustMatch + } + return nil } // SubscribeResponse notifies a client when a workspace's status changes @@ -900,7 +994,7 @@ type SubscribeResponse struct { func (x *SubscribeResponse) Reset() { *x = SubscribeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[9] + mi := &file_core_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -913,7 +1007,7 @@ func (x *SubscribeResponse) String() string { func (*SubscribeResponse) ProtoMessage() {} func (x *SubscribeResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[9] + mi := &file_core_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -926,7 +1020,7 @@ func (x *SubscribeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubscribeResponse.ProtoReflect.Descriptor instead. func (*SubscribeResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{9} + return file_core_proto_rawDescGZIP(), []int{10} } func (m *SubscribeResponse) GetPayload() isSubscribeResponse_Payload { @@ -988,7 +1082,7 @@ type MarkActiveRequest struct { func (x *MarkActiveRequest) Reset() { *x = MarkActiveRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[10] + mi := &file_core_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1001,7 +1095,7 @@ func (x *MarkActiveRequest) String() string { func (*MarkActiveRequest) ProtoMessage() {} func (x *MarkActiveRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[10] + mi := &file_core_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1014,7 +1108,7 @@ func (x *MarkActiveRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MarkActiveRequest.ProtoReflect.Descriptor instead. func (*MarkActiveRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{10} + return file_core_proto_rawDescGZIP(), []int{11} } func (x *MarkActiveRequest) GetId() string { @@ -1041,7 +1135,7 @@ type MarkActiveResponse struct { func (x *MarkActiveResponse) Reset() { *x = MarkActiveResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[11] + mi := &file_core_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1054,7 +1148,7 @@ func (x *MarkActiveResponse) String() string { func (*MarkActiveResponse) ProtoMessage() {} func (x *MarkActiveResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[11] + mi := &file_core_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1067,7 +1161,7 @@ func (x *MarkActiveResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MarkActiveResponse.ProtoReflect.Descriptor instead. func (*MarkActiveResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{11} + return file_core_proto_rawDescGZIP(), []int{12} } // SetTimeoutRequest configures the timeout of a workspace @@ -1085,7 +1179,7 @@ type SetTimeoutRequest struct { func (x *SetTimeoutRequest) Reset() { *x = SetTimeoutRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[12] + mi := &file_core_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1098,7 +1192,7 @@ func (x *SetTimeoutRequest) String() string { func (*SetTimeoutRequest) ProtoMessage() {} func (x *SetTimeoutRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[12] + mi := &file_core_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1111,7 +1205,7 @@ func (x *SetTimeoutRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetTimeoutRequest.ProtoReflect.Descriptor instead. func (*SetTimeoutRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{12} + return file_core_proto_rawDescGZIP(), []int{13} } func (x *SetTimeoutRequest) GetId() string { @@ -1138,7 +1232,7 @@ type SetTimeoutResponse struct { func (x *SetTimeoutResponse) Reset() { *x = SetTimeoutResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[13] + mi := &file_core_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1151,7 +1245,7 @@ func (x *SetTimeoutResponse) String() string { func (*SetTimeoutResponse) ProtoMessage() {} func (x *SetTimeoutResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[13] + mi := &file_core_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1164,7 +1258,7 @@ func (x *SetTimeoutResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetTimeoutResponse.ProtoReflect.Descriptor instead. func (*SetTimeoutResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{13} + return file_core_proto_rawDescGZIP(), []int{14} } // ControlPortRequest exposes or un-exposes networking ports of a workspace @@ -1185,7 +1279,7 @@ type ControlPortRequest struct { func (x *ControlPortRequest) Reset() { *x = ControlPortRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[14] + mi := &file_core_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1198,7 +1292,7 @@ func (x *ControlPortRequest) String() string { func (*ControlPortRequest) ProtoMessage() {} func (x *ControlPortRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[14] + mi := &file_core_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1211,7 +1305,7 @@ func (x *ControlPortRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ControlPortRequest.ProtoReflect.Descriptor instead. func (*ControlPortRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{14} + return file_core_proto_rawDescGZIP(), []int{15} } func (x *ControlPortRequest) GetId() string { @@ -1245,7 +1339,7 @@ type ControlPortResponse struct { func (x *ControlPortResponse) Reset() { *x = ControlPortResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[15] + mi := &file_core_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1258,7 +1352,7 @@ func (x *ControlPortResponse) String() string { func (*ControlPortResponse) ProtoMessage() {} func (x *ControlPortResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[15] + mi := &file_core_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1271,7 +1365,7 @@ func (x *ControlPortResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ControlPortResponse.ProtoReflect.Descriptor instead. func (*ControlPortResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{15} + return file_core_proto_rawDescGZIP(), []int{16} } // TakeSnapshotRequest creates a copy of the workspace content. This copy can be used to initialize a new workspace. @@ -1287,7 +1381,7 @@ type TakeSnapshotRequest struct { func (x *TakeSnapshotRequest) Reset() { *x = TakeSnapshotRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[16] + mi := &file_core_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1300,7 +1394,7 @@ func (x *TakeSnapshotRequest) String() string { func (*TakeSnapshotRequest) ProtoMessage() {} func (x *TakeSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[16] + mi := &file_core_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1313,7 +1407,7 @@ func (x *TakeSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TakeSnapshotRequest.ProtoReflect.Descriptor instead. func (*TakeSnapshotRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{16} + return file_core_proto_rawDescGZIP(), []int{17} } func (x *TakeSnapshotRequest) GetId() string { @@ -1336,7 +1430,7 @@ type TakeSnapshotResponse struct { func (x *TakeSnapshotResponse) Reset() { *x = TakeSnapshotResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[17] + mi := &file_core_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1349,7 +1443,7 @@ func (x *TakeSnapshotResponse) String() string { func (*TakeSnapshotResponse) ProtoMessage() {} func (x *TakeSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[17] + mi := &file_core_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1362,7 +1456,7 @@ func (x *TakeSnapshotResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TakeSnapshotResponse.ProtoReflect.Descriptor instead. func (*TakeSnapshotResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{17} + return file_core_proto_rawDescGZIP(), []int{18} } func (x *TakeSnapshotResponse) GetUrl() string { @@ -1387,7 +1481,7 @@ type ControlAdmissionRequest struct { func (x *ControlAdmissionRequest) Reset() { *x = ControlAdmissionRequest{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[18] + mi := &file_core_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1400,7 +1494,7 @@ func (x *ControlAdmissionRequest) String() string { func (*ControlAdmissionRequest) ProtoMessage() {} func (x *ControlAdmissionRequest) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[18] + mi := &file_core_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1413,7 +1507,7 @@ func (x *ControlAdmissionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ControlAdmissionRequest.ProtoReflect.Descriptor instead. func (*ControlAdmissionRequest) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{18} + return file_core_proto_rawDescGZIP(), []int{19} } func (x *ControlAdmissionRequest) GetId() string { @@ -1439,7 +1533,7 @@ type ControlAdmissionResponse struct { func (x *ControlAdmissionResponse) Reset() { *x = ControlAdmissionResponse{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[19] + mi := &file_core_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1452,7 +1546,7 @@ func (x *ControlAdmissionResponse) String() string { func (*ControlAdmissionResponse) ProtoMessage() {} func (x *ControlAdmissionResponse) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[19] + mi := &file_core_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1465,7 +1559,7 @@ func (x *ControlAdmissionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ControlAdmissionResponse.ProtoReflect.Descriptor instead. func (*ControlAdmissionResponse) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{19} + return file_core_proto_rawDescGZIP(), []int{20} } // WorkspaceStatus describes a workspace status @@ -1499,7 +1593,7 @@ type WorkspaceStatus struct { func (x *WorkspaceStatus) Reset() { *x = WorkspaceStatus{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[20] + mi := &file_core_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1512,7 +1606,7 @@ func (x *WorkspaceStatus) String() string { func (*WorkspaceStatus) ProtoMessage() {} func (x *WorkspaceStatus) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[20] + mi := &file_core_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1525,7 +1619,7 @@ func (x *WorkspaceStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceStatus.ProtoReflect.Descriptor instead. func (*WorkspaceStatus) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{20} + return file_core_proto_rawDescGZIP(), []int{21} } func (x *WorkspaceStatus) GetId() string { @@ -1616,7 +1710,7 @@ type WorkspaceSpec struct { func (x *WorkspaceSpec) Reset() { *x = WorkspaceSpec{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[21] + mi := &file_core_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1629,7 +1723,7 @@ func (x *WorkspaceSpec) String() string { func (*WorkspaceSpec) ProtoMessage() {} func (x *WorkspaceSpec) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[21] + mi := &file_core_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1642,7 +1736,7 @@ func (x *WorkspaceSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceSpec.ProtoReflect.Descriptor instead. func (*WorkspaceSpec) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{21} + return file_core_proto_rawDescGZIP(), []int{22} } func (x *WorkspaceSpec) GetWorkspaceImage() string { @@ -1713,7 +1807,7 @@ type PortSpec struct { func (x *PortSpec) Reset() { *x = PortSpec{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[22] + mi := &file_core_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1726,7 +1820,7 @@ func (x *PortSpec) String() string { func (*PortSpec) ProtoMessage() {} func (x *PortSpec) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[22] + mi := &file_core_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1739,7 +1833,7 @@ func (x *PortSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use PortSpec.ProtoReflect.Descriptor instead. func (*PortSpec) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{22} + return file_core_proto_rawDescGZIP(), []int{23} } func (x *PortSpec) GetPort() uint32 { @@ -1803,7 +1897,7 @@ type WorkspaceConditions struct { func (x *WorkspaceConditions) Reset() { *x = WorkspaceConditions{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[23] + mi := &file_core_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1816,7 +1910,7 @@ func (x *WorkspaceConditions) String() string { func (*WorkspaceConditions) ProtoMessage() {} func (x *WorkspaceConditions) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[23] + mi := &file_core_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1829,7 +1923,7 @@ func (x *WorkspaceConditions) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceConditions.ProtoReflect.Descriptor instead. func (*WorkspaceConditions) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{23} + return file_core_proto_rawDescGZIP(), []int{24} } func (x *WorkspaceConditions) GetFailed() string { @@ -1914,12 +2008,15 @@ type WorkspaceMetadata struct { MetaId string `protobuf:"bytes,2,opt,name=meta_id,json=metaId,proto3" json:"meta_id,omitempty"` // started_at is the time when this workspace was started. Consider this field read-only, i.e. setting in a request will have no effect. StartedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"` + // Annotations are key/value pairs that gets attached to the workspace. + // This is primarily intended for annotating headless workspace loads. + Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *WorkspaceMetadata) Reset() { *x = WorkspaceMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[24] + mi := &file_core_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1932,7 +2029,7 @@ func (x *WorkspaceMetadata) String() string { func (*WorkspaceMetadata) ProtoMessage() {} func (x *WorkspaceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[24] + mi := &file_core_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1945,7 +2042,7 @@ func (x *WorkspaceMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceMetadata.ProtoReflect.Descriptor instead. func (*WorkspaceMetadata) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{24} + return file_core_proto_rawDescGZIP(), []int{25} } func (x *WorkspaceMetadata) GetOwner() string { @@ -1969,6 +2066,13 @@ func (x *WorkspaceMetadata) GetStartedAt() *timestamppb.Timestamp { return nil } +func (x *WorkspaceMetadata) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + // WorkspaceRuntimeInfo details the workspace's runtime, e.g. executing system, node other information // about the environment the workspace runs in. This information serves a diangostic purpose only and // should not be directly acted upon. @@ -1988,7 +2092,7 @@ type WorkspaceRuntimeInfo struct { func (x *WorkspaceRuntimeInfo) Reset() { *x = WorkspaceRuntimeInfo{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[25] + mi := &file_core_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2001,7 +2105,7 @@ func (x *WorkspaceRuntimeInfo) String() string { func (*WorkspaceRuntimeInfo) ProtoMessage() {} func (x *WorkspaceRuntimeInfo) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[25] + mi := &file_core_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2014,7 +2118,7 @@ func (x *WorkspaceRuntimeInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceRuntimeInfo.ProtoReflect.Descriptor instead. func (*WorkspaceRuntimeInfo) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{25} + return file_core_proto_rawDescGZIP(), []int{26} } func (x *WorkspaceRuntimeInfo) GetNodeName() string { @@ -2054,7 +2158,7 @@ type WorkspaceAuthentication struct { func (x *WorkspaceAuthentication) Reset() { *x = WorkspaceAuthentication{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[26] + mi := &file_core_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2067,7 +2171,7 @@ func (x *WorkspaceAuthentication) String() string { func (*WorkspaceAuthentication) ProtoMessage() {} func (x *WorkspaceAuthentication) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[26] + mi := &file_core_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2080,7 +2184,7 @@ func (x *WorkspaceAuthentication) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceAuthentication.ProtoReflect.Descriptor instead. func (*WorkspaceAuthentication) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{26} + return file_core_proto_rawDescGZIP(), []int{27} } func (x *WorkspaceAuthentication) GetAdmission() AdmissionLevel { @@ -2130,7 +2234,7 @@ type StartWorkspaceSpec struct { func (x *StartWorkspaceSpec) Reset() { *x = StartWorkspaceSpec{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[27] + mi := &file_core_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2143,7 +2247,7 @@ func (x *StartWorkspaceSpec) String() string { func (*StartWorkspaceSpec) ProtoMessage() {} func (x *StartWorkspaceSpec) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[27] + mi := &file_core_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2156,7 +2260,7 @@ func (x *StartWorkspaceSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use StartWorkspaceSpec.ProtoReflect.Descriptor instead. func (*StartWorkspaceSpec) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{27} + return file_core_proto_rawDescGZIP(), []int{28} } func (x *StartWorkspaceSpec) GetWorkspaceImage() string { @@ -2251,7 +2355,7 @@ type GitSpec struct { func (x *GitSpec) Reset() { *x = GitSpec{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[28] + mi := &file_core_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2264,7 +2368,7 @@ func (x *GitSpec) String() string { func (*GitSpec) ProtoMessage() {} func (x *GitSpec) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[28] + mi := &file_core_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2277,7 +2381,7 @@ func (x *GitSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use GitSpec.ProtoReflect.Descriptor instead. func (*GitSpec) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{28} + return file_core_proto_rawDescGZIP(), []int{29} } func (x *GitSpec) GetUsername() string { @@ -2307,7 +2411,7 @@ type EnvironmentVariable struct { func (x *EnvironmentVariable) Reset() { *x = EnvironmentVariable{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[29] + mi := &file_core_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2320,7 +2424,7 @@ func (x *EnvironmentVariable) String() string { func (*EnvironmentVariable) ProtoMessage() {} func (x *EnvironmentVariable) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[29] + mi := &file_core_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2333,7 +2437,7 @@ func (x *EnvironmentVariable) ProtoReflect() protoreflect.Message { // Deprecated: Use EnvironmentVariable.ProtoReflect.Descriptor instead. func (*EnvironmentVariable) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{29} + return file_core_proto_rawDescGZIP(), []int{30} } func (x *EnvironmentVariable) GetName() string { @@ -2367,7 +2471,7 @@ type WorkspaceLogMessage struct { func (x *WorkspaceLogMessage) Reset() { *x = WorkspaceLogMessage{} if protoimpl.UnsafeEnabled { - mi := &file_core_proto_msgTypes[30] + mi := &file_core_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2380,7 +2484,7 @@ func (x *WorkspaceLogMessage) String() string { func (*WorkspaceLogMessage) ProtoMessage() {} func (x *WorkspaceLogMessage) ProtoReflect() protoreflect.Message { - mi := &file_core_proto_msgTypes[30] + mi := &file_core_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2393,7 +2497,7 @@ func (x *WorkspaceLogMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceLogMessage.ProtoReflect.Descriptor instead. func (*WorkspaceLogMessage) Descriptor() ([]byte, []int) { - return file_core_proto_rawDescGZIP(), []int{30} + return file_core_proto_rawDescGZIP(), []int{31} } func (x *WorkspaceLogMessage) GetId() string { @@ -2425,339 +2529,368 @@ var file_core_proto_rawDesc = []byte{ 0x76, 0x69, 0x63, 0x65, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x22, 0x16, 0x0a, 0x14, 0x47, - 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x47, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xe3, 0x01, 0x0a, - 0x15, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x34, 0x0a, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, - 0x65, 0x63, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x05, - 0x10, 0x06, 0x22, 0x2a, 0x0a, 0x16, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, - 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x5a, - 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, - 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x74, - 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, - 0x6f, 0x0a, 0x19, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, 0x0a, 0x0c, - 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x22, 0x12, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0xf9, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x03, - 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, - 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3c, 0x0a, 0x06, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 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, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x22, 0x3b, 0x0a, 0x11, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x22, 0x14, 0x0a, - 0x12, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x14, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x61, 0x0a, 0x12, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, - 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0x15, 0x0a, - 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, 0x13, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, - 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x28, 0x0a, 0x14, 0x54, - 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x56, 0x0a, 0x17, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x1a, 0x0a, - 0x18, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9e, 0x03, 0x0a, 0x0f, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2b, 0x0a, - 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, - 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x01, 0x0a, 0x0e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x14, + 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, 0x49, 0x64, 0x12, 0x48, 0x0a, + 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x4c, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x34, 0x0a, 0x0a, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x09, 0x6d, 0x75, 0x73, 0x74, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x47, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xe3, + 0x01, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, + 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, + 0x73, 0x70, 0x65, 0x63, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, + 0x08, 0x05, 0x10, 0x06, 0x22, 0x2a, 0x0a, 0x16, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x22, 0x5a, 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x17, 0x0a, 0x15, + 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x6f, 0x0a, 0x19, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x2d, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, - 0x35, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0xfd, 0x01, 0x0a, 0x0d, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, - 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, - 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x68, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x10, - 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, - 0x12, 0x34, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, - 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x7f, 0x0a, 0x08, 0x50, 0x6f, - 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, - 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, - 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xc6, 0x04, 0x0a, 0x13, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x44, 0x0a, 0x0e, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, - 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, - 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x70, 0x75, - 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x0e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, - 0x6f, 0x6c, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, - 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x51, 0x0a, - 0x15, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x13, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x12, 0x39, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, - 0x6c, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x11, 0x6e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, + 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x22, 0x48, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, + 0x61, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x52, 0x09, 0x6d, 0x75, 0x73, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xf9, 0x01, 0x0a, + 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, + 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 0x09, 0x0a, + 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x3b, 0x0a, 0x11, 0x4d, 0x61, 0x72, 0x6b, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x11, 0x53, + 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x14, 0x0a, 0x12, + 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x61, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x6f, + 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, + 0x12, 0x23, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, + 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0x15, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, 0x13, + 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x28, 0x0a, 0x14, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x56, 0x0a, + 0x17, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x1a, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x9e, 0x03, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x04, 0x73, + 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, + 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, + 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, 0x61, + 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x6f, - 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x4a, 0x0a, 0x13, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x09, 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, - 0x11, 0x66, 0x69, 0x72, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x74, - 0x61, 0x73, 0x6b, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x12, 0x68, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x54, 0x61, 0x73, 0x6b, 0x46, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x22, 0x7d, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, - 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x22, 0x67, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x64, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6f, 0x64, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x70, 0x22, 0x6f, 0x0a, 0x17, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8e, 0x04, - 0x0a, 0x12, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x6e, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x32, + 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, + 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x61, 0x75, + 0x74, 0x68, 0x22, 0xfd, 0x01, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x0c, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x46, 0x0a, 0x0b, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, - 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, - 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, - 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, - 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x5f, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, - 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, - 0x03, 0x67, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x03, 0x67, 0x69, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x33, 0x0a, 0x09, 0x61, 0x64, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, - 0x0a, 0x07, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x3f, 0x0a, 0x13, 0x45, - 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x13, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x2a, 0x34, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, - 0x52, 0x4d, 0x41, 0x4c, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4d, 0x4d, 0x45, - 0x44, 0x49, 0x41, 0x54, 0x45, 0x4c, 0x59, 0x10, 0x01, 0x2a, 0x3a, 0x0a, 0x0e, 0x41, 0x64, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x10, 0x41, - 0x44, 0x4d, 0x49, 0x54, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, - 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x44, 0x4d, 0x49, 0x54, 0x5f, 0x45, 0x56, 0x45, 0x52, 0x59, - 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x2a, 0x49, 0x0a, 0x0e, 0x50, 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x4f, 0x52, 0x54, 0x5f, - 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, - 0x54, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, - 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x01, - 0x2a, 0x38, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, - 0x4c, 0x53, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, - 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x02, 0x2a, 0x83, 0x01, 0x0a, 0x0e, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x0b, 0x0a, - 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, - 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x45, 0x41, 0x54, - 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, - 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, - 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x52, 0x55, 0x50, - 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, - 0x47, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x06, - 0x2a, 0x68, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, - 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x55, 0x4c, 0x4c, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x53, - 0x50, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x55, 0x50, 0x10, 0x04, 0x12, 0x13, 0x0a, - 0x0f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, - 0x10, 0x05, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x22, 0x04, 0x08, 0x02, 0x10, 0x02, 0x22, 0x04, - 0x08, 0x03, 0x10, 0x03, 0x22, 0x04, 0x08, 0x06, 0x10, 0x06, 0x2a, 0x40, 0x0a, 0x0d, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, - 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, - 0x55, 0x49, 0x4c, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, - 0x02, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x03, 0x32, 0x91, 0x06, 0x0a, - 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x12, 0x4c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4f, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x4c, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, - 0x0a, 0x11, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x17, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0a, - 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, - 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x43, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, - 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, - 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, - 0x0a, 0x0c, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1a, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x10, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, - 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, - 0x77, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x65, + 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x68, 0x65, + 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, + 0x73, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, + 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x28, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x77, + 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x22, 0x7f, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, + 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, + 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x75, 0x72, 0x6c, 0x22, 0xc6, 0x04, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x44, 0x0a, + 0x0e, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6d, 0x61, + 0x67, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, + 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x51, 0x0a, 0x15, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x62, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x6f, 0x6f, 0x6c, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, + 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x11, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6e, + 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, + 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0f, 0x6e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x4a, + 0x0a, 0x13, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x09, 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, 0x11, 0x66, 0x69, 0x72, 0x73, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x65, + 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x68, 0x65, 0x61, 0x64, 0x6c, 0x65, + 0x73, 0x73, 0x54, 0x61, 0x73, 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x8a, 0x02, 0x0a, + 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x61, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, 0x49, + 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x4b, 0x0a, 0x0b, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x67, 0x0a, 0x14, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x70, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x70, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, + 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, + 0x49, 0x70, 0x22, 0x6f, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, + 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x22, 0x8e, 0x04, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, + 0x12, 0x40, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x46, 0x6c, 0x61, 0x67, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, + 0x67, 0x73, 0x12, 0x46, 0x0a, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x52, 0x0b, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x6f, + 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, + 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, + 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, + 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, + 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x6f, 0x75, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x03, 0x67, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, + 0x52, 0x03, 0x67, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, + 0x33, 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, 0x0a, 0x07, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, + 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, + 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x22, 0x3f, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x75, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, + 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x34, 0x0a, 0x13, 0x53, 0x74, 0x6f, + 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x0f, + 0x0a, 0x0b, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x4c, 0x59, 0x10, 0x01, 0x2a, + 0x3a, 0x0a, 0x0e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x44, 0x4d, 0x49, 0x54, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, + 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x44, 0x4d, 0x49, 0x54, + 0x5f, 0x45, 0x56, 0x45, 0x52, 0x59, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x2a, 0x49, 0x0a, 0x0e, 0x50, + 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, + 0x17, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, + 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x4f, + 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x55, + 0x42, 0x4c, 0x49, 0x43, 0x10, 0x01, 0x2a, 0x38, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, + 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54, + 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x02, + 0x2a, 0x83, 0x01, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, + 0x61, 0x73, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, 0x0a, + 0x08, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x49, + 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0b, 0x0a, + 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, + 0x54, 0x45, 0x52, 0x52, 0x55, 0x50, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x53, + 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, + 0x50, 0x50, 0x45, 0x44, 0x10, 0x06, 0x2a, 0x68, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, + 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x55, 0x4c, 0x4c, + 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x55, + 0x50, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x10, 0x05, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x22, 0x04, + 0x08, 0x02, 0x10, 0x02, 0x22, 0x04, 0x08, 0x03, 0x10, 0x03, 0x22, 0x04, 0x08, 0x06, 0x10, 0x06, + 0x2a, 0x50, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x00, 0x12, 0x0c, + 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, + 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x48, 0x4f, 0x53, 0x54, + 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x44, + 0x10, 0x04, 0x32, 0x91, 0x06, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x65, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x6f, + 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, + 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x73, 0x6d, + 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, + 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x17, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x77, 0x73, 0x6d, + 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x65, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0b, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0c, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x55, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, + 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2773,7 +2906,7 @@ func file_core_proto_rawDescGZIP() []byte { } var file_core_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_core_proto_msgTypes = make([]protoimpl.MessageInfo, 32) +var file_core_proto_msgTypes = make([]protoimpl.MessageInfo, 35) var file_core_proto_goTypes = []interface{}{ (StopWorkspacePolicy)(0), // 0: wsman.StopWorkspacePolicy (AdmissionLevel)(0), // 1: wsman.AdmissionLevel @@ -2782,104 +2915,111 @@ var file_core_proto_goTypes = []interface{}{ (WorkspacePhase)(0), // 4: wsman.WorkspacePhase (WorkspaceFeatureFlag)(0), // 5: wsman.WorkspaceFeatureFlag (WorkspaceType)(0), // 6: wsman.WorkspaceType - (*GetWorkspacesRequest)(nil), // 7: wsman.GetWorkspacesRequest - (*GetWorkspacesResponse)(nil), // 8: wsman.GetWorkspacesResponse - (*StartWorkspaceRequest)(nil), // 9: wsman.StartWorkspaceRequest - (*StartWorkspaceResponse)(nil), // 10: wsman.StartWorkspaceResponse - (*StopWorkspaceRequest)(nil), // 11: wsman.StopWorkspaceRequest - (*StopWorkspaceResponse)(nil), // 12: wsman.StopWorkspaceResponse - (*DescribeWorkspaceRequest)(nil), // 13: wsman.DescribeWorkspaceRequest - (*DescribeWorkspaceResponse)(nil), // 14: wsman.DescribeWorkspaceResponse - (*SubscribeRequest)(nil), // 15: wsman.SubscribeRequest - (*SubscribeResponse)(nil), // 16: wsman.SubscribeResponse - (*MarkActiveRequest)(nil), // 17: wsman.MarkActiveRequest - (*MarkActiveResponse)(nil), // 18: wsman.MarkActiveResponse - (*SetTimeoutRequest)(nil), // 19: wsman.SetTimeoutRequest - (*SetTimeoutResponse)(nil), // 20: wsman.SetTimeoutResponse - (*ControlPortRequest)(nil), // 21: wsman.ControlPortRequest - (*ControlPortResponse)(nil), // 22: wsman.ControlPortResponse - (*TakeSnapshotRequest)(nil), // 23: wsman.TakeSnapshotRequest - (*TakeSnapshotResponse)(nil), // 24: wsman.TakeSnapshotResponse - (*ControlAdmissionRequest)(nil), // 25: wsman.ControlAdmissionRequest - (*ControlAdmissionResponse)(nil), // 26: wsman.ControlAdmissionResponse - (*WorkspaceStatus)(nil), // 27: wsman.WorkspaceStatus - (*WorkspaceSpec)(nil), // 28: wsman.WorkspaceSpec - (*PortSpec)(nil), // 29: wsman.PortSpec - (*WorkspaceConditions)(nil), // 30: wsman.WorkspaceConditions - (*WorkspaceMetadata)(nil), // 31: wsman.WorkspaceMetadata - (*WorkspaceRuntimeInfo)(nil), // 32: wsman.WorkspaceRuntimeInfo - (*WorkspaceAuthentication)(nil), // 33: wsman.WorkspaceAuthentication - (*StartWorkspaceSpec)(nil), // 34: wsman.StartWorkspaceSpec - (*GitSpec)(nil), // 35: wsman.GitSpec - (*EnvironmentVariable)(nil), // 36: wsman.EnvironmentVariable - (*WorkspaceLogMessage)(nil), // 37: wsman.WorkspaceLogMessage - nil, // 38: wsman.SubscribeResponse.HeaderEntry - (*api.GitStatus)(nil), // 39: contentservice.GitStatus - (*timestamppb.Timestamp)(nil), // 40: google.protobuf.Timestamp - (*api.WorkspaceInitializer)(nil), // 41: contentservice.WorkspaceInitializer + (*MetadataFilter)(nil), // 7: wsman.MetadataFilter + (*GetWorkspacesRequest)(nil), // 8: wsman.GetWorkspacesRequest + (*GetWorkspacesResponse)(nil), // 9: wsman.GetWorkspacesResponse + (*StartWorkspaceRequest)(nil), // 10: wsman.StartWorkspaceRequest + (*StartWorkspaceResponse)(nil), // 11: wsman.StartWorkspaceResponse + (*StopWorkspaceRequest)(nil), // 12: wsman.StopWorkspaceRequest + (*StopWorkspaceResponse)(nil), // 13: wsman.StopWorkspaceResponse + (*DescribeWorkspaceRequest)(nil), // 14: wsman.DescribeWorkspaceRequest + (*DescribeWorkspaceResponse)(nil), // 15: wsman.DescribeWorkspaceResponse + (*SubscribeRequest)(nil), // 16: wsman.SubscribeRequest + (*SubscribeResponse)(nil), // 17: wsman.SubscribeResponse + (*MarkActiveRequest)(nil), // 18: wsman.MarkActiveRequest + (*MarkActiveResponse)(nil), // 19: wsman.MarkActiveResponse + (*SetTimeoutRequest)(nil), // 20: wsman.SetTimeoutRequest + (*SetTimeoutResponse)(nil), // 21: wsman.SetTimeoutResponse + (*ControlPortRequest)(nil), // 22: wsman.ControlPortRequest + (*ControlPortResponse)(nil), // 23: wsman.ControlPortResponse + (*TakeSnapshotRequest)(nil), // 24: wsman.TakeSnapshotRequest + (*TakeSnapshotResponse)(nil), // 25: wsman.TakeSnapshotResponse + (*ControlAdmissionRequest)(nil), // 26: wsman.ControlAdmissionRequest + (*ControlAdmissionResponse)(nil), // 27: wsman.ControlAdmissionResponse + (*WorkspaceStatus)(nil), // 28: wsman.WorkspaceStatus + (*WorkspaceSpec)(nil), // 29: wsman.WorkspaceSpec + (*PortSpec)(nil), // 30: wsman.PortSpec + (*WorkspaceConditions)(nil), // 31: wsman.WorkspaceConditions + (*WorkspaceMetadata)(nil), // 32: wsman.WorkspaceMetadata + (*WorkspaceRuntimeInfo)(nil), // 33: wsman.WorkspaceRuntimeInfo + (*WorkspaceAuthentication)(nil), // 34: wsman.WorkspaceAuthentication + (*StartWorkspaceSpec)(nil), // 35: wsman.StartWorkspaceSpec + (*GitSpec)(nil), // 36: wsman.GitSpec + (*EnvironmentVariable)(nil), // 37: wsman.EnvironmentVariable + (*WorkspaceLogMessage)(nil), // 38: wsman.WorkspaceLogMessage + nil, // 39: wsman.MetadataFilter.AnnotationsEntry + nil, // 40: wsman.SubscribeResponse.HeaderEntry + nil, // 41: wsman.WorkspaceMetadata.AnnotationsEntry + (*api.GitStatus)(nil), // 42: contentservice.GitStatus + (*timestamppb.Timestamp)(nil), // 43: google.protobuf.Timestamp + (*api.WorkspaceInitializer)(nil), // 44: contentservice.WorkspaceInitializer } var file_core_proto_depIdxs = []int32{ - 27, // 0: wsman.GetWorkspacesResponse.status:type_name -> wsman.WorkspaceStatus - 31, // 1: wsman.StartWorkspaceRequest.metadata:type_name -> wsman.WorkspaceMetadata - 34, // 2: wsman.StartWorkspaceRequest.spec:type_name -> wsman.StartWorkspaceSpec - 6, // 3: wsman.StartWorkspaceRequest.type:type_name -> wsman.WorkspaceType - 0, // 4: wsman.StopWorkspaceRequest.policy:type_name -> wsman.StopWorkspacePolicy - 27, // 5: wsman.DescribeWorkspaceResponse.status:type_name -> wsman.WorkspaceStatus - 27, // 6: wsman.SubscribeResponse.status:type_name -> wsman.WorkspaceStatus - 37, // 7: wsman.SubscribeResponse.log:type_name -> wsman.WorkspaceLogMessage - 38, // 8: wsman.SubscribeResponse.header:type_name -> wsman.SubscribeResponse.HeaderEntry - 29, // 9: wsman.ControlPortRequest.spec:type_name -> wsman.PortSpec - 1, // 10: wsman.ControlAdmissionRequest.level:type_name -> wsman.AdmissionLevel - 31, // 11: wsman.WorkspaceStatus.metadata:type_name -> wsman.WorkspaceMetadata - 28, // 12: wsman.WorkspaceStatus.spec:type_name -> wsman.WorkspaceSpec - 4, // 13: wsman.WorkspaceStatus.phase:type_name -> wsman.WorkspacePhase - 30, // 14: wsman.WorkspaceStatus.conditions:type_name -> wsman.WorkspaceConditions - 39, // 15: wsman.WorkspaceStatus.repo:type_name -> contentservice.GitStatus - 32, // 16: wsman.WorkspaceStatus.runtime:type_name -> wsman.WorkspaceRuntimeInfo - 33, // 17: wsman.WorkspaceStatus.auth:type_name -> wsman.WorkspaceAuthentication - 29, // 18: wsman.WorkspaceSpec.exposed_ports:type_name -> wsman.PortSpec - 6, // 19: wsman.WorkspaceSpec.type:type_name -> wsman.WorkspaceType - 2, // 20: wsman.PortSpec.visibility:type_name -> wsman.PortVisibility - 3, // 21: wsman.WorkspaceConditions.pulling_images:type_name -> wsman.WorkspaceConditionBool - 3, // 22: wsman.WorkspaceConditions.service_exists:type_name -> wsman.WorkspaceConditionBool - 3, // 23: wsman.WorkspaceConditions.final_backup_complete:type_name -> wsman.WorkspaceConditionBool - 3, // 24: wsman.WorkspaceConditions.deployed:type_name -> wsman.WorkspaceConditionBool - 3, // 25: wsman.WorkspaceConditions.network_not_ready:type_name -> wsman.WorkspaceConditionBool - 40, // 26: wsman.WorkspaceConditions.first_user_activity:type_name -> google.protobuf.Timestamp - 40, // 27: wsman.WorkspaceMetadata.started_at:type_name -> google.protobuf.Timestamp - 1, // 28: wsman.WorkspaceAuthentication.admission:type_name -> wsman.AdmissionLevel - 5, // 29: wsman.StartWorkspaceSpec.feature_flags:type_name -> wsman.WorkspaceFeatureFlag - 41, // 30: wsman.StartWorkspaceSpec.initializer:type_name -> contentservice.WorkspaceInitializer - 29, // 31: wsman.StartWorkspaceSpec.ports:type_name -> wsman.PortSpec - 36, // 32: wsman.StartWorkspaceSpec.envvars:type_name -> wsman.EnvironmentVariable - 35, // 33: wsman.StartWorkspaceSpec.git:type_name -> wsman.GitSpec - 1, // 34: wsman.StartWorkspaceSpec.admission:type_name -> wsman.AdmissionLevel - 31, // 35: wsman.WorkspaceLogMessage.metadata:type_name -> wsman.WorkspaceMetadata - 7, // 36: wsman.WorkspaceManager.GetWorkspaces:input_type -> wsman.GetWorkspacesRequest - 9, // 37: wsman.WorkspaceManager.StartWorkspace:input_type -> wsman.StartWorkspaceRequest - 11, // 38: wsman.WorkspaceManager.StopWorkspace:input_type -> wsman.StopWorkspaceRequest - 13, // 39: wsman.WorkspaceManager.DescribeWorkspace:input_type -> wsman.DescribeWorkspaceRequest - 15, // 40: wsman.WorkspaceManager.Subscribe:input_type -> wsman.SubscribeRequest - 17, // 41: wsman.WorkspaceManager.MarkActive:input_type -> wsman.MarkActiveRequest - 19, // 42: wsman.WorkspaceManager.SetTimeout:input_type -> wsman.SetTimeoutRequest - 21, // 43: wsman.WorkspaceManager.ControlPort:input_type -> wsman.ControlPortRequest - 23, // 44: wsman.WorkspaceManager.TakeSnapshot:input_type -> wsman.TakeSnapshotRequest - 25, // 45: wsman.WorkspaceManager.ControlAdmission:input_type -> wsman.ControlAdmissionRequest - 8, // 46: wsman.WorkspaceManager.GetWorkspaces:output_type -> wsman.GetWorkspacesResponse - 10, // 47: wsman.WorkspaceManager.StartWorkspace:output_type -> wsman.StartWorkspaceResponse - 12, // 48: wsman.WorkspaceManager.StopWorkspace:output_type -> wsman.StopWorkspaceResponse - 14, // 49: wsman.WorkspaceManager.DescribeWorkspace:output_type -> wsman.DescribeWorkspaceResponse - 16, // 50: wsman.WorkspaceManager.Subscribe:output_type -> wsman.SubscribeResponse - 18, // 51: wsman.WorkspaceManager.MarkActive:output_type -> wsman.MarkActiveResponse - 20, // 52: wsman.WorkspaceManager.SetTimeout:output_type -> wsman.SetTimeoutResponse - 22, // 53: wsman.WorkspaceManager.ControlPort:output_type -> wsman.ControlPortResponse - 24, // 54: wsman.WorkspaceManager.TakeSnapshot:output_type -> wsman.TakeSnapshotResponse - 26, // 55: wsman.WorkspaceManager.ControlAdmission:output_type -> wsman.ControlAdmissionResponse - 46, // [46:56] is the sub-list for method output_type - 36, // [36:46] is the sub-list for method input_type - 36, // [36:36] is the sub-list for extension type_name - 36, // [36:36] is the sub-list for extension extendee - 0, // [0:36] is the sub-list for field type_name + 39, // 0: wsman.MetadataFilter.annotations:type_name -> wsman.MetadataFilter.AnnotationsEntry + 7, // 1: wsman.GetWorkspacesRequest.must_match:type_name -> wsman.MetadataFilter + 28, // 2: wsman.GetWorkspacesResponse.status:type_name -> wsman.WorkspaceStatus + 32, // 3: wsman.StartWorkspaceRequest.metadata:type_name -> wsman.WorkspaceMetadata + 35, // 4: wsman.StartWorkspaceRequest.spec:type_name -> wsman.StartWorkspaceSpec + 6, // 5: wsman.StartWorkspaceRequest.type:type_name -> wsman.WorkspaceType + 0, // 6: wsman.StopWorkspaceRequest.policy:type_name -> wsman.StopWorkspacePolicy + 28, // 7: wsman.DescribeWorkspaceResponse.status:type_name -> wsman.WorkspaceStatus + 7, // 8: wsman.SubscribeRequest.must_match:type_name -> wsman.MetadataFilter + 28, // 9: wsman.SubscribeResponse.status:type_name -> wsman.WorkspaceStatus + 38, // 10: wsman.SubscribeResponse.log:type_name -> wsman.WorkspaceLogMessage + 40, // 11: wsman.SubscribeResponse.header:type_name -> wsman.SubscribeResponse.HeaderEntry + 30, // 12: wsman.ControlPortRequest.spec:type_name -> wsman.PortSpec + 1, // 13: wsman.ControlAdmissionRequest.level:type_name -> wsman.AdmissionLevel + 32, // 14: wsman.WorkspaceStatus.metadata:type_name -> wsman.WorkspaceMetadata + 29, // 15: wsman.WorkspaceStatus.spec:type_name -> wsman.WorkspaceSpec + 4, // 16: wsman.WorkspaceStatus.phase:type_name -> wsman.WorkspacePhase + 31, // 17: wsman.WorkspaceStatus.conditions:type_name -> wsman.WorkspaceConditions + 42, // 18: wsman.WorkspaceStatus.repo:type_name -> contentservice.GitStatus + 33, // 19: wsman.WorkspaceStatus.runtime:type_name -> wsman.WorkspaceRuntimeInfo + 34, // 20: wsman.WorkspaceStatus.auth:type_name -> wsman.WorkspaceAuthentication + 30, // 21: wsman.WorkspaceSpec.exposed_ports:type_name -> wsman.PortSpec + 6, // 22: wsman.WorkspaceSpec.type:type_name -> wsman.WorkspaceType + 2, // 23: wsman.PortSpec.visibility:type_name -> wsman.PortVisibility + 3, // 24: wsman.WorkspaceConditions.pulling_images:type_name -> wsman.WorkspaceConditionBool + 3, // 25: wsman.WorkspaceConditions.service_exists:type_name -> wsman.WorkspaceConditionBool + 3, // 26: wsman.WorkspaceConditions.final_backup_complete:type_name -> wsman.WorkspaceConditionBool + 3, // 27: wsman.WorkspaceConditions.deployed:type_name -> wsman.WorkspaceConditionBool + 3, // 28: wsman.WorkspaceConditions.network_not_ready:type_name -> wsman.WorkspaceConditionBool + 43, // 29: wsman.WorkspaceConditions.first_user_activity:type_name -> google.protobuf.Timestamp + 43, // 30: wsman.WorkspaceMetadata.started_at:type_name -> google.protobuf.Timestamp + 41, // 31: wsman.WorkspaceMetadata.annotations:type_name -> wsman.WorkspaceMetadata.AnnotationsEntry + 1, // 32: wsman.WorkspaceAuthentication.admission:type_name -> wsman.AdmissionLevel + 5, // 33: wsman.StartWorkspaceSpec.feature_flags:type_name -> wsman.WorkspaceFeatureFlag + 44, // 34: wsman.StartWorkspaceSpec.initializer:type_name -> contentservice.WorkspaceInitializer + 30, // 35: wsman.StartWorkspaceSpec.ports:type_name -> wsman.PortSpec + 37, // 36: wsman.StartWorkspaceSpec.envvars:type_name -> wsman.EnvironmentVariable + 36, // 37: wsman.StartWorkspaceSpec.git:type_name -> wsman.GitSpec + 1, // 38: wsman.StartWorkspaceSpec.admission:type_name -> wsman.AdmissionLevel + 32, // 39: wsman.WorkspaceLogMessage.metadata:type_name -> wsman.WorkspaceMetadata + 8, // 40: wsman.WorkspaceManager.GetWorkspaces:input_type -> wsman.GetWorkspacesRequest + 10, // 41: wsman.WorkspaceManager.StartWorkspace:input_type -> wsman.StartWorkspaceRequest + 12, // 42: wsman.WorkspaceManager.StopWorkspace:input_type -> wsman.StopWorkspaceRequest + 14, // 43: wsman.WorkspaceManager.DescribeWorkspace:input_type -> wsman.DescribeWorkspaceRequest + 16, // 44: wsman.WorkspaceManager.Subscribe:input_type -> wsman.SubscribeRequest + 18, // 45: wsman.WorkspaceManager.MarkActive:input_type -> wsman.MarkActiveRequest + 20, // 46: wsman.WorkspaceManager.SetTimeout:input_type -> wsman.SetTimeoutRequest + 22, // 47: wsman.WorkspaceManager.ControlPort:input_type -> wsman.ControlPortRequest + 24, // 48: wsman.WorkspaceManager.TakeSnapshot:input_type -> wsman.TakeSnapshotRequest + 26, // 49: wsman.WorkspaceManager.ControlAdmission:input_type -> wsman.ControlAdmissionRequest + 9, // 50: wsman.WorkspaceManager.GetWorkspaces:output_type -> wsman.GetWorkspacesResponse + 11, // 51: wsman.WorkspaceManager.StartWorkspace:output_type -> wsman.StartWorkspaceResponse + 13, // 52: wsman.WorkspaceManager.StopWorkspace:output_type -> wsman.StopWorkspaceResponse + 15, // 53: wsman.WorkspaceManager.DescribeWorkspace:output_type -> wsman.DescribeWorkspaceResponse + 17, // 54: wsman.WorkspaceManager.Subscribe:output_type -> wsman.SubscribeResponse + 19, // 55: wsman.WorkspaceManager.MarkActive:output_type -> wsman.MarkActiveResponse + 21, // 56: wsman.WorkspaceManager.SetTimeout:output_type -> wsman.SetTimeoutResponse + 23, // 57: wsman.WorkspaceManager.ControlPort:output_type -> wsman.ControlPortResponse + 25, // 58: wsman.WorkspaceManager.TakeSnapshot:output_type -> wsman.TakeSnapshotResponse + 27, // 59: wsman.WorkspaceManager.ControlAdmission:output_type -> wsman.ControlAdmissionResponse + 50, // [50:60] is the sub-list for method output_type + 40, // [40:50] is the sub-list for method input_type + 40, // [40:40] is the sub-list for extension type_name + 40, // [40:40] is the sub-list for extension extendee + 0, // [0:40] is the sub-list for field type_name } func init() { file_core_proto_init() } @@ -2889,7 +3029,7 @@ func file_core_proto_init() { } if !protoimpl.UnsafeEnabled { file_core_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetWorkspacesRequest); i { + switch v := v.(*MetadataFilter); i { case 0: return &v.state case 1: @@ -2901,7 +3041,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetWorkspacesResponse); i { + switch v := v.(*GetWorkspacesRequest); i { case 0: return &v.state case 1: @@ -2913,7 +3053,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartWorkspaceRequest); i { + switch v := v.(*GetWorkspacesResponse); i { case 0: return &v.state case 1: @@ -2925,7 +3065,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartWorkspaceResponse); i { + switch v := v.(*StartWorkspaceRequest); i { case 0: return &v.state case 1: @@ -2937,7 +3077,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopWorkspaceRequest); i { + switch v := v.(*StartWorkspaceResponse); i { case 0: return &v.state case 1: @@ -2949,7 +3089,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopWorkspaceResponse); i { + switch v := v.(*StopWorkspaceRequest); i { case 0: return &v.state case 1: @@ -2961,7 +3101,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DescribeWorkspaceRequest); i { + switch v := v.(*StopWorkspaceResponse); i { case 0: return &v.state case 1: @@ -2973,7 +3113,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DescribeWorkspaceResponse); i { + switch v := v.(*DescribeWorkspaceRequest); i { case 0: return &v.state case 1: @@ -2985,7 +3125,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubscribeRequest); i { + switch v := v.(*DescribeWorkspaceResponse); i { case 0: return &v.state case 1: @@ -2997,7 +3137,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubscribeResponse); i { + switch v := v.(*SubscribeRequest); i { case 0: return &v.state case 1: @@ -3009,7 +3149,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MarkActiveRequest); i { + switch v := v.(*SubscribeResponse); i { case 0: return &v.state case 1: @@ -3021,7 +3161,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MarkActiveResponse); i { + switch v := v.(*MarkActiveRequest); i { case 0: return &v.state case 1: @@ -3033,7 +3173,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetTimeoutRequest); i { + switch v := v.(*MarkActiveResponse); i { case 0: return &v.state case 1: @@ -3045,7 +3185,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetTimeoutResponse); i { + switch v := v.(*SetTimeoutRequest); i { case 0: return &v.state case 1: @@ -3057,7 +3197,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ControlPortRequest); i { + switch v := v.(*SetTimeoutResponse); i { case 0: return &v.state case 1: @@ -3069,7 +3209,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ControlPortResponse); i { + switch v := v.(*ControlPortRequest); i { case 0: return &v.state case 1: @@ -3081,7 +3221,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TakeSnapshotRequest); i { + switch v := v.(*ControlPortResponse); i { case 0: return &v.state case 1: @@ -3093,7 +3233,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TakeSnapshotResponse); i { + switch v := v.(*TakeSnapshotRequest); i { case 0: return &v.state case 1: @@ -3105,7 +3245,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ControlAdmissionRequest); i { + switch v := v.(*TakeSnapshotResponse); i { case 0: return &v.state case 1: @@ -3117,7 +3257,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ControlAdmissionResponse); i { + switch v := v.(*ControlAdmissionRequest); i { case 0: return &v.state case 1: @@ -3129,7 +3269,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceStatus); i { + switch v := v.(*ControlAdmissionResponse); i { case 0: return &v.state case 1: @@ -3141,7 +3281,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceSpec); i { + switch v := v.(*WorkspaceStatus); i { case 0: return &v.state case 1: @@ -3153,7 +3293,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PortSpec); i { + switch v := v.(*WorkspaceSpec); i { case 0: return &v.state case 1: @@ -3165,7 +3305,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceConditions); i { + switch v := v.(*PortSpec); i { case 0: return &v.state case 1: @@ -3177,7 +3317,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceMetadata); i { + switch v := v.(*WorkspaceConditions); i { case 0: return &v.state case 1: @@ -3189,7 +3329,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceRuntimeInfo); i { + switch v := v.(*WorkspaceMetadata); i { case 0: return &v.state case 1: @@ -3201,7 +3341,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceAuthentication); i { + switch v := v.(*WorkspaceRuntimeInfo); i { case 0: return &v.state case 1: @@ -3213,7 +3353,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartWorkspaceSpec); i { + switch v := v.(*WorkspaceAuthentication); i { case 0: return &v.state case 1: @@ -3225,7 +3365,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GitSpec); i { + switch v := v.(*StartWorkspaceSpec); i { case 0: return &v.state case 1: @@ -3237,7 +3377,7 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnvironmentVariable); i { + switch v := v.(*GitSpec); i { case 0: return &v.state case 1: @@ -3249,6 +3389,18 @@ func file_core_proto_init() { } } file_core_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnvironmentVariable); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WorkspaceLogMessage); i { case 0: return &v.state @@ -3261,7 +3413,7 @@ func file_core_proto_init() { } } } - file_core_proto_msgTypes[9].OneofWrappers = []interface{}{ + file_core_proto_msgTypes[10].OneofWrappers = []interface{}{ (*SubscribeResponse_Status)(nil), (*SubscribeResponse_Log)(nil), } @@ -3271,7 +3423,7 @@ func file_core_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_core_proto_rawDesc, NumEnums: 7, - NumMessages: 32, + NumMessages: 35, NumExtensions: 0, NumServices: 1, }, diff --git a/components/ws-manager-api/typescript/src/core_pb.d.ts b/components/ws-manager-api/typescript/src/core_pb.d.ts index 6ed6a1f7cf5904..2cb43d98a9a859 100644 --- a/components/ws-manager-api/typescript/src/core_pb.d.ts +++ b/components/ws-manager-api/typescript/src/core_pb.d.ts @@ -14,8 +14,41 @@ import * as jspb from "google-protobuf"; import * as content_service_api_initializer_pb from "@gitpod/content-service/lib"; import * as google_protobuf_timestamp_pb from "google-protobuf/google/protobuf/timestamp_pb"; +export class MetadataFilter extends jspb.Message { + getOwner(): string; + setOwner(value: string): MetadataFilter; + getMetaId(): string; + setMetaId(value: string): MetadataFilter; + + getAnnotationsMap(): jspb.Map; + clearAnnotationsMap(): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): MetadataFilter.AsObject; + static toObject(includeInstance: boolean, msg: MetadataFilter): MetadataFilter.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: MetadataFilter, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): MetadataFilter; + static deserializeBinaryFromReader(message: MetadataFilter, reader: jspb.BinaryReader): MetadataFilter; +} + +export namespace MetadataFilter { + export type AsObject = { + owner: string, + metaId: string, + + annotationsMap: Array<[string, string]>, + } +} + export class GetWorkspacesRequest extends jspb.Message { + hasMustMatch(): boolean; + clearMustMatch(): void; + getMustMatch(): MetadataFilter | undefined; + setMustMatch(value?: MetadataFilter): GetWorkspacesRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): GetWorkspacesRequest.AsObject; static toObject(includeInstance: boolean, msg: GetWorkspacesRequest): GetWorkspacesRequest.AsObject; @@ -28,6 +61,7 @@ export class GetWorkspacesRequest extends jspb.Message { export namespace GetWorkspacesRequest { export type AsObject = { + mustMatch?: MetadataFilter.AsObject, } } @@ -199,6 +233,11 @@ export namespace DescribeWorkspaceResponse { export class SubscribeRequest extends jspb.Message { + hasMustMatch(): boolean; + clearMustMatch(): void; + getMustMatch(): MetadataFilter | undefined; + setMustMatch(value?: MetadataFilter): SubscribeRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): SubscribeRequest.AsObject; static toObject(includeInstance: boolean, msg: SubscribeRequest): SubscribeRequest.AsObject; @@ -211,6 +250,7 @@ export class SubscribeRequest extends jspb.Message { export namespace SubscribeRequest { export type AsObject = { + mustMatch?: MetadataFilter.AsObject, } } @@ -655,6 +695,9 @@ export class WorkspaceMetadata extends jspb.Message { getStartedAt(): google_protobuf_timestamp_pb.Timestamp | undefined; setStartedAt(value?: google_protobuf_timestamp_pb.Timestamp): WorkspaceMetadata; + getAnnotationsMap(): jspb.Map; + clearAnnotationsMap(): void; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): WorkspaceMetadata.AsObject; static toObject(includeInstance: boolean, msg: WorkspaceMetadata): WorkspaceMetadata.AsObject; @@ -670,6 +713,8 @@ export namespace WorkspaceMetadata { owner: string, metaId: string, startedAt?: google_protobuf_timestamp_pb.Timestamp.AsObject, + + annotationsMap: Array<[string, string]>, } } @@ -902,4 +947,5 @@ export enum WorkspaceType { PREBUILD = 1, PROBE = 2, GHOST = 3, + IMAGEBUILD = 4, } diff --git a/components/ws-manager-api/typescript/src/core_pb.js b/components/ws-manager-api/typescript/src/core_pb.js index 057ed2b197cc5d..9c2e1257d62af6 100644 --- a/components/ws-manager-api/typescript/src/core_pb.js +++ b/components/ws-manager-api/typescript/src/core_pb.js @@ -38,6 +38,7 @@ goog.exportSymbol('proto.wsman.GetWorkspacesResponse', null, global); goog.exportSymbol('proto.wsman.GitSpec', null, global); goog.exportSymbol('proto.wsman.MarkActiveRequest', null, global); goog.exportSymbol('proto.wsman.MarkActiveResponse', null, global); +goog.exportSymbol('proto.wsman.MetadataFilter', null, global); goog.exportSymbol('proto.wsman.PortSpec', null, global); goog.exportSymbol('proto.wsman.PortVisibility', null, global); goog.exportSymbol('proto.wsman.SetTimeoutRequest', null, global); @@ -64,6 +65,27 @@ goog.exportSymbol('proto.wsman.WorkspaceRuntimeInfo', null, global); goog.exportSymbol('proto.wsman.WorkspaceSpec', null, global); goog.exportSymbol('proto.wsman.WorkspaceStatus', null, global); goog.exportSymbol('proto.wsman.WorkspaceType', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.wsman.MetadataFilter = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.wsman.MetadataFilter, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.wsman.MetadataFilter.displayName = 'proto.wsman.MetadataFilter'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -718,6 +740,199 @@ if (goog.DEBUG && !COMPILED) { +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.wsman.MetadataFilter.prototype.toObject = function(opt_includeInstance) { + return proto.wsman.MetadataFilter.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.wsman.MetadataFilter} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.wsman.MetadataFilter.toObject = function(includeInstance, msg) { + var f, obj = { + owner: jspb.Message.getFieldWithDefault(msg, 1, ""), + metaId: jspb.Message.getFieldWithDefault(msg, 2, ""), + annotationsMap: (f = msg.getAnnotationsMap()) ? f.toObject(includeInstance, undefined) : [] + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.wsman.MetadataFilter} + */ +proto.wsman.MetadataFilter.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.wsman.MetadataFilter; + return proto.wsman.MetadataFilter.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.wsman.MetadataFilter} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.wsman.MetadataFilter} + */ +proto.wsman.MetadataFilter.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setOwner(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setMetaId(value); + break; + case 3: + var value = msg.getAnnotationsMap(); + reader.readMessage(value, function(message, reader) { + jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readString, null, "", ""); + }); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.wsman.MetadataFilter.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.wsman.MetadataFilter.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.wsman.MetadataFilter} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.wsman.MetadataFilter.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getOwner(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getMetaId(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getAnnotationsMap(true); + if (f && f.getLength() > 0) { + f.serializeBinary(3, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString); + } +}; + + +/** + * optional string owner = 1; + * @return {string} + */ +proto.wsman.MetadataFilter.prototype.getOwner = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.wsman.MetadataFilter} returns this + */ +proto.wsman.MetadataFilter.prototype.setOwner = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string meta_id = 2; + * @return {string} + */ +proto.wsman.MetadataFilter.prototype.getMetaId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.wsman.MetadataFilter} returns this + */ +proto.wsman.MetadataFilter.prototype.setMetaId = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * map annotations = 3; + * @param {boolean=} opt_noLazyCreate Do not create the map if + * empty, instead returning `undefined` + * @return {!jspb.Map} + */ +proto.wsman.MetadataFilter.prototype.getAnnotationsMap = function(opt_noLazyCreate) { + return /** @type {!jspb.Map} */ ( + jspb.Message.getMapField(this, 3, opt_noLazyCreate, + null)); +}; + + +/** + * Clears values from the map. The map will be non-null. + * @return {!proto.wsman.MetadataFilter} returns this + */ +proto.wsman.MetadataFilter.prototype.clearAnnotationsMap = function() { + this.getAnnotationsMap().clear(); + return this;}; + + + + + if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. @@ -747,7 +962,7 @@ proto.wsman.GetWorkspacesRequest.prototype.toObject = function(opt_includeInstan */ proto.wsman.GetWorkspacesRequest.toObject = function(includeInstance, msg) { var f, obj = { - + mustMatch: (f = msg.getMustMatch()) && proto.wsman.MetadataFilter.toObject(includeInstance, f) }; if (includeInstance) { @@ -784,6 +999,11 @@ proto.wsman.GetWorkspacesRequest.deserializeBinaryFromReader = function(msg, rea } var field = reader.getFieldNumber(); switch (field) { + case 1: + var value = new proto.wsman.MetadataFilter; + reader.readMessage(value,proto.wsman.MetadataFilter.deserializeBinaryFromReader); + msg.setMustMatch(value); + break; default: reader.skipField(); break; @@ -813,6 +1033,51 @@ proto.wsman.GetWorkspacesRequest.prototype.serializeBinary = function() { */ proto.wsman.GetWorkspacesRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; + f = message.getMustMatch(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.wsman.MetadataFilter.serializeBinaryToWriter + ); + } +}; + + +/** + * optional MetadataFilter must_match = 1; + * @return {?proto.wsman.MetadataFilter} + */ +proto.wsman.GetWorkspacesRequest.prototype.getMustMatch = function() { + return /** @type{?proto.wsman.MetadataFilter} */ ( + jspb.Message.getWrapperField(this, proto.wsman.MetadataFilter, 1)); +}; + + +/** + * @param {?proto.wsman.MetadataFilter|undefined} value + * @return {!proto.wsman.GetWorkspacesRequest} returns this +*/ +proto.wsman.GetWorkspacesRequest.prototype.setMustMatch = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.wsman.GetWorkspacesRequest} returns this + */ +proto.wsman.GetWorkspacesRequest.prototype.clearMustMatch = function() { + return this.setMustMatch(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.wsman.GetWorkspacesRequest.prototype.hasMustMatch = function() { + return jspb.Message.getField(this, 1) != null; }; @@ -2002,7 +2267,7 @@ proto.wsman.SubscribeRequest.prototype.toObject = function(opt_includeInstance) */ proto.wsman.SubscribeRequest.toObject = function(includeInstance, msg) { var f, obj = { - + mustMatch: (f = msg.getMustMatch()) && proto.wsman.MetadataFilter.toObject(includeInstance, f) }; if (includeInstance) { @@ -2039,6 +2304,11 @@ proto.wsman.SubscribeRequest.deserializeBinaryFromReader = function(msg, reader) } var field = reader.getFieldNumber(); switch (field) { + case 1: + var value = new proto.wsman.MetadataFilter; + reader.readMessage(value,proto.wsman.MetadataFilter.deserializeBinaryFromReader); + msg.setMustMatch(value); + break; default: reader.skipField(); break; @@ -2068,6 +2338,51 @@ proto.wsman.SubscribeRequest.prototype.serializeBinary = function() { */ proto.wsman.SubscribeRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; + f = message.getMustMatch(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.wsman.MetadataFilter.serializeBinaryToWriter + ); + } +}; + + +/** + * optional MetadataFilter must_match = 1; + * @return {?proto.wsman.MetadataFilter} + */ +proto.wsman.SubscribeRequest.prototype.getMustMatch = function() { + return /** @type{?proto.wsman.MetadataFilter} */ ( + jspb.Message.getWrapperField(this, proto.wsman.MetadataFilter, 1)); +}; + + +/** + * @param {?proto.wsman.MetadataFilter|undefined} value + * @return {!proto.wsman.SubscribeRequest} returns this +*/ +proto.wsman.SubscribeRequest.prototype.setMustMatch = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.wsman.SubscribeRequest} returns this + */ +proto.wsman.SubscribeRequest.prototype.clearMustMatch = function() { + return this.setMustMatch(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.wsman.SubscribeRequest.prototype.hasMustMatch = function() { + return jspb.Message.getField(this, 1) != null; }; @@ -5198,7 +5513,8 @@ proto.wsman.WorkspaceMetadata.toObject = function(includeInstance, msg) { var f, obj = { owner: jspb.Message.getFieldWithDefault(msg, 1, ""), metaId: jspb.Message.getFieldWithDefault(msg, 2, ""), - startedAt: (f = msg.getStartedAt()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f) + startedAt: (f = msg.getStartedAt()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + annotationsMap: (f = msg.getAnnotationsMap()) ? f.toObject(includeInstance, undefined) : [] }; if (includeInstance) { @@ -5248,6 +5564,12 @@ proto.wsman.WorkspaceMetadata.deserializeBinaryFromReader = function(msg, reader reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); msg.setStartedAt(value); break; + case 4: + var value = msg.getAnnotationsMap(); + reader.readMessage(value, function(message, reader) { + jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readString, null, "", ""); + }); + break; default: reader.skipField(); break; @@ -5299,6 +5621,10 @@ proto.wsman.WorkspaceMetadata.serializeBinaryToWriter = function(message, writer google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter ); } + f = message.getAnnotationsMap(true); + if (f && f.getLength() > 0) { + f.serializeBinary(4, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString); + } }; @@ -5375,6 +5701,28 @@ proto.wsman.WorkspaceMetadata.prototype.hasStartedAt = function() { }; +/** + * map annotations = 4; + * @param {boolean=} opt_noLazyCreate Do not create the map if + * empty, instead returning `undefined` + * @return {!jspb.Map} + */ +proto.wsman.WorkspaceMetadata.prototype.getAnnotationsMap = function(opt_noLazyCreate) { + return /** @type {!jspb.Map} */ ( + jspb.Message.getMapField(this, 4, opt_noLazyCreate, + null)); +}; + + +/** + * Clears values from the map. The map will be non-null. + * @return {!proto.wsman.WorkspaceMetadata} returns this + */ +proto.wsman.WorkspaceMetadata.prototype.clearAnnotationsMap = function() { + this.getAnnotationsMap().clear(); + return this;}; + + @@ -6865,7 +7213,8 @@ proto.wsman.WorkspaceType = { REGULAR: 0, PREBUILD: 1, PROBE: 2, - GHOST: 3 + GHOST: 3, + IMAGEBUILD: 4 }; goog.object.extend(exports, proto.wsman); diff --git a/components/ws-manager/pkg/manager/annotations.go b/components/ws-manager/pkg/manager/annotations.go index 3a829704f6fea0..89fb15a7e5d104 100644 --- a/components/ws-manager/pkg/manager/annotations.go +++ b/components/ws-manager/pkg/manager/annotations.go @@ -82,6 +82,9 @@ const ( // nodeNameAnnotation contains the name of the node the pod ran on. We use this to remeber the name in case the pod gets evicted. nodeNameAnnotation = "gitpod.io/nodeName" + + // workspaceAnnotationPrefix prefixes pod annotations that contain annotations specified during the workspaces start request + workspaceAnnotationPrefix = "gitpod/annotation." ) // markWorkspaceAsReady adds annotations to a workspace pod diff --git a/components/ws-manager/pkg/manager/create.go b/components/ws-manager/pkg/manager/create.go index d4d9f212ad203a..0aecea68ae3060 100644 --- a/components/ws-manager/pkg/manager/create.go +++ b/components/ws-manager/pkg/manager/create.go @@ -53,6 +53,8 @@ func (m *Manager) createWorkspacePod(startContext *startWorkspaceContext) (*core typeSpecificTpl, err = getWorkspacePodTemplate(m.Config.WorkspacePodTemplate.ProbePath) case api.WorkspaceType_GHOST: typeSpecificTpl, err = getWorkspacePodTemplate(m.Config.WorkspacePodTemplate.GhostPath) + case api.WorkspaceType_IMAGEBUILD: + typeSpecificTpl, err = getWorkspacePodTemplate(m.Config.WorkspacePodTemplate.ImagebuildPath) } if err != nil { return nil, xerrors.Errorf("cannot read type-specific pod template - this is a configuration problem: %w", err) @@ -262,6 +264,8 @@ func (m *Manager) createDefiniteWorkspacePod(startContext *startWorkspaceContext prefix = "probe" case api.WorkspaceType_GHOST: prefix = "ghost" + case api.WorkspaceType_IMAGEBUILD: + prefix = "imagebuild" default: prefix = "ws" } @@ -296,6 +300,9 @@ func (m *Manager) createDefiniteWorkspacePod(startContext *startWorkspaceContext } annotations[customTimeoutAnnotation] = req.Spec.Timeout } + for k, v := range req.Metadata.Annotations { + annotations[workspaceAnnotationPrefix+k] = v + } // By default we embue our workspace pods with some tolerance towards pressure taints, // see https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/#taint-based-evictions diff --git a/components/ws-manager/pkg/manager/manager.go b/components/ws-manager/pkg/manager/manager.go index 176fff24c9dad4..26a042c7ec6a6d 100644 --- a/components/ws-manager/pkg/manager/manager.go +++ b/components/ws-manager/pkg/manager/manager.go @@ -806,7 +806,55 @@ func (m *Manager) DescribeWorkspace(ctx context.Context, req *api.DescribeWorksp // Subscribe streams all status updates to a client func (m *Manager) Subscribe(req *api.SubscribeRequest, srv api.WorkspaceManager_SubscribeServer) (err error) { - return m.subscribe(srv.Context(), srv) + var sub subscriber = srv + if req.MustMatch != nil { + sub = &filteringSubscriber{srv, req.MustMatch} + } + + return m.subscribe(srv.Context(), sub) +} + +type filteringSubscriber struct { + Sub subscriber + Filter *api.MetadataFilter +} + +func matchesMetadataFilter(filter *api.MetadataFilter, md *api.WorkspaceMetadata) bool { + if filter == nil { + return true + } + + if filter.MetaId != "" && filter.MetaId != md.MetaId { + return false + } + if filter.Owner != "" && filter.Owner != md.Owner { + return false + } + for k, v := range filter.Annotations { + av, ok := md.Annotations[k] + if !ok || av != v { + return false + } + } + return true +} + +func (f *filteringSubscriber) Send(resp *api.SubscribeResponse) error { + var md *api.WorkspaceMetadata + if lg := resp.GetLog(); lg != nil { + md = lg.Metadata + } else if sts := resp.GetStatus(); sts != nil { + md = sts.Metadata + } + if md == nil { + // no metadata, no forwarding + return nil + } + if !matchesMetadataFilter(f.Filter, md) { + return nil + } + + return f.Sub.Send(resp) } type subscriber interface { @@ -967,6 +1015,10 @@ func (m *Manager) GetWorkspaces(ctx context.Context, req *api.GetWorkspacesReque continue } + if !matchesMetadataFilter(req.MustMatch, status.Metadata) { + continue + } + result = append(result, status) } diff --git a/components/ws-manager/pkg/manager/monitor.go b/components/ws-manager/pkg/manager/monitor.go index 31c624d7127145..ba99f025386bf7 100644 --- a/components/ws-manager/pkg/manager/monitor.go +++ b/components/ws-manager/pkg/manager/monitor.go @@ -234,6 +234,9 @@ func (m *Monitor) actOnPodEvent(ctx context.Context, status *api.WorkspaceStatus // // Beware: do not else-if this condition with the other phases as we don't want the stop // login in any other phase, too. + m.initializerMapLock.Lock() + delete(m.initializerMap, pod.Name) + m.initializerMapLock.Unlock() } else if status.Conditions.Failed != "" || status.Conditions.Timeout != "" { // the workspace has failed to run/start - shut it down // we should mark the workspace as failedBeforeStopping - this way the failure status will persist @@ -390,7 +393,7 @@ func (m *Monitor) writeEventTraceLog(status *api.WorkspaceStatus, wso *workspace } for _, c := range twso.Pod.Spec.Containers { for i, env := range c.Env { - isGitpodVar := strings.HasPrefix(env.Name, "GITPOD_") || strings.HasPrefix(env.Name, "THEIA_") + isGitpodVar := strings.HasPrefix(env.Name, "GITPOD_") || strings.HasPrefix(env.Name, "SUPERVISOR_") || strings.HasPrefix(env.Name, "BOB_") || strings.HasPrefix(env.Name, "THEIA_") if isGitpodVar { continue } diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden new file mode 100644 index 00000000000000..f4d927467c8495 --- /dev/null +++ b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden @@ -0,0 +1,229 @@ +{ + "reason": { + "metadata": { + "name": "imagebuild-foobar", + "namespace": "default", + "creationTimestamp": null, + "labels": { + "app": "gitpod", + "component": "workspace", + "gitpod.io/networkpolicy": "default", + "gpwsman": "true", + "headless": "true", + "metaID": "foobar", + "owner": "tester", + "workspaceID": "foobar", + "workspaceType": "imagebuild" + }, + "annotations": { + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false", + "container.apparmor.security.beta.kubernetes.io/workspace": "unconfined", + "gitpod.io/requiredNodeServices": "ws-daemon,registry-facade", + "gitpod/admission": "admit_owner_only", + "gitpod/contentInitializer": "GmcKZXdvcmtzcGFjZXMvY3J5cHRpYy1pZC1nb2VzLWhlcmcvZmQ2MjgwNGItNGNhYi0xMWU5LTg0M2EtNGU2NDUzNzMwNDhlLnRhckBnaXRwb2QtZGV2LXVzZXItY2hyaXN0ZXN0aW5n", + "gitpod/id": "foobar", + "gitpod/imageSpec": "CrwBZXUuZ2NyLmlvL2dpdHBvZC1kZXYvd29ya3NwYWNlLWltYWdlcy9hYzFjMDc1NTAwNzk2NmU0ZDZlMDkwZWE4MjE3MjlhYzc0N2QyMmFjL2V1Lmdjci5pby9naXRwb2QtZGV2L3dvcmtzcGFjZS1iYXNlLWltYWdlcy9naXRodWIuY29tL3R5cGVmb3gvZ2l0cG9kOjgwYTdkNDI3YTFmY2QzNDZkNDIwNjAzZDgwYTMxZDU3Y2Y3NWE3YWYSNGV1Lmdjci5pby9naXRwb2QtY29yZS1kZXYvYnVpZC90aGVpYS1pZGU6c29tZXZlcnNpb24=", + "gitpod/never-ready": "true", + "gitpod/ownerToken": "%7J'[Of/8NDiWE+9F,I6^Jcj_1\u0026}-F8p", + "gitpod/servicePrefix": "foobarservice", + "gitpod/traceid": "", + "gitpod/url": "foobar-foobarservice-gitpod.io", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "23000", + "prometheus.io/scrape": "true", + "seccomp.security.alpha.kubernetes.io/pod": "localhost/workspace-default" + } + }, + "spec": { + "volumes": [ + { + "name": "vol-this-workspace", + "hostPath": { + "path": "/tmp/workspaces/foobar", + "type": "DirectoryOrCreate" + } + }, + { + "name": "daemon-mount", + "hostPath": { + "path": "/tmp/workspaces/foobar-daemon", + "type": "DirectoryOrCreate" + } + } + ], + "containers": [ + { + "name": "workspace", + "image": "registry-facade:8080/remote/foobar", + "command": [ + "/.supervisor/workspacekit", + "ring0" + ], + "ports": [ + { + "containerPort": 23000 + } + ], + "env": [ + { + "name": "GITPOD_REPO_ROOT", + "value": "/workspace" + }, + { + "name": "GITPOD_CLI_APITOKEN", + "value": "Ab=5=rRA*9:C'T{;RRB\u003e]vK2p6`fFfrS" + }, + { + "name": "GITPOD_WORKSPACE_ID", + "value": "foobar" + }, + { + "name": "GITPOD_INSTANCE_ID", + "value": "foobar" + }, + { + "name": "GITPOD_THEIA_PORT", + "value": "23000" + }, + { + "name": "THEIA_WORKSPACE_ROOT", + "value": "/workspace" + }, + { + "name": "GITPOD_HOST", + "value": "gitpod.io" + }, + { + "name": "GITPOD_WORKSPACE_URL", + "value": "foobar-foobarservice-gitpod.io" + }, + { + "name": "THEIA_SUPERVISOR_ENDPOINT", + "value": ":22999" + }, + { + "name": "THEIA_WEBVIEW_EXTERNAL_ENDPOINT", + "value": "webview-{{hostname}}" + }, + { + "name": "THEIA_MINI_BROWSER_HOST_PATTERN", + "value": "browser-{{hostname}}" + }, + { + "name": "GITPOD_GIT_USER_NAME", + "value": "usernameGoesHere" + }, + { + "name": "GITPOD_GIT_USER_EMAIL", + "value": "some@user.com" + }, + { + "name": "foo", + "value": "bar" + }, + { + "name": "GITPOD_INTERVAL", + "value": "30000" + }, + { + "name": "GITPOD_MEMORY", + "value": "999" + }, + { + "name": "GITPOD_HEADLESS", + "value": "true" + } + ], + "resources": { + "limits": { + "cpu": "900m", + "memory": "1G" + }, + "requests": { + "cpu": "899m", + "ephemeral-storage": "5Gi", + "memory": "999M" + } + }, + "volumeMounts": [ + { + "name": "vol-this-workspace", + "mountPath": "/workspace", + "mountPropagation": "HostToContainer" + }, + { + "name": "daemon-mount", + "mountPath": "/.workspace", + "mountPropagation": "HostToContainer" + } + ], + "readinessProbe": { + "httpGet": { + "path": "/_supervisor/v1/status/content/wait/true", + "port": 22999, + "scheme": "HTTP" + }, + "timeoutSeconds": 1, + "periodSeconds": 1, + "successThreshold": 1, + "failureThreshold": 600 + }, + "terminationMessagePolicy": "File", + "imagePullPolicy": "Always", + "securityContext": { + "capabilities": { + "add": [ + "AUDIT_WRITE", + "FSETID", + "KILL", + "NET_BIND_SERVICE", + "SYS_PTRACE" + ], + "drop": [ + "SETPCAP", + "CHOWN", + "NET_RAW", + "DAC_OVERRIDE", + "FOWNER", + "SYS_CHROOT", + "SETFCAP", + "SETUID", + "SETGID" + ] + }, + "privileged": false, + "runAsUser": 33333, + "runAsGroup": 33333, + "runAsNonRoot": true, + "readOnlyRootFilesystem": false, + "allowPrivilegeEscalation": true + } + } + ], + "restartPolicy": "Never", + "serviceAccountName": "workspace", + "automountServiceAccountToken": false, + "schedulerName": "workspace-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/disk-pressure", + "operator": "Exists", + "effect": "NoExecute" + }, + { + "key": "node.kubernetes.io/memory-pressure", + "operator": "Exists", + "effect": "NoExecute" + }, + { + "key": "node.kubernetes.io/network-unavailable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 30 + } + ], + "enableServiceLinks": false + }, + "status": {} + } +} \ No newline at end of file diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.json b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.json new file mode 100644 index 00000000000000..d67e2764cfa43c --- /dev/null +++ b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.json @@ -0,0 +1,36 @@ +{ + "request": { + "id": "foobar", + "type": 4, + "metadata": { + "owner": "tester", + "metaId": "foobar" + }, + "servicePrefix": "foobarservice", + "spec": { + "ideImage": "eu.gcr.io/gitpod-core-dev/buid/theia-ide:someversion", + "workspaceImage": "eu.gcr.io/gitpod-dev/workspace-images/ac1c0755007966e4d6e090ea821729ac747d22ac/eu.gcr.io/gitpod-dev/workspace-base-images/github.com/typefox/gitpod:80a7d427a1fcd346d420603d80a31d57cf75a7af", + "initializer": { + "snapshot": { + "snapshot": "workspaces/cryptic-id-goes-herg/fd62804b-4cab-11e9-843a-4e645373048e.tar@gitpod-dev-user-christesting" + } + }, + "ports": [ + { + "port": 8080, + "target": 38080 + } + ], + "envvars": [ + { + "name": "foo", + "value": "bar" + } + ], + "git": { + "username": "usernameGoesHere", + "email": "some@user.com" + } + } + } +} \ No newline at end of file From acaa38417713fa24d74788dd122f377bc0938aec Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Fri, 18 Jun 2021 08:05:02 +0000 Subject: [PATCH 02/15] [image-builder] Backport mk3 from gitpod-com --- components/BUILD.yaml | 2 + components/image-builder-bob/.gitignore | 1 + components/image-builder-bob/BUILD.yaml | 32 + components/image-builder-bob/cmd/build.go | 48 + components/image-builder-bob/cmd/daemon.go | 104 ++ components/image-builder-bob/cmd/root.go | 31 + components/image-builder-bob/go.mod | 94 + components/image-builder-bob/go.sum | 1552 +++++++++++++++++ components/image-builder-bob/ide-startup.sh | 6 + .../image-builder-bob/leeway.Dockerfile | 30 + components/image-builder-bob/main.go | 11 + .../image-builder-bob/pkg/builder/auth.go | 54 + .../pkg/builder/auth_buildkit.go | 157 ++ .../image-builder-bob/pkg/builder/builder.go | 336 ++++ .../image-builder-bob/pkg/builder/config.go | 145 ++ .../supervisor-ide-config.json | 3 + components/image-builder-mk3/BUILD.yaml | 33 + .../image-builder-mk3/cmd/generate-config.go | 45 + components/image-builder-mk3/cmd/root.go | 133 ++ components/image-builder-mk3/cmd/run.go | 132 ++ .../image-builder-mk3/config-schema.json | 126 ++ components/image-builder-mk3/debug.sh | 12 + .../image-builder-mk3/example-build.json | 14 + .../image-builder-mk3/example-config.json | 19 + components/image-builder-mk3/go.mod | 86 + components/image-builder-mk3/go.sum | 394 +++++ .../image-builder.code-workspace | 48 + .../image-builder-mk3/leeway.Dockerfile | 17 + components/image-builder-mk3/main.go | 13 + components/image-builder-mk3/pkg/auth/auth.go | 243 +++ .../pkg/orchestrator/monitor.go | 244 +++ .../pkg/orchestrator/orchestrator.go | 724 ++++++++ .../image-builder-mk3/pkg/resolve/resolve.go | 170 ++ components/image-builder-mk3/telepresence.sh | 23 + .../workspace-image-layer/BUILD.yaml | 15 + .../gitpod-layer/Dockerfile | 34 + .../gitpod-layer/alpine/Dockerfile | 34 + .../gitpod-layer/alpine/gitpod/.bashrc-append | 27 + .../alpine/gitpod/.bashrc-prepend | 37 + .../gitpod-layer/alpine/gitpod/layer.sh | 56 + .../gitpod-layer/amazon/Dockerfile | 38 + .../gitpod-layer/amazon/cla.md.gpg | Bin 0 -> 6131 bytes .../gitpod-layer/amazon/gitpod/.bashrc-append | 11 + .../amazon/gitpod/.bashrc-prepend | 53 + .../gitpod-layer/amazon/gitpod/layer.sh | 156 ++ .../gitpod-layer/build.sh | 42 + .../gitpod-layer/debian/Dockerfile | 34 + .../gitpod-layer/debian/gitpod/.bashrc-append | 11 + .../debian/gitpod/.bashrc-prepend | 58 + .../gitpod-layer/debian/gitpod/layer.sh | 64 + .../gitpod-layer/prepend.dockerfile | 7 + .../scripts/detect-distro.sh | 48 + .../scripts/generate-dockerfile.sh | 37 + .../tests/positive/alpine-withuser.dockerfile | 6 + .../tests/positive/alpine.dockerfile | 3 + .../tests/positive/ubuntu-bionic.dockerfile | 1 + .../ubuntu-xenial-withuser-sudo.dockerfile | 6 + .../ubuntu-xenial-withuser.dockerfile | 5 + .../tests/positive/ubuntu-xenial.dockerfile | 1 + .../tests/positive/verify.sh | 18 + .../workspace-image-layer/tests/runtests.sh | 34 + components/image-builder/README.md | 3 + .../ws-manager/pkg/manager/annotations.go | 2 +- components/ws-manager/pkg/manager/config.go | 2 + components/ws-manager/pkg/manager/status.go | 14 +- .../manager/testdata/status_metadata.golden | 35 + .../pkg/manager/testdata/status_metadata.json | 358 ++++ gitpod-ws.code-workspace | 2 + 68 files changed, 6330 insertions(+), 4 deletions(-) create mode 100644 components/image-builder-bob/.gitignore create mode 100644 components/image-builder-bob/BUILD.yaml create mode 100644 components/image-builder-bob/cmd/build.go create mode 100644 components/image-builder-bob/cmd/daemon.go create mode 100644 components/image-builder-bob/cmd/root.go create mode 100644 components/image-builder-bob/go.mod create mode 100644 components/image-builder-bob/go.sum create mode 100644 components/image-builder-bob/ide-startup.sh create mode 100644 components/image-builder-bob/leeway.Dockerfile create mode 100644 components/image-builder-bob/main.go create mode 100644 components/image-builder-bob/pkg/builder/auth.go create mode 100644 components/image-builder-bob/pkg/builder/auth_buildkit.go create mode 100644 components/image-builder-bob/pkg/builder/builder.go create mode 100644 components/image-builder-bob/pkg/builder/config.go create mode 100644 components/image-builder-bob/supervisor-ide-config.json create mode 100644 components/image-builder-mk3/BUILD.yaml create mode 100644 components/image-builder-mk3/cmd/generate-config.go create mode 100644 components/image-builder-mk3/cmd/root.go create mode 100644 components/image-builder-mk3/cmd/run.go create mode 100644 components/image-builder-mk3/config-schema.json create mode 100755 components/image-builder-mk3/debug.sh create mode 100644 components/image-builder-mk3/example-build.json create mode 100644 components/image-builder-mk3/example-config.json create mode 100644 components/image-builder-mk3/go.mod create mode 100644 components/image-builder-mk3/go.sum create mode 100644 components/image-builder-mk3/image-builder.code-workspace create mode 100644 components/image-builder-mk3/leeway.Dockerfile create mode 100644 components/image-builder-mk3/main.go create mode 100644 components/image-builder-mk3/pkg/auth/auth.go create mode 100644 components/image-builder-mk3/pkg/orchestrator/monitor.go create mode 100644 components/image-builder-mk3/pkg/orchestrator/orchestrator.go create mode 100644 components/image-builder-mk3/pkg/resolve/resolve.go create mode 100755 components/image-builder-mk3/telepresence.sh create mode 100644 components/image-builder-mk3/workspace-image-layer/BUILD.yaml create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/Dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/Dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-append create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-prepend create mode 100755 components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/layer.sh create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/Dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/cla.md.gpg create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-append create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-prepend create mode 100755 components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/layer.sh create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/Dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-append create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-prepend create mode 100755 components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/layer.sh create mode 100644 components/image-builder-mk3/workspace-image-layer/gitpod-layer/prepend.dockerfile create mode 100755 components/image-builder-mk3/workspace-image-layer/scripts/detect-distro.sh create mode 100755 components/image-builder-mk3/workspace-image-layer/scripts/generate-dockerfile.sh create mode 100644 components/image-builder-mk3/workspace-image-layer/tests/positive/alpine-withuser.dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/tests/positive/alpine.dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-bionic.dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser-sudo.dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser.dockerfile create mode 100644 components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial.dockerfile create mode 100755 components/image-builder-mk3/workspace-image-layer/tests/positive/verify.sh create mode 100755 components/image-builder-mk3/workspace-image-layer/tests/runtests.sh create mode 100644 components/image-builder/README.md create mode 100644 components/ws-manager/pkg/manager/testdata/status_metadata.golden create mode 100644 components/ws-manager/pkg/manager/testdata/status_metadata.json diff --git a/components/BUILD.yaml b/components/BUILD.yaml index 7a3658beda53dc..d5117c79a1d119 100644 --- a/components/BUILD.yaml +++ b/components/BUILD.yaml @@ -44,6 +44,8 @@ packages: - components/ide/code:docker - components/ide/theia:docker - components/image-builder:docker + - components/image-builder-mk3:docker + - components/image-builder-bob:docker - components/local-app:docker - components/proxy:docker - components/registry-facade:docker diff --git a/components/image-builder-bob/.gitignore b/components/image-builder-bob/.gitignore new file mode 100644 index 00000000000000..696fb6baa5ce30 --- /dev/null +++ b/components/image-builder-bob/.gitignore @@ -0,0 +1 @@ +bob diff --git a/components/image-builder-bob/BUILD.yaml b/components/image-builder-bob/BUILD.yaml new file mode 100644 index 00000000000000..6d7e64c50d949a --- /dev/null +++ b/components/image-builder-bob/BUILD.yaml @@ -0,0 +1,32 @@ +packages: +- name: app + type: go + srcs: + - "**/*.go" + - "go.mod" + - "go.sum" + env: + - CGO_ENABLED=0 + - GOOS=linux + - GOPROXY= + deps: + - components/common-go:lib + config: + packaging: app +- name: docker + type: docker + srcs: + - supervisor-ide-config.json + - ide-startup.sh + deps: + - :app + - components/image-builder-mk3/workspace-image-layer:pack + config: + argdeps: + - imageRepoBase + dockerfile: leeway.Dockerfile + metadata: + helm-component: imageBuilderMk3.bob + image: + - ${imageRepoBase}/image-builder/bob:${version} + - ${imageRepoBase}/image-builder/bob:${__git_commit} diff --git a/components/image-builder-bob/cmd/build.go b/components/image-builder-bob/cmd/build.go new file mode 100644 index 00000000000000..8f0466a57452d0 --- /dev/null +++ b/components/image-builder-bob/cmd/build.go @@ -0,0 +1,48 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package cmd + +import ( + "os" + "time" + + "github.com/gitpod-io/gitpod/image-builder/bob/pkg/builder" + + log "github.com/gitpod-io/gitpod/common-go/log" + "github.com/spf13/cobra" +) + +// buildCmd represents the build command +var buildCmd = &cobra.Command{ + Use: "build", + Short: "Runs the image build and is configured using environment variables (see pkg/builder/config.go for details)", + Run: func(cmd *cobra.Command, args []string) { + if os.Geteuid() != 0 { + log.Fatal("must run as root") + } + + // give the headless listener some time to attach + time.Sleep(1 * time.Second) + + cfg, err := builder.GetConfigFromEnv() + if err != nil { + log.WithError(err).Fatal("cannot get config") + return + } + + b := &builder.Builder{ + Config: cfg, + } + err = b.Build() + if err != nil { + log.WithError(err).Fatal("build failed") + return + } + }, +} + +func init() { + rootCmd.AddCommand(buildCmd) +} diff --git a/components/image-builder-bob/cmd/daemon.go b/components/image-builder-bob/cmd/daemon.go new file mode 100644 index 00000000000000..b26fafb6bef5ac --- /dev/null +++ b/components/image-builder-bob/cmd/daemon.go @@ -0,0 +1,104 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package cmd + +import ( + "context" + "encoding/json" + "fmt" + "os" + "os/signal" + "syscall" + + log "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/image-builder/bob/pkg/builder" + + "github.com/containerd/console" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/util/progress/progressui" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" +) + +// daemonCmd represents the build command +var daemonCmd = &cobra.Command{ + Use: "daemon ", + Short: "Starts a buildkitd and pre-caches images", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + if os.Geteuid() != 0 { + log.Fatal("must run as root") + } + + skt := args[0] + cl, teardown, err := builder.StartBuildkit(skt) + if err != nil { + log.WithError(err).Fatal("cannot start daemon") + } + defer teardown() + + rawimgs := os.Getenv("BOB_CACHE_IMAGES") + if rawimgs != "" { + var images []string + err = json.Unmarshal([]byte(rawimgs), &images) + if err != nil { + log.WithError(err).Error("cannot unmarshal BOB_CACHE_IMAGES") + } + + if len(images) > 0 { + err = prewarmCache(cl, images) + if err != nil { + log.WithError(err).Error("cannot prewarm cache") + } + } + } + + // run until we're told to stop + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) + log.Info("👷 image-builder daemon is up and running. Stop with SIGINT or CTRL+C") + <-sigChan + log.Info("Received SIGINT - shutting down") + }, +} + +func prewarmCache(cl *client.Client, images []string) error { + for _, img := range images { + bld := llb.Image(img).Run(llb.Shlex("echo")) + for idx, img := range images { + bld = bld.AddMount(fmt.Sprintf("/mnt/%03d", idx), llb.Image(img)).Run(llb.Shlex("echo")) + } + pulllb, err := bld.Marshal(context.Background()) + if err != nil { + log.WithError(err).Fatal("cannot produce image pull LLB") + } + + log.Info("pulling images") + var ( + ch = make(chan *client.SolveStatus) + eg, ctx = errgroup.WithContext(context.Background()) + ) + eg.Go(func() error { + _, err := cl.Solve(ctx, pulllb, client.SolveOpt{}, ch) + return err + }) + eg.Go(func() error { + var c console.Console + // not using shared context to not disrupt display but let is finish reporting errors + return progressui.DisplaySolveStatus(context.TODO(), "", c, os.Stderr, ch) + }) + err = eg.Wait() + if err != nil { + return err + } + } + log.Info("done pulling images") + return nil +} + +func init() { + rootCmd.AddCommand(daemonCmd) +} diff --git a/components/image-builder-bob/cmd/root.go b/components/image-builder-bob/cmd/root.go new file mode 100644 index 00000000000000..86197463aeefe5 --- /dev/null +++ b/components/image-builder-bob/cmd/root.go @@ -0,0 +1,31 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package cmd + +import ( + "fmt" + "os" + + log "github.com/gitpod-io/gitpod/common-go/log" + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "bob", + Short: "Bob is the in-workspace component of the image builder. You should never have to interact with it directly.", +} + +// Execute runs the root command +func Execute() { + log.Init("bob", "", true, true) + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { +} diff --git a/components/image-builder-bob/go.mod b/components/image-builder-bob/go.mod new file mode 100644 index 00000000000000..c5641c65059199 --- /dev/null +++ b/components/image-builder-bob/go.mod @@ -0,0 +1,94 @@ +module github.com/gitpod-io/gitpod/image-builder/bob + +go 1.16 + +require ( + github.com/Microsoft/go-winio v0.5.0 // indirect + github.com/containerd/console v1.0.2 + github.com/containerd/containerd v1.5.3 + github.com/gitpod-io/gitpod/common-go v0.0.0-00010101000000-000000000000 + github.com/gofrs/flock v0.8.0 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/moby/buildkit v0.9.0 + github.com/pkg/errors v0.9.1 + github.com/spf13/cobra v1.1.3 + go.opencensus.io v0.23.0 // indirect + golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a + golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 + google.golang.org/genproto v0.0.0-20210518161634-ec7691c0a37d // indirect + google.golang.org/grpc v1.38.0 +) + +// copied from https://github.com/moby/buildkit/blob/master/go.mod#L73-L82 +replace ( + github.com/docker/docker => github.com/docker/docker v20.10.3-0.20210609100121-ef4d47340142+incompatible + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939 + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939 +) + +replace github.com/gitpod-io/gitpod/common-go => ../common-go // leeway + +replace k8s.io/api => k8s.io/api v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/apimachinery => k8s.io/apimachinery v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/apiserver => k8s.io/apiserver v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/client-go => k8s.io/client-go v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/code-generator => k8s.io/code-generator v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/component-base => k8s.io/component-base v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cri-api => k8s.io/cri-api v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kubelet => k8s.io/kubelet v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/metrics => k8s.io/metrics v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/component-helpers => k8s.io/component-helpers v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/controller-manager => k8s.io/controller-manager v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kubectl => k8s.io/kubectl v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/mount-utils => k8s.io/mount-utils v0.21.0 // leeway indirect from components/common-go:lib + +// copied from https://github.com/moby/buildkit/blob/master/go.mod#L73-L82 +replace ( + // protobuf: corresponds to containerd + github.com/golang/protobuf => github.com/golang/protobuf v1.3.5 + github.com/hashicorp/go-immutable-radix => github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe + github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 + // genproto: corresponds to containerd + google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 + // grpc: corresponds to protobuf + google.golang.org/grpc => google.golang.org/grpc v1.30.0 +) diff --git a/components/image-builder-bob/go.sum b/components/image-builder-bob/go.sum new file mode 100644 index 00000000000000..14501d63fcd2d3 --- /dev/null +++ b/components/image-builder-bob/go.sum @@ -0,0 +1,1552 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.2/go.mod h1:H8IAquKe2L30IxoupDgqTaQvKSwF/c8prYHynGIWQbA= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= +contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= +contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= +contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= +contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= +contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/AkihiroSuda/containerd-fuse-overlayfs v1.0.0/go.mod h1:0mMDvQFeLbbn1Wy8P2j3hwFhqBq+FKn8OZPno8WLmp8= +github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= +github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= +github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= +github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= +github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ= +github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3HV0OhsddkmM= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.18 h1:cYnKADiM1869gvBpos3YCteeT6sZLB48lB5dmMMs8Tg= +github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim/test v0.0.0-20200826032352-301c83a30e7c/go.mod h1:30A5igQ91GEmhYJF8TaRP79pMBOYynRsyOByfVV0dU4= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ= +github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs= +github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= +github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U= +github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6abzXN4Pg= +github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= +github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= +github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.3 h1:mfKOepNDIJ3EiBTEyHFpEqB6YSOSkGcjPDIu7cD+YzY= +github.com/containerd/containerd v1.5.3/go.mod h1:sx18RgvW6ABJ4iYUw7Q5x7bgFOAB9B6G7+yO0XBc4zw= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fuse-overlayfs-snapshotter v1.0.2/go.mod h1:nRZceC8a7dRm3Ao6cJAwuJWPFiBPaibHiFntRUnzhwU= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/stargz-snapshotter v0.0.0-20201027054423-3a04e4c2c116/go.mod h1:o59b3PCKVAf9jjiKtCc/9hLAd+5p/rfhBfm6aBcTEr4= +github.com/containerd/stargz-snapshotter v0.6.4/go.mod h1:1t0SF1gAHJhCSftWKDLVitvfF3c2qhL5hymG7C50wto= +github.com/containerd/stargz-snapshotter/estargz v0.6.4/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9U= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20190925022749-754388324470/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.0-beta1.0.20201029214301-1d20b15adc38+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.3-0.20210609100121-ef4d47340142+incompatible h1:CKSQs5KedtaAdusBPAJQS7cN1PibFX4RuThbwHgJrJE= +github.com/docker/docker v20.10.3-0.20210609100121-ef4d47340142+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libnetwork v0.8.0-dev.2.0.20200917202933-d0951081b35f/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g= +github.com/go-critic/go-critic v0.4.3/go.mod h1:j4O3D4RoIwRqlZw5jJpx0BNfXWWbpcJoKu5cYSe4YmQ= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= +github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4-0.20210608040537-544b4180ac70 h1:yxuuMouxXYv9V1HprM9jTODJPGrTrC0FYVtPSnyIXxs= +github.com/golang/snappy v0.0.4-0.20210608040537-544b4180ac70/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.23.7/go.mod h1:g/38bxfhp4rI7zeWSxcdIeHTQGS58TCak8FYcyCmavQ= +github.com/golangci/golangci-lint v1.27.0/go.mod h1:+eZALfxIuthdrHPtfM7w/R3POJLjHDfJJw8XZl9xOng= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/crfs v0.0.0-20191108021818-71d77da419c9/go.mod h1:etGhoOqfwPkooV6aqoX3eBGQOJblqdoc9XvWOeuxpPw= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE= +github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= +github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= +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.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/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.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= +github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +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= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/goreleaser/goreleaser v0.136.0/go.mod h1:wiKrPUeSNh6Wu8nUHxZydSOVQ/OZvOaO7DTtFqie904= +github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= +github.com/goreleaser/nfpm v1.3.0/go.mod h1:w0p7Kc9TAUgWMyrub63ex3M2Mgw88M4GZXoTq5UCb40= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +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.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= +github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= +github.com/hanwen/go-fuse/v2 v2.0.3/go.mod h1:0EQM6aH2ctVpvZ6a+onrQ/vaykxh2GH7hy3e13vzTUY= +github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09UnyJyqyW+bFuq864eh+wC7dj65aXmXLRe5to0= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= +github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s= +github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ= +github.com/moby/buildkit v0.9.0 h1:PcdyqIOidDySJnMNaWh96ZMKtrRWuu4QEpFGjIXhC+E= +github.com/moby/buildkit v0.9.0/go.mod h1:S9ceObCS/yMHsJD7FQx4fUCe3E7HHYjYVvk0CtynxOw= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= +github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= +github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= +github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= +github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= +github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ= +github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +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.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE= +github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d h1:pNa8metDkwZjb9g4T8s+krQ+HRgZAkqnXml+wNir/+s= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.1/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8/go.mod h1:CGFX09Ci3pq9QZdj86B+VGIdNj4VyCo2iPOGS9esB/k= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE= +github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE= +github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989/go.mod h1:i9l/TNj+yDFh9SZXUTvspXTjbFXgZGP/UvhU1S65A4A= +github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME= +github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= +github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +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 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= +github.com/sourcegraph/go-diff v0.5.3/go.mod h1:v9JDtjCE4HHHCZGId75rg8gkKKa98RVjBcBGsVmMmak= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +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.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tetafro/godot v0.3.7/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0= +github.com/tetafro/godot v0.4.2/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +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/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= +github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= +github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN64dG941IOXfhJhlH0qB92hxJ9A1ewrdUmJ6xo= +github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf h1:L0ixhsTk9j+dVnIvF6aiVCxPiaFvwTOyJxqimPq44p8= +github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf/go.mod h1:lJAxK//iyZ3yGbQswdrPTxugZIDM7sd4bEsD0x3XMHk= +github.com/tonistiigi/go-actions-cache v0.0.0-20210714033416-b93d7f1b2e70/go.mod h1:dNS+PPTqGnSl80x3wEyWWCHeON5xiBGtcM0uD6CgHNU= +github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe/go.mod h1:/+MCh11CJf2oz0BXmlmqyopK/ad1rKkcOXPoYuPCJYU= +github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939 h1:s6wDMZYNyWt8KvkjhrMpOthFPgI3JB8ipJS+eCV/psg= +github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939/go.mod h1:Vm5u/mtkj1OMhtao0v+BGo2LUoLCgHYXvRmj0jWITlE= +github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939/go.mod h1:a9cocRplhIBkUAJmak+BPDx+LVL7cTmqUPB0uBcTA4k= +github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939/go.mod h1:JQAtechjxLEL81EjmbRwxBq/XEzGaHcsPuDHAx54hg4= +github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= +github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= +github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c= +github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc= +github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= +github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +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.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= +github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= +go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib v0.21.0 h1:RMJ6GlUVzLYp/zmItxTTdAmr1gnpO/HHMFmvjAhvJQM= +go.opentelemetry.io/contrib v0.21.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= +go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC1/go.mod h1:FXJnjGCoTQL6nQ8OpFJ0JI1DrdOvMoVx49ic0Hg4+D4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1 h1:GHKxjc4EDldz8ScMDpiNwX4BAub6wGFUUo5Axm2BimU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1/go.mod h1:FliQjImlo7emZVjixV8nbDMAa4iAkcWTE9zzSEOiEPw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1/go.mod h1:cDwRc2Jrh5Gku1peGK8p9rRuX/Uq2OtVmLicjlw2WYU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.0.0-RC1/go.mod h1:OYKzEoxgXFvehW7X12WYT4/a2BlASJK9l7RtG4A91fg= +go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= +go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= +go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= +go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= +golang.org/x/build v0.0.0-20190314133821-5284462c4bec/go.mod h1:atTaCNAy0f16Ah5aV1gMSwgiKVHwu/JncqDpuRr7lS4= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +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-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201013081832-0aaa2718063a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210313202042-bd2e13477e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +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= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +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= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113232020-e2727e816f5a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200102140908-9497f49d5709/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204192400-7124308813f3/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +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= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= +google.golang.org/api v0.3.0/go.mod h1:IuvZyQh8jgscv8qWfQ4ABd8m7hEudgBFM/EdhA3BnXw= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.1-0.20200106000736-b8fc810ca6b5/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/segmentio/analytics-go.v3 v3.1.0/go.mod h1:4QqqlTlSSpVlWA9/9nDcPw+FkM2yv1NQoYjUbL9/JAw= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= +k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= +k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= +k8s.io/cloud-provider v0.21.0/go.mod h1:z17TQgu3JgUFjcgby8sj5X86YdVK5Pbt+jm/eYMZU9M= +k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= +k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw= +k8s.io/controller-manager v0.21.0/go.mod h1:Ohy0GRNRKPVjB8C8G+dV+4aPn26m8HYUI6ejloUBvUA= +k8s.io/cri-api v0.21.0/go.mod h1:nJbXlTpXwYCYuGMR7v3PQb1Du4WOGj2I9085xMVjr3I= +k8s.io/csi-translation-lib v0.21.0/go.mod h1:edq+UMpgqEx3roTuGF/03uIuSOsI986jtu65+ytLlkA= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAlS1s8DJca5q4= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= +mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc= +pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4= diff --git a/components/image-builder-bob/ide-startup.sh b/components/image-builder-bob/ide-startup.sh new file mode 100644 index 00000000000000..5f6cde6a08f7e8 --- /dev/null +++ b/components/image-builder-bob/ide-startup.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright (c) 2021 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +sleep infinity \ No newline at end of file diff --git a/components/image-builder-bob/leeway.Dockerfile b/components/image-builder-bob/leeway.Dockerfile new file mode 100644 index 00000000000000..7b9c0b301ac26a --- /dev/null +++ b/components/image-builder-bob/leeway.Dockerfile @@ -0,0 +1,30 @@ +# Copyright (c) 2021 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +FROM moby/buildkit:v0.9.0 + +USER root +RUN apk --no-cache add sudo bash \ + && addgroup -g 33333 gitpod \ + && adduser -D -h /home/gitpod -s /bin/sh -u 33333 -G gitpod gitpod \ + && echo "gitpod ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gitpod \ + && chmod 0440 /etc/sudoers.d/gitpod + +COPY components-image-builder-bob--app/bob /app/ +RUN chmod 4755 /app/bob + +COPY components-image-builder-mk3-workspace-image-layer--pack/pack.tar /app/workspace-image-layer.tar.gz +RUN mkdir /app/gplayer \ + && cd /app/gplayer \ + && tar xzf /app/workspace-image-layer.tar.gz \ + && rm -r /app/workspace-image-layer.tar.gz \ + && mv gitpod-layer/* . + +RUN mkdir /ide +COPY ide-startup.sh /ide/startup.sh +COPY supervisor-ide-config.json /ide/ + +# sudo buildctl-daemonless.sh +ENTRYPOINT [ "/app/bob" ] +CMD [ "build" ] \ No newline at end of file diff --git a/components/image-builder-bob/main.go b/components/image-builder-bob/main.go new file mode 100644 index 00000000000000..28254cd55e23a6 --- /dev/null +++ b/components/image-builder-bob/main.go @@ -0,0 +1,11 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package main + +import "github.com/gitpod-io/gitpod/image-builder/bob/cmd" + +func main() { + cmd.Execute() +} diff --git a/components/image-builder-bob/pkg/builder/auth.go b/components/image-builder-bob/pkg/builder/auth.go new file mode 100644 index 00000000000000..7aca735555116b --- /dev/null +++ b/components/image-builder-bob/pkg/builder/auth.go @@ -0,0 +1,54 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package builder + +import ( + "encoding/json" + + "github.com/moby/buildkit/session" + "github.com/moby/buildkit/session/auth" + "google.golang.org/grpc" +) + +// authConfig configures authentication for a single host +type authConfig struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func newAuthProviderFromEnvvar(content string) (at session.Attachable, err error) { + var res map[string]authConfig + err = json.Unmarshal([]byte(content), &res) + if err != nil { + return + } + + return &authProvider{ + res: res, + seeds: make(map[string][]byte), + }, nil +} + +type authProvider struct { + res map[string]authConfig + seeds map[string][]byte +} + +func (ap *authProvider) credentials(host string) (*auth.CredentialsResponse, error) { + if host == "registry-1.docker.io" { + host = "https://index.docker.io/v1/" + } + ac, ok := ap.res[host] + res := &auth.CredentialsResponse{} + if ok { + res.Username = ac.Username + res.Secret = ac.Password + } + return res, nil +} + +func (ap *authProvider) Register(server *grpc.Server) { + auth.RegisterAuthServer(server, ap) +} diff --git a/components/image-builder-bob/pkg/builder/auth_buildkit.go b/components/image-builder-bob/pkg/builder/auth_buildkit.go new file mode 100644 index 00000000000000..fdc41a9f76c1a3 --- /dev/null +++ b/components/image-builder-bob/pkg/builder/auth_buildkit.go @@ -0,0 +1,157 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// copied from https://github.com/moby/buildkit/blob/master/session/auth/authprovider/authprovider.go + +package builder + +import ( + "context" + "crypto/ed25519" + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "encoding/json" + "net/http" + "os" + "strconv" + "time" + + authutil "github.com/containerd/containerd/remotes/docker/auth" + remoteserrors "github.com/containerd/containerd/remotes/errors" + "github.com/moby/buildkit/session/auth" + "github.com/pkg/errors" + "golang.org/x/crypto/nacl/sign" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (ap *authProvider) FetchToken(ctx context.Context, req *auth.FetchTokenRequest) (rr *auth.FetchTokenResponse, err error) { + creds, err := ap.credentials(req.Host) + if err != nil { + return nil, err + } + + to := authutil.TokenOptions{ + Realm: req.Realm, + Service: req.Service, + Scopes: req.Scopes, + Username: creds.Username, + Secret: creds.Secret, + } + + if creds.Secret != "" { + defer func() { + err = errors.Wrap(err, "failed to fetch oauth token") + }() + // try GET first because Docker Hub does not support POST + // switch once support has landed + resp, err := authutil.FetchToken(ctx, http.DefaultClient, nil, to) + if err != nil { + var errStatus remoteserrors.ErrUnexpectedStatus + if errors.As(err, &errStatus) { + // retry with POST request + // As of September 2017, GCR is known to return 404. + // As of February 2018, JFrog Artifactory is known to return 401. + if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 { + resp, err := authutil.FetchTokenWithOAuth(ctx, http.DefaultClient, nil, "buildkit-client", to) + if err != nil { + return nil, err + } + + return toTokenResponse(resp.AccessToken, resp.IssuedAt, resp.ExpiresIn), nil + } + } + return nil, err + } + return toTokenResponse(resp.Token, resp.IssuedAt, resp.ExpiresIn), nil + } + // do request anonymously + resp, err := authutil.FetchToken(ctx, http.DefaultClient, nil, to) + if err != nil { + return nil, errors.Wrap(err, "failed to fetch anonymous token") + } + return toTokenResponse(resp.Token, resp.IssuedAt, resp.ExpiresIn), nil +} + +func (ap *authProvider) Credentials(ctx context.Context, req *auth.CredentialsRequest) (*auth.CredentialsResponse, error) { + resp, err := ap.credentials(req.Host) + return resp, err +} + +func (ap *authProvider) GetTokenAuthority(ctx context.Context, req *auth.GetTokenAuthorityRequest) (*auth.GetTokenAuthorityResponse, error) { + key, err := ap.getAuthorityKey(req.Host, req.Salt) + if err != nil { + return nil, err + } + + return &auth.GetTokenAuthorityResponse{PublicKey: key[32:]}, nil +} + +func (ap *authProvider) VerifyTokenAuthority(ctx context.Context, req *auth.VerifyTokenAuthorityRequest) (*auth.VerifyTokenAuthorityResponse, error) { + key, err := ap.getAuthorityKey(req.Host, req.Salt) + if err != nil { + return nil, err + } + + priv := new([64]byte) + copy((*priv)[:], key) + + return &auth.VerifyTokenAuthorityResponse{Signed: sign.Sign(nil, req.Payload, priv)}, nil +} + +func (ap *authProvider) getAuthorityKey(host string, salt []byte) (ed25519.PrivateKey, error) { + if v, err := strconv.ParseBool(os.Getenv("BUILDKIT_NO_CLIENT_TOKEN")); err == nil && v { + return nil, status.Errorf(codes.Unavailable, "client side tokens disabled") + } + + creds, err := ap.credentials(host) + if err != nil { + return nil, err + } + + var seed []byte + if s, ok := ap.seeds[host]; ok { + seed = s + } else { + seed = make([]byte, 16) + _, _ = rand.Read(seed) + ap.seeds[host] = seed + } + + mac := hmac.New(sha256.New, salt) + if creds.Secret != "" { + mac.Write(seed) + enc := json.NewEncoder(mac) + enc.Encode(creds) + } + + sum := mac.Sum(nil) + + return ed25519.NewKeyFromSeed(sum[:ed25519.SeedSize]), nil +} + +func toTokenResponse(token string, issuedAt time.Time, expires int) *auth.FetchTokenResponse { + resp := &auth.FetchTokenResponse{ + Token: token, + ExpiresIn: int64(expires), + } + if !issuedAt.IsZero() { + resp.IssuedAt = issuedAt.Unix() + } + return resp +} diff --git a/components/image-builder-bob/pkg/builder/builder.go b/components/image-builder-bob/pkg/builder/builder.go new file mode 100644 index 00000000000000..76124cae74fc3b --- /dev/null +++ b/components/image-builder-bob/pkg/builder/builder.go @@ -0,0 +1,336 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package builder + +import ( + "context" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "syscall" + "time" + + "github.com/gitpod-io/gitpod/common-go/log" + + "github.com/containerd/console" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/session" + "github.com/moby/buildkit/util/progress/progressui" + "golang.org/x/sync/errgroup" + "golang.org/x/xerrors" +) + +const ( + buildkitdSocketPath = "unix:///run/buildkit/buildkitd.sock" + maxConnectionAttempts = 10 + initialConnectionTimeout = 2 * time.Second + gplayerDir = "/app/gplayer" +) + +// Builder builds images using buildkit +type Builder struct { + Config *Config +} + +// Build runs the actual image build +func (b *Builder) Build() error { + var ( + cl *client.Client + teardown func() error = func() error { return nil } + err error + ) + if b.Config.ExternalBuildkitd != "" { + log.WithField("socketPath", b.Config.ExternalBuildkitd).Info("using external buildkit daemon") + cl, err = connectToBuildkitd(b.Config.ExternalBuildkitd) + + if err != nil { + log.Warn("cannot connect to node-local buildkitd - falling back to pod-local one") + cl, teardown, err = StartBuildkit(buildkitdSocketPath) + } + } else { + cl, teardown, err = StartBuildkit(buildkitdSocketPath) + } + if err != nil { + return err + } + defer teardown() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err = b.buildBaseLayer(ctx, cl) + if err != nil { + return err + } + err = b.buildGPLayer(ctx, cl) + if err != nil { + return err + } + + return nil +} + +func (b *Builder) buildBaseLayer(ctx context.Context, cl *client.Client) error { + if !b.Config.BuildBase { + return nil + } + + fmt.Printf("waiting for build context\n") + waitctx, cancel := context.WithTimeout(ctx, 30*time.Minute) + defer cancel() + err := waitForBuildContext(waitctx) + if err != nil { + return err + } + + fmt.Printf("building base image\n") + + var sess []session.Attachable + if baselayerAuth := b.Config.BaseLayerAuth; baselayerAuth != "" { + auth, err := newAuthProviderFromEnvvar(baselayerAuth) + if err != nil { + return fmt.Errorf("invalid base layer authentication: %w", err) + } + sess = append(sess, auth) + } + + contextdir := b.Config.ContextDir + if contextdir == "" { + contextdir = "." + } + solveOpt := client.SolveOpt{ + Frontend: "dockerfile.v0", + FrontendAttrs: map[string]string{ + "filename": filepath.Base(b.Config.Dockerfile), + }, + LocalDirs: map[string]string{ + "context": contextdir, + "dockerfile": filepath.Dir(b.Config.Dockerfile), + }, + Session: sess, + CacheImports: b.Config.LocalCacheImport(), + } + + eg, ectx := errgroup.WithContext(ctx) + ch := make(chan *client.SolveStatus) + eg.Go(func() error { + _, err := cl.Solve(ectx, nil, solveOpt, ch) + if err != nil { + return err + } + return nil + }) + eg.Go(func() error { + var c console.Console + return progressui.DisplaySolveStatus(ectx, "", c, os.Stdout, ch) + }) + err = eg.Wait() + if err != nil { + return err + } + + // First we built the base, now we push the image by building it again. + // We can't do this in one go because we cannot separate authentication for pull and push. + // However we want separate authentication for pulling the FROM of base image builds and pushing + // the built base images. + solveOpt.Exports = []client.ExportEntry{ + { + Type: "image", + Attrs: map[string]string{ + "name": b.Config.BaseRef, + "push": "true", + }, + }, + } + if lauth := b.Config.GPLayerAuth; lauth != "" { + auth, err := newAuthProviderFromEnvvar(lauth) + if err != nil { + return fmt.Errorf("invalid gp layer authentication: %w", err) + } + solveOpt.Session = []session.Attachable{auth} + } + eg, ectx = errgroup.WithContext(ctx) + ch = make(chan *client.SolveStatus) + eg.Go(func() error { + _, err := cl.Solve(ectx, nil, solveOpt, ch) + if err != nil { + return err + } + return nil + }) + eg.Go(func() error { + var c console.Console + return progressui.DisplaySolveStatus(ectx, "", c, os.Stdout, ch) + }) + err = eg.Wait() + if err != nil { + return err + } + + fmt.Printf("base image done\n") + return err +} + +func (b *Builder) buildGPLayer(ctx context.Context, cl *client.Client) (err error) { + var sess []session.Attachable + if gplayerAuth := b.Config.GPLayerAuth; gplayerAuth != "" { + auth, err := newAuthProviderFromEnvvar(gplayerAuth) + if err != nil { + return err + } + sess = append(sess, auth) + } + + solveOpt := client.SolveOpt{ + Frontend: "dockerfile.v0", + LocalDirs: map[string]string{ + "context": gplayerDir, + "dockerfile": gplayerDir, + }, + FrontendAttrs: map[string]string{ + "build-arg:baseref": b.Config.BaseRef, + }, + Exports: []client.ExportEntry{ + { + Type: "image", + Attrs: map[string]string{ + "name": b.Config.TargetRef, + "push": "true", + }, + }, + }, + Session: sess, + CacheImports: b.Config.LocalCacheImport(), + } + + eg, ctx := errgroup.WithContext(ctx) + ch := make(chan *client.SolveStatus) + eg.Go(func() error { + _, err := cl.Solve(ctx, nil, solveOpt, ch) + if err != nil { + return xerrors.Errorf("cannot build Gitpod layer: %w", err) + } + return nil + }) + eg.Go(func() error { + var c console.Console + return progressui.DisplaySolveStatus(ctx, "", c, os.Stdout, ch) + }) + return eg.Wait() +} + +func waitForBuildContext(ctx context.Context) error { + done := make(chan struct{}) + + go func() { + for { + if ctx.Err() != nil { + return + } + + if _, err := os.Stat("/workspace/.gitpod/ready"); err != nil { + continue + } + + close(done) + return + } + }() + + select { + case <-ctx.Done(): + return ctx.Err() + case <-done: + return nil + } +} + +// StartBuildkit starts a local buildkit daemon +func StartBuildkit(socketPath string) (cl *client.Client, teardown func() error, err error) { + stderr, err := ioutil.TempFile(os.TempDir(), "buildkitd_stderr") + if err != nil { + return nil, nil, fmt.Errorf("cannot create buildkitd log file: %w", err) + } + stdout, err := ioutil.TempFile(os.TempDir(), "buildkitd_stdout") + if err != nil { + return nil, nil, fmt.Errorf("cannot create buildkitd log file: %w", err) + } + + cmd := exec.Command("buildkitd", "--addr="+socketPath, "--oci-worker-net=host", "--root=/workspace/buildkit") + cmd.SysProcAttr = &syscall.SysProcAttr{Credential: &syscall.Credential{Uid: 0, Gid: 0}} + cmd.Stderr = stderr + cmd.Stdout = stdout + err = cmd.Start() + defer func() { + if err == nil { + return + } + + if cmd.Process != nil { + cmd.Process.Kill() + } + + stderr.Seek(0, 0) + stdout.Seek(0, 0) + serr, _ := ioutil.ReadAll(stderr) + sout, _ := ioutil.ReadAll(stdout) + stderr.Close() + stdout.Close() + + log.WithField("buildkitd-stderr", string(serr)).WithField("buildkitd-stdout", string(sout)).Error("buildkitd failure") + }() + if err != nil { + return nil, nil, fmt.Errorf("cannot start buildkitd: %w", err) + } + + teardown = func() error { + err := cmd.Process.Kill() + stdout.Close() + stderr.Close() + return err + } + cl, err = connectToBuildkitd(socketPath) + if err != nil { + return + } + + return +} + +func connectToBuildkitd(socketPath string) (cl *client.Client, err error) { + for i := 0; i < maxConnectionAttempts; i++ { + ctx, cancel := context.WithTimeout(context.Background(), initialConnectionTimeout) + + log.WithField("attempt", i).Debug("attempting to connect to buildkitd") + cl, err = client.New(ctx, socketPath, client.WithFailFast()) + if err != nil { + if i == maxConnectionAttempts-1 { + log.WithField("attempt", i).WithError(err).Warn("cannot connect to buildkitd") + } + + cancel() + time.Sleep(1 * time.Second) + continue + } + + _, err = cl.ListWorkers(ctx) + if err != nil { + if i == maxConnectionAttempts-1 { + log.WithField("attempt", i).WithError(err).Error("cannot connect to buildkitd") + } + + cancel() + time.Sleep(1 * time.Second) + continue + } + + cancel() + return + } + + return nil, fmt.Errorf("cannot connect to buildkitd") +} diff --git a/components/image-builder-bob/pkg/builder/config.go b/components/image-builder-bob/pkg/builder/config.go new file mode 100644 index 00000000000000..58fe42a1909cc3 --- /dev/null +++ b/components/image-builder-bob/pkg/builder/config.go @@ -0,0 +1,145 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package builder + +import ( + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/moby/buildkit/client" +) + +// Config configures a builder +type Config struct { + TargetRef string + BaseRef string + BaseContext string + BuildBase bool + BaseLayerAuth string + GPLayerAuth string + Dockerfile string + ContextDir string + ExternalBuildkitd string + localCacheImport string +} + +// GetConfigFromEnv extracts configuration from environment variables +func GetConfigFromEnv() (*Config, error) { + cfg := &Config{ + TargetRef: os.Getenv("BOB_TARGET_REF"), + BaseRef: os.Getenv("BOB_BASE_REF"), + BaseContext: os.Getenv("THEIA_WORKSPACE_ROOT"), + BuildBase: os.Getenv("BOB_BUILD_BASE") == "true", + BaseLayerAuth: os.Getenv("BOB_BASELAYER_AUTH"), + GPLayerAuth: os.Getenv("BOB_GPLAYER_AUTH"), + Dockerfile: os.Getenv("BOB_DOCKERFILE_PATH"), + ContextDir: os.Getenv("BOB_CONTEXT_DIR"), + ExternalBuildkitd: os.Getenv("BOB_EXTERNAL_BUILDKITD"), + localCacheImport: os.Getenv("BOB_LOCAL_CACHE_IMPORT"), + } + + if cfg.BaseRef == "" { + return nil, fmt.Errorf("BOB_BASE_REF must not be empty") + } + if cfg.TargetRef == "" { + return nil, fmt.Errorf("BOB_TARGET_REF must not be empty") + } + if cfg.BuildBase { + if cfg.Dockerfile == "" { + return nil, fmt.Errorf("When building the base image BOB_DOCKERFILE_PATH is mandatory") + } + var err error + cfg.Dockerfile, err = filepath.Abs(cfg.Dockerfile) + if err != nil { + return nil, fmt.Errorf("cannot make BOB_DOCKERFILE_PATH absolute: %w", err) + } + if !strings.HasPrefix(cfg.Dockerfile, "/workspace") { + return nil, fmt.Errorf("BOB_DOCKERFILE_PATH must begin with /workspace") + } + if stat, err := os.Stat(cfg.Dockerfile); err != nil || stat.IsDir() { + return nil, fmt.Errorf("BOB_DOCKERFILE_PATH does not exist or isn't a file") + } + } + + var authKey = os.Getenv("BOB_AUTH_KEY") + if authKey != "" { + if len(authKey) != 32 { + return nil, fmt.Errorf("BOB_AUTH_KEY must be exactly 32 bytes long") + } + + // we have an authkey, hence assume that the auth fields are base64 encoded and encrypted + if cfg.BaseLayerAuth != "" { + dec := make([]byte, base64.RawStdEncoding.DecodedLen(len(cfg.BaseLayerAuth))) + _, err := base64.RawStdEncoding.Decode(dec, []byte(cfg.BaseLayerAuth)) + if err != nil { + return nil, fmt.Errorf("BOB_BASELAYER_AUTH is not base64 encoded but BOB_AUTH_KEY is present") + } + cfg.BaseLayerAuth, err = decrypt(dec, authKey) + if err != nil { + return nil, fmt.Errorf("cannot decrypt BOB_BASELAYER_AUTH: %w", err) + } + } + if cfg.GPLayerAuth != "" { + dec := make([]byte, base64.RawStdEncoding.DecodedLen(len(cfg.GPLayerAuth))) + _, err := base64.RawStdEncoding.Decode(dec, []byte(cfg.GPLayerAuth)) + if err != nil { + return nil, fmt.Errorf("BOB_GPLAYER_AUTH is not base64 encoded but BOB_AUTH_KEY is present") + } + cfg.GPLayerAuth, err = decrypt(dec, authKey) + if err != nil { + return nil, fmt.Errorf("cannot decrypt BOB_GPLAYER_AUTH: %w", err) + } + } + } + + return cfg, nil +} + +// LocalCacheImport produces a cache option that imports from a local cache +func (c Config) LocalCacheImport() []client.CacheOptionsEntry { + if c.localCacheImport == "" { + return nil + } + + return []client.CacheOptionsEntry{ + { + Type: "local", + Attrs: map[string]string{ + "src": c.localCacheImport, + }, + }, + } +} + +// source: https://astaxie.gitbooks.io/build-web-application-with-golang/en/09.6.html +func decrypt(ciphertext []byte, key string) (string, error) { + c, err := aes.NewCipher([]byte(key)) + if err != nil { + return "", err + } + + gcm, err := cipher.NewGCM(c) + if err != nil { + return "", err + } + + nonceSize := gcm.NonceSize() + if len(ciphertext) < nonceSize { + return "", fmt.Errorf("ciphertext too short") + } + + nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:] + res, err := gcm.Open(nil, nonce, ciphertext, nil) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/components/image-builder-bob/supervisor-ide-config.json b/components/image-builder-bob/supervisor-ide-config.json new file mode 100644 index 00000000000000..9e6de71193643d --- /dev/null +++ b/components/image-builder-bob/supervisor-ide-config.json @@ -0,0 +1,3 @@ +{ + "entrypoint": "/ide/startup.sh" +} \ No newline at end of file diff --git a/components/image-builder-mk3/BUILD.yaml b/components/image-builder-mk3/BUILD.yaml new file mode 100644 index 00000000000000..47341f892b47cf --- /dev/null +++ b/components/image-builder-mk3/BUILD.yaml @@ -0,0 +1,33 @@ +packages: +- name: app + type: go + srcs: + - "**/*.go" + - "go.mod" + - "go.sum" + deps: + - components/common-go:lib + - components/content-service-api/go:lib + - components/content-service:lib + - components/image-builder-api/go:lib + - components/ws-manager-api/go:lib + - components/registry-facade-api/go:lib + env: + - CGO_ENABLED=0 + - GOOS=linux + config: + packaging: app +- name: docker + type: docker + deps: + - :app + - components/image-builder-mk3/workspace-image-layer:pack + argdeps: + - imageRepoBase + config: + dockerfile: leeway.Dockerfile + metadata: + helm-component: imageBuilderMk3 + image: + - ${imageRepoBase}/image-builder-mk3:${version} + - ${imageRepoBase}/image-builder-mk3:${__git_commit} \ No newline at end of file diff --git a/components/image-builder-mk3/cmd/generate-config.go b/components/image-builder-mk3/cmd/generate-config.go new file mode 100644 index 00000000000000..ab0dc69cce189e --- /dev/null +++ b/components/image-builder-mk3/cmd/generate-config.go @@ -0,0 +1,45 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +//go:generate sh -c "cd .. && CGO_ENABLED=0 go run main.go generate config > config-schema.json" + +package cmd + +import ( + "encoding/json" + "fmt" + + "github.com/alecthomas/jsonschema" + "github.com/spf13/cobra" +) + +// generateCmd represents the generate command +var generateCmd = &cobra.Command{ + Use: "generate ", + Short: "Generate Typescript/JSON schema for parts of this application", + Args: cobra.ExactArgs(1), +} + +func init() { + rootCmd.AddCommand(generateCmd) +} + +var generateConfigCmd = &cobra.Command{ + Use: "config", + Short: "Generates JSON schema for the configuration", + + Run: func(cmd *cobra.Command, args []string) { + schema := jsonschema.Reflect(&config{}) + schema.Title = "image-builder config schema - generated using img generate config" + out, err := json.MarshalIndent(schema, "", " ") + if err != nil { + panic(err) + } + fmt.Print(string(out)) + }, +} + +func init() { + generateCmd.AddCommand(generateConfigCmd) +} diff --git a/components/image-builder-mk3/cmd/root.go b/components/image-builder-mk3/cmd/root.go new file mode 100644 index 00000000000000..8054f8faeccb73 --- /dev/null +++ b/components/image-builder-mk3/cmd/root.go @@ -0,0 +1,133 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package cmd + +import ( + "crypto/tls" + "crypto/x509" + "encoding/json" + "fmt" + "io/ioutil" + "os" + + "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/common-go/tracing" + "github.com/gitpod-io/gitpod/image-builder/pkg/orchestrator" + + "github.com/mattn/go-isatty" + "github.com/spf13/cobra" + "golang.org/x/xerrors" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +var ( + // ServiceName is the name we use for tracing/logging + ServiceName = "image-builder" + // Version of this service - set during build + Version = "" +) + +var verbose bool +var configFile string +var rootCmd = &cobra.Command{ + Use: "image-builder", + Short: "Workspace image-builder service", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + log.Init(ServiceName, Version, verbose && !isatty.IsTerminal(os.Stdout.Fd()), verbose) + }, +} + +// Execute runs this main command +func Execute() { + closer := tracing.Init("image-builder") + if closer != nil { + defer closer.Close() + } + + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func getConfig() *config { + ctnt, err := ioutil.ReadFile(configFile) + if err != nil { + log.WithError(xerrors.Errorf("cannot read config: %w", err)).Error("cannot read configuration. Maybe missing --config?") + os.Exit(1) + } + + var cfg config + err = json.Unmarshal(ctnt, &cfg) + if err != nil { + log.WithError(err).Error("cannot read configuration. Maybe missing --config?") + os.Exit(1) + } + + return &cfg +} + +func init() { + rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose JSON logging") + rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file") +} + +type config struct { + Orchestrator *orchestrator.Configuration `json:"orchestrator"` + RefCache refcacheConfig `json:"refCache,omitempty"` + Service struct { + Addr string `json:"address"` + TLS tlsConfig `json:"tls"` + } `json:"service"` + Prometheus struct { + Addr string `json:"address"` + } `json:"prometheus"` + PProf struct { + Addr string `json:"address"` + } `json:"pprof"` +} + +type refcacheConfig struct { + Interval string `json:"interval"` + Refs []string `json:"refs"` +} + +type tlsConfig struct { + Authority string `json:"ca"` + Certificate string `json:"crt"` + PrivateKey string `json:"key"` +} + +// ServerOption produces the GRPC option that configures a server to use this TLS configuration +func (c *tlsConfig) ServerOption() (grpc.ServerOption, error) { + if c.Authority == "" || c.Certificate == "" || c.PrivateKey == "" { + return nil, nil + } + + // Load certs + certificate, err := tls.LoadX509KeyPair(c.Certificate, c.PrivateKey) + if err != nil { + return nil, xerrors.Errorf("cannot load TLS certificate: %w", err) + } + + // Create a certificate pool from the certificate authority + certPool := x509.NewCertPool() + ca, err := ioutil.ReadFile(c.Authority) + if err != nil { + return nil, xerrors.Errorf("cannot not read ca certificate: %w", err) + } + if ok := certPool.AppendCertsFromPEM(ca); !ok { + return nil, xerrors.Errorf("failed to append ca certs") + } + + creds := credentials.NewTLS(&tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + Certificates: []tls.Certificate{certificate}, + ClientCAs: certPool, + }) + + return grpc.Creds(creds), nil +} diff --git a/components/image-builder-mk3/cmd/run.go b/components/image-builder-mk3/cmd/run.go new file mode 100644 index 00000000000000..842aaa8badb576 --- /dev/null +++ b/components/image-builder-mk3/cmd/run.go @@ -0,0 +1,132 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package cmd + +import ( + "context" + "net" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/common-go/pprof" + "github.com/gitpod-io/gitpod/image-builder/api" + "github.com/gitpod-io/gitpod/image-builder/pkg/orchestrator" + "github.com/gitpod-io/gitpod/image-builder/pkg/resolve" + + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" + "github.com/opentracing/opentracing-go" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/spf13/cobra" + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" +) + +// runCmd represents the run command +var runCmd = &cobra.Command{ + Use: "run", + Short: "Starts the image-builder service", + Run: func(cmd *cobra.Command, args []string) { + cfg := getConfig() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + span, ctx := opentracing.StartSpanFromContext(ctx, "/cmd/Run") + defer span.Finish() + + service, err := orchestrator.NewOrchestratingBuilder(*cfg.Orchestrator) + if err != nil { + log.Fatal(err) + } + if cfg.RefCache.Interval != "" && len(cfg.RefCache.Refs) > 0 { + interval, err := time.ParseDuration(cfg.RefCache.Interval) + if err != nil { + log.WithError(err).WithField("interval", cfg.RefCache.Interval).Fatal("interval is not a valid duration") + } + + resolver := &resolve.PrecachingRefResolver{ + Resolver: &resolve.StandaloneRefResolver{}, + Candidates: cfg.RefCache.Refs, + } + go resolver.StartCaching(ctx, interval) + service.RefResolver = resolver + } + + err = service.Start(ctx) + if err != nil { + log.Fatal(err) + } + + grpcOpts := []grpc.ServerOption{ + // We don't know how good our cients are at closing connections. If they don't close them properly + // we'll be leaking goroutines left and right. Closing Idle connections should prevent that. + grpc.KeepaliveParams(keepalive.ServerParameters{MaxConnectionIdle: 30 * time.Minute}), + grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( + grpc_opentracing.StreamServerInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())), + )), + grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( + grpc_opentracing.UnaryServerInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())), + )), + } + tlsOpt, err := cfg.Service.TLS.ServerOption() + if err != nil { + log.WithError(err).Fatal("cannot use TLS config") + } + if tlsOpt != nil { + log.WithField("crt", cfg.Service.TLS.Certificate).WithField("key", cfg.Service.TLS.PrivateKey).Debug("securing gRPC server with TLS") + grpcOpts = append(grpcOpts, tlsOpt) + } else { + log.Warn("no TLS configured - gRPC server will be unsecured") + } + + server := grpc.NewServer(grpcOpts...) + api.RegisterImageBuilderServer(server, service) + lis, err := net.Listen("tcp", cfg.Service.Addr) + if err != nil { + log.WithError(err).Fatalf("cannot listen on %s", cfg.Service.Addr) + } + go func() { + err := server.Serve(lis) + if err != nil { + log.WithError(err).Fatal("cannot start server") + } + }() + log.WithField("addr", cfg.Service.Addr).Info("started workspace content server") + + if cfg.Prometheus.Addr != "" { + handler := http.NewServeMux() + handler.Handle("/metrics", promhttp.Handler()) + + go func() { + err := http.ListenAndServe(cfg.Prometheus.Addr, handler) + if err != nil { + log.WithError(err).Error("Prometheus metrics server failed") + } + }() + log.WithField("addr", cfg.Prometheus.Addr).Info("started Prometheus metrics server") + } + + if cfg.PProf.Addr != "" { + go pprof.Serve(cfg.PProf.Addr) + } + + // run until we're told to stop + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) + log.Info("👷 image-builder is up and running. Stop with SIGINT or CTRL+C") + <-sigChan + server.Stop() + // service.Stop() + log.Info("Received SIGINT - shutting down") + }, +} + +func init() { + rootCmd.AddCommand(runCmd) +} diff --git a/components/image-builder-mk3/config-schema.json b/components/image-builder-mk3/config-schema.json new file mode 100644 index 00000000000000..a13725d7af21b4 --- /dev/null +++ b/components/image-builder-mk3/config-schema.json @@ -0,0 +1,126 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/config", + "title": "image-builder config schema - generated using img generate config", + "definitions": { + "": { + "required": [ + "address", + "tls" + ], + "properties": { + "address": { + "type": "string" + }, + "tls": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/tlsConfig" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Configuration": { + "required": [ + "baseImageRepository", + "workspaceImageRepository", + "gitpodLayerLoc", + "workdir" + ], + "properties": { + "baseImageRepository": { + "type": "string" + }, + "dockerCfgFile": { + "type": "string" + }, + "gitpodLayerLoc": { + "type": "string" + }, + "imageBuildSalt": { + "type": "string" + }, + "imagebuilderRef": { + "type": "string" + }, + "workdir": { + "type": "string" + }, + "workspaceImageRepository": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "config": { + "required": [ + "builder", + "service", + "prometheus", + "pprof" + ], + "properties": { + "builder": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Configuration" + }, + "pprof": { + "$ref": "#/definitions/" + }, + "prometheus": { + "$ref": "#/definitions/" + }, + "refCache": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/refcacheConfig" + }, + "service": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/" + } + }, + "additionalProperties": false, + "type": "object" + }, + "refcacheConfig": { + "required": [ + "interval", + "refs" + ], + "properties": { + "interval": { + "type": "string" + }, + "refs": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "additionalProperties": false, + "type": "object" + }, + "tlsConfig": { + "required": [ + "ca", + "crt", + "key" + ], + "properties": { + "ca": { + "type": "string" + }, + "crt": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + } + } +} \ No newline at end of file diff --git a/components/image-builder-mk3/debug.sh b/components/image-builder-mk3/debug.sh new file mode 100755 index 00000000000000..d1750574b66107 --- /dev/null +++ b/components/image-builder-mk3/debug.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# This script builds the image builder and replaces the current deployment with it. + +docker ps &> /dev/null || (echo "You need a working Docker daemon. Maybe set DOCKER_HOST?"; exit 1) +gcloud auth list | grep typefox &>/dev/null || (echo "Login using 'gcloud auth login' for the docker push to work"; exit 1) + +leeway build .:docker -Dversion=dev +devImage=eu.gcr.io/gitpod-dev/image-builder:dev + +kubectl patch deployment image-builder --patch '{"spec": {"template": {"spec": {"containers": [{"name": "service","image": "'$devImage'"}]}}}}' +kubectl get pods --no-headers -o=custom-columns=:metadata.name | grep image-builder | xargs kubectl delete pod \ No newline at end of file diff --git a/components/image-builder-mk3/example-build.json b/components/image-builder-mk3/example-build.json new file mode 100644 index 00000000000000..3c502984136291 --- /dev/null +++ b/components/image-builder-mk3/example-build.json @@ -0,0 +1,14 @@ +{ + "file": { + "source": { + "git": { + "remoteUri": "https://github.com/AlexTugarev/test.repo", + "targetMode": "REMOTE_BRANCH", + "cloneTaget": "good-workspace-image", + "config": {} + } + }, + "dockerfilePath": ".gitpod.dockerfile", + "contextPath": "." + } +} \ No newline at end of file diff --git a/components/image-builder-mk3/example-config.json b/components/image-builder-mk3/example-config.json new file mode 100644 index 00000000000000..78c08bc18a7433 --- /dev/null +++ b/components/image-builder-mk3/example-config.json @@ -0,0 +1,19 @@ +{ + "$schema": "./config-schema.json", + "builder": { + "dockerCfgFile": "/home/gitpod/.docker/config.json", + "gitpodLayerLoc": "/tmp/build/components-image-builder-workspace-image-layer--pack.588fcb85389f5c10ae444b52674654698f446a10/pack.tar", + "baseImageRepository": "eu.gcr.io/gitpod-dev/base-images", + "workspaceImageRepository": "eu.gcr.io/gitpod-dev/workspace-images", + "imageBuildSalt": "001" + }, + "pprof": { + "address": ":9999" + }, + "prometheus": { + "address": ":9500" + }, + "service": { + "address": ":8080" + } +} \ No newline at end of file diff --git a/components/image-builder-mk3/go.mod b/components/image-builder-mk3/go.mod new file mode 100644 index 00000000000000..b6a0844c5a3d4f --- /dev/null +++ b/components/image-builder-mk3/go.mod @@ -0,0 +1,86 @@ +module github.com/gitpod-io/gitpod/image-builder + +go 1.16 + +require ( + github.com/alecthomas/jsonschema v0.0.0-20190504002508-159cbd5dba26 + github.com/containerd/containerd v1.3.4 + github.com/docker/cli v0.0.0-20191001124654-d83cd9046437 + github.com/docker/distribution v2.7.1+incompatible + github.com/docker/docker v1.13.1 + github.com/docker/docker-credential-helpers v0.6.3 // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/gitpod-io/gitpod/common-go v0.0.0-00010101000000-000000000000 + github.com/gitpod-io/gitpod/content-service/api v0.0.0-00010101000000-000000000000 + github.com/gitpod-io/gitpod/image-builder/api v0.0.0-00010101000000-000000000000 + github.com/gitpod-io/gitpod/ws-manager/api v0.0.0-00010101000000-000000000000 + github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 + github.com/mattn/go-isatty v0.0.9 + github.com/opentracing/opentracing-go v1.2.0 + github.com/prometheus/client_golang v1.11.0 + github.com/spf13/cobra v0.0.5 + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 + google.golang.org/grpc v1.38.0 + gotest.tools v2.2.0+incompatible // indirect +) + +replace github.com/gitpod-io/gitpod/common-go => ../common-go // leeway + +replace github.com/gitpod-io/gitpod/content-service => ../content-service // leeway + +replace github.com/gitpod-io/gitpod/content-service/api => ../content-service-api/go // leeway + +replace github.com/gitpod-io/gitpod/image-builder/api => ../image-builder-api/go // leeway + +replace github.com/gitpod-io/gitpod/registry-facade/api => ../registry-facade-api/go // leeway + +replace github.com/gitpod-io/gitpod/ws-manager/api => ../ws-manager-api/go // leeway + +replace k8s.io/api => k8s.io/api v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/apimachinery => k8s.io/apimachinery v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/apiserver => k8s.io/apiserver v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/client-go => k8s.io/client-go v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/code-generator => k8s.io/code-generator v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/component-base => k8s.io/component-base v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/cri-api => k8s.io/cri-api v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kubelet => k8s.io/kubelet v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/metrics => k8s.io/metrics v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/component-helpers => k8s.io/component-helpers v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/controller-manager => k8s.io/controller-manager v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/kubectl => k8s.io/kubectl v0.21.0 // leeway indirect from components/common-go:lib + +replace k8s.io/mount-utils => k8s.io/mount-utils v0.21.0 // leeway indirect from components/common-go:lib diff --git a/components/image-builder-mk3/go.sum b/components/image-builder-mk3/go.sum new file mode 100644 index 00000000000000..d3283160783cf9 --- /dev/null +++ b/components/image-builder-mk3/go.sum @@ -0,0 +1,394 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I= +github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/jsonschema v0.0.0-20190504002508-159cbd5dba26 h1:b/CA15BzZIj8xNKnBxUwUmXt3USfJjb4Gl9eJIfMLtE= +github.com/alecthomas/jsonschema v0.0.0-20190504002508-159cbd5dba26/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI= +github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/cli v0.0.0-20191001124654-d83cd9046437 h1:3lPaZRCBzk2YnoE1kcTmQQ8i32pv67lZU5R90O03ZMM= +github.com/docker/cli v0.0.0-20191001124654-d83cd9046437/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= +github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +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.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= +github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= +github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4= +go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +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/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= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +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= +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= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +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= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/segmentio/analytics-go.v3 v3.1.0/go.mod h1:4QqqlTlSSpVlWA9/9nDcPw+FkM2yv1NQoYjUbL9/JAw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= +k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/components/image-builder-mk3/image-builder.code-workspace b/components/image-builder-mk3/image-builder.code-workspace new file mode 100644 index 00000000000000..429e3e35da341c --- /dev/null +++ b/components/image-builder-mk3/image-builder.code-workspace @@ -0,0 +1,48 @@ +{ + "folders": [ + { "path": "../image-builder-bob" }, + { "path": "../image-builder-mk3" }, + { "path": "../ws-manager" }, + { "path": "../server" }, + { "path": "../../test" } + ], + "settings": { + "typescript.tsdk": "gitpod/node_modules/typescript/lib", + "[json]": { + "editor.insertSpaces": true, + "editor.tabSize": 2 + }, + "[yaml]": { + "editor.insertSpaces": true, + "editor.tabSize": 2 + }, + "[go]": { + "editor.formatOnSave": true + }, + "[tf]": { + "editor.insertSpaces": true, + "editor.tabSize": 2 + }, + "go.formatTool": "goimports", + "go.useLanguageServer": true, + "workspace.supportMultiRootWorkspace": true, + "database.connections": [ + { + "type": "mysql", + "name": "devstaging DB", + "host": "127.0.0.1:23306", + "username": "gitpod", + "database": "gitpod", + "password": "test" + } + ], + "launch": {}, + "files.exclude": { + "**/.git": true + }, + "go.lintTool": "golangci-lint", + "gopls": { + "allowModfileModifications": true + } + } +} diff --git a/components/image-builder-mk3/leeway.Dockerfile b/components/image-builder-mk3/leeway.Dockerfile new file mode 100644 index 00000000000000..575c53d3cd9b7d --- /dev/null +++ b/components/image-builder-mk3/leeway.Dockerfile @@ -0,0 +1,17 @@ +# Copyright (c) 2021 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +FROM alpine:3.13 + +# Ensure latest packages are present, like security updates. +RUN apk upgrade --no-cache \ + && apk add --no-cache git bash ca-certificates + +COPY components-image-builder-mk3--app/image-builder /app/ +RUN chmod +x /app/image-builder + +COPY components-image-builder-mk3-workspace-image-layer--pack/pack.tar /app/workspace-image-layer.tar.gz + +ENTRYPOINT [ "/app/image-builder" ] +CMD [ "-v", "help" ] \ No newline at end of file diff --git a/components/image-builder-mk3/main.go b/components/image-builder-mk3/main.go new file mode 100644 index 00000000000000..2181fd284e429e --- /dev/null +++ b/components/image-builder-mk3/main.go @@ -0,0 +1,13 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package main + +import ( + "github.com/gitpod-io/gitpod/image-builder/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/components/image-builder-mk3/pkg/auth/auth.go b/components/image-builder-mk3/pkg/auth/auth.go new file mode 100644 index 00000000000000..6be3db5cd64fab --- /dev/null +++ b/components/image-builder-mk3/pkg/auth/auth.go @@ -0,0 +1,243 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package auth + +import ( + "encoding/base64" + "encoding/json" + "os" + + "github.com/gitpod-io/gitpod/image-builder/api" + + "github.com/docker/cli/cli/config/configfile" + "github.com/docker/distribution/reference" + "github.com/docker/docker/api/types" + "github.com/gitpod-io/gitpod/common-go/log" + "golang.org/x/xerrors" +) + +// RegistryAuthenticator can provide authentication for some registries +type RegistryAuthenticator interface { + // Authenticate attempts to provide authentication for Docker registry access + Authenticate(registry string) (auth *Authentication, err error) +} + +// NewDockerConfigFileAuth reads a docker config file to provide authentication +func NewDockerConfigFileAuth(fn string) (*DockerConfigFileAuth, error) { + fp, err := os.OpenFile(fn, os.O_RDONLY, 0600) + if err != nil { + return nil, err + } + defer fp.Close() + + cfg := configfile.New(fn) + err = cfg.LoadFromReader(fp) + if err != nil { + return nil, err + } + + return &DockerConfigFileAuth{cfg}, nil +} + +// DockerConfigFileAuth uses a Docker config file to provide authentication +type DockerConfigFileAuth struct { + C *configfile.ConfigFile +} + +// Authenticate attempts to provide an encoded authentication string for Docker registry access +func (a *DockerConfigFileAuth) Authenticate(registry string) (auth *Authentication, err error) { + ac, err := a.C.GetAuthConfig(registry) + if err != nil { + return nil, err + } + + return &Authentication{ + Username: ac.Username, + Password: ac.Password, + Auth: ac.Auth, + Email: ac.Email, + ServerAddress: ac.ServerAddress, + IdentityToken: ac.IdentityToken, + RegistryToken: ac.RegistryToken, + }, nil +} + +// Authentication represents docker usable authentication +type Authentication types.AuthConfig + +// ToBase64 produces a base64 encoded JSON string usable as Docker auth +func (a *Authentication) ToBase64() string { + if a == nil { + return "" + } + + encodedJSON, err := json.Marshal(a) + if err != nil { + log.WithError(err).Warn("cannot marshal authentication - this might break things down the road") + return "" + } + return base64.URLEncoding.EncodeToString(encodedJSON) +} + +// AllowedAuthFor describes for which repositories authentication may be provided for +type AllowedAuthFor struct { + All bool + Explicit []string +} + +var ( + // AllowedAuthForAll means auth for all repositories is allowed + AllowedAuthForAll AllowedAuthFor = AllowedAuthFor{true, nil} + // AllowedAuthForNone means auth for no repositories is allowed + AllowedAuthForNone AllowedAuthFor = AllowedAuthFor{false, nil} +) + +// IsAllowNone returns true if we are to allow authentication for no repos +func (a AllowedAuthFor) IsAllowNone() bool { + return !a.All && len(a.Explicit) == 0 +} + +// IsAllowAll returns true if we are to allow authentication for all repos +func (a AllowedAuthFor) IsAllowAll() bool { + return a.All +} + +// Elevate adds a ref to the list of authenticated repositories +func (a AllowedAuthFor) Elevate(ref string) AllowedAuthFor { + pref, _ := reference.ParseNormalizedNamed(ref) + if pref == nil { + log.WithField("ref", ref).Debug("cannot elevate auth for invalid image ref") + return a + } + + return AllowedAuthFor{a.All, append(a.Explicit, reference.Domain(pref))} +} + +// Resolver resolves an auth request determining which authentication is actually allowed +type Resolver struct { + BaseImageRepository string + WorkspaceImageRepository string +} + +// ResolveRequestAuth computes the allowed authentication for a build based on its request +func (r Resolver) ResolveRequestAuth(auth *api.BuildRegistryAuth) (authFor AllowedAuthFor) { + // by default we allow nothing + authFor = AllowedAuthForNone + if auth == nil { + return + } + + switch ath := auth.Mode.(type) { + case *api.BuildRegistryAuth_Total: + if ath.Total.AllowAll { + authFor = AllowedAuthForAll + } else { + authFor = AllowedAuthForNone + } + case *api.BuildRegistryAuth_Selective: + var explicit []string + if ath.Selective.AllowBaserep { + ref, _ := reference.ParseNormalizedNamed(r.BaseImageRepository) + explicit = append(explicit, reference.Domain(ref)) + } + if ath.Selective.AllowWorkspacerep { + ref, _ := reference.ParseNormalizedNamed(r.WorkspaceImageRepository) + explicit = append(explicit, reference.Domain(ref)) + } + explicit = append(explicit, ath.Selective.AnyOf...) + authFor = AllowedAuthFor{false, explicit} + default: + authFor = AllowedAuthForNone + } + return +} + +// GetAuthFor computes the base64 encoded auth format for a Docker image pull/push +func (a AllowedAuthFor) GetAuthFor(auth RegistryAuthenticator, refstr string) (res *Authentication, err error) { + if auth == nil { + return + } + + ref, err := reference.ParseNormalizedNamed(refstr) + if err != nil { + return nil, xerrors.Errorf("cannot parse image ref: %v", err) + } + + reg := reference.Domain(ref) + var regAllowed bool + if a.IsAllowAll() { + // free for all + regAllowed = true + } else { + for _, a := range a.Explicit { + if a == reg { + regAllowed = true + break + } + } + } + if !regAllowed { + log.WithField("reg", reg).WithField("ref", ref).WithField("a", a).Debug("registry not allowed") + return nil, nil + } + + return auth.Authenticate(reg) +} + +// ImageBuildAuth is the format image builds needs +type ImageBuildAuth map[string]types.AuthConfig + +// GetImageBuildAuthFor produces authentication in the format an image builds needs +func (a AllowedAuthFor) GetImageBuildAuthFor(auth RegistryAuthenticator, refstr []string) (res ImageBuildAuth, err error) { + if auth == nil { + return nil, nil + } + + res = make(ImageBuildAuth) + for _, r := range refstr { + ref, err := reference.ParseNormalizedNamed(r) + if err != nil { + return nil, xerrors.Errorf("cannot parse image ref: %v", err) + } + + reg := reference.Domain(ref) + var regAllowed bool + if a.IsAllowAll() { + // free for all + regAllowed = true + } else { + for _, a := range a.Explicit { + if a == reg { + regAllowed = true + break + } + } + } + if !regAllowed { + continue + } + + ra, err := auth.Authenticate(reg) + if err != nil { + return nil, xerrors.Errorf("cannot get registry authentication: %v", err) + } + + res[reg] = types.AuthConfig(*ra) + } + for _, reg := range a.Explicit { + if _, ok := res[reg]; ok { + continue + } + + ra, err := auth.Authenticate(reg) + if err != nil { + return nil, xerrors.Errorf("cannot get registry authentication: %v", err) + } + + res[reg] = types.AuthConfig(*ra) + } + + return +} diff --git a/components/image-builder-mk3/pkg/orchestrator/monitor.go b/components/image-builder-mk3/pkg/orchestrator/monitor.go new file mode 100644 index 00000000000000..a48b4730f382b0 --- /dev/null +++ b/components/image-builder-mk3/pkg/orchestrator/monitor.go @@ -0,0 +1,244 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package orchestrator + +import ( + "context" + "strings" + "time" + + "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/common-go/tracing" + "github.com/gitpod-io/gitpod/image-builder/api" + wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// monitor subscribes to the ws-manager, listens for build updates and distributes them internally +func (o *Orchestrator) monitor() { + ctx := context.Background() + for { + sub, err := o.wsman.Subscribe(ctx, &wsmanapi.SubscribeRequest{ + MustMatch: &wsmanapi.MetadataFilter{ + Owner: buildWorkspaceOwnerID, + }, + }) + if err != nil { + log.WithError(err).Info("connection to ws-manager lost - retrying") + time.Sleep(5 * time.Second) + continue + } + + for { + msg, err := sub.Recv() + if err != nil { + log.WithError(err).Info("connection to ws-manager lost - retrying") + time.Sleep(5 * time.Second) + break + } + + log := msg.GetLog() + if log != nil { + o.publishLog(log.Id, log.Message) + continue + } + + status := msg.GetStatus() + if status != nil { + o.publishStatus(status) + continue + } + } + } +} + +// retryIfUnavailable makes multiple attempts to execute op if op returns an UNAVAILABLE gRPC status code +func retryIfUnavailable(ctx context.Context, op func(ctx context.Context) error, initialBackoff time.Duration, retries int) (err error) { + span, ctx := tracing.FromContext(ctx, "retryIfUnavailable") + defer tracing.FinishSpan(span, &err) + + for i := 0; i < retries; i++ { + err := op(ctx) + span.LogKV("attempt", i) + + if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable { + // service is unavailable - try again aftersme time + time.Sleep(initialBackoff * time.Duration(1+i)) + log.WithField("attempt", i).Warn("ws-manager currently unavailable - retrying") + continue + } + + if err != nil { + return err + } + return nil + } + + // we've maxed out our retry attempts + return status.Error(codes.Unavailable, "workspace services are currently unavailable") +} + +func (o *Orchestrator) censor(buildID string, words []string) { + o.mu.Lock() + defer o.mu.Unlock() + + o.censorship[buildID] = words +} + +func (o *Orchestrator) publishLog(buildID string, message string) { + o.mu.RLock() + listener, ok := o.logListener[buildID] + o.mu.RUnlock() + + // we don't have any log listener for this build + if !ok { + return + } + + o.mu.RLock() + wds := o.censorship[buildID] + o.mu.RUnlock() + for _, w := range wds { + message = strings.ReplaceAll(message, w, "") + } + + for l := range listener { + select { + case l <- &api.LogsResponse{ + Content: []byte(message), + }: + continue + + case <-time.After(5 * time.Second): + log.Warn("timeout while forwarding log to listener - dropping listener") + o.mu.Lock() + ll := o.logListener[buildID] + // In the meantime the listener list may have been removed/cleared by a call to clearListener. + // We don't have to do any work in this case. + if ll != nil { + close(l) + delete(ll, l) + } + o.mu.Unlock() + } + } +} + +func (o *Orchestrator) publishStatus(msg *wsmanapi.WorkspaceStatus) { + o.mu.RLock() + listener, ok := o.buildListener[msg.Id] + o.mu.RUnlock() + + // we don't have any log listener for this build + if !ok { + return + } + + resp := extractBuildResponse(msg) + for l := range listener { + select { + case l <- resp: + continue + + case <-time.After(5 * time.Second): + log.Warn("timeout while forwarding status to listener - dropping listener") + o.mu.Lock() + ll := o.buildListener[msg.Id] + // In the meantime the listener list may have been removed/cleared by a call to clearListener. + // We don't have to do any work in this case. + if ll != nil { + close(l) + delete(ll, l) + } + o.mu.Unlock() + } + } +} + +func extractBuildResponse(status *wsmanapi.WorkspaceStatus) *api.BuildResponse { + var ( + s = api.BuildStatus_running + msg = status.Message + ) + if status.Phase == wsmanapi.WorkspacePhase_STOPPING { + if status.Conditions.Failed == "" { + s = api.BuildStatus_done_success + } else { + s = api.BuildStatus_done_failure + msg = status.Conditions.Failed + } + } + + return &api.BuildResponse{ + Ref: status.Metadata.Annotations["ref"], + BaseRef: status.Metadata.Annotations["baseref"], + Message: msg, + Status: s, + } +} + +type buildListener chan *api.BuildResponse + +type logListener chan *api.LogsResponse + +func (o *Orchestrator) registerBuildListener(buildID string) (c <-chan *api.BuildResponse, cancel func()) { + o.mu.Lock() + defer o.mu.Unlock() + + l := make(buildListener) + ls := o.buildListener[buildID] + if ls == nil { + ls = make(map[buildListener]struct{}) + } + ls[l] = struct{}{} + o.buildListener[buildID] = ls + + cancel = func() { + o.mu.Lock() + defer o.mu.Unlock() + ls := o.buildListener[buildID] + if ls == nil { + return + } + delete(ls, l) + o.buildListener[buildID] = ls + } + return l, cancel +} + +func (o *Orchestrator) registerLogListener(buildID string) (c <-chan *api.LogsResponse, cancel func()) { + o.mu.Lock() + defer o.mu.Unlock() + + l := make(logListener) + ls := o.logListener[buildID] + if ls == nil { + ls = make(map[logListener]struct{}) + } + ls[l] = struct{}{} + o.logListener[buildID] = ls + + cancel = func() { + o.mu.Lock() + defer o.mu.Unlock() + ls := o.logListener[buildID] + if ls == nil { + return + } + delete(ls, l) + o.logListener[buildID] = ls + } + return l, cancel +} + +func (o *Orchestrator) clearListener(buildID string) { + o.mu.Lock() + defer o.mu.Unlock() + + delete(o.buildListener, buildID) + delete(o.logListener, buildID) + delete(o.censorship, buildID) +} diff --git a/components/image-builder-mk3/pkg/orchestrator/orchestrator.go b/components/image-builder-mk3/pkg/orchestrator/orchestrator.go new file mode 100644 index 00000000000000..32b0c4e2ea4572 --- /dev/null +++ b/components/image-builder-mk3/pkg/orchestrator/orchestrator.go @@ -0,0 +1,724 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package orchestrator + +import ( + "context" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "time" + + "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/common-go/tracing" + csapi "github.com/gitpod-io/gitpod/content-service/api" + protocol "github.com/gitpod-io/gitpod/image-builder/api" + "github.com/gitpod-io/gitpod/image-builder/pkg/auth" + "github.com/gitpod-io/gitpod/image-builder/pkg/resolve" + wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api" + grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" + "github.com/opentracing/opentracing-go" + "golang.org/x/xerrors" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/status" +) + +const ( + // buildWorkspaceOwnerID is the owner ID we pass to ws-manager + buildWorkspaceOwnerID = "image-builder" + + // maxBuildRuntime is the maximum time a build is allowed to take + maxBuildRuntime = 60 * time.Minute +) + +// Configuration configures the orchestrator +type Configuration struct { + WorkspaceManager struct { + Address string `json:"address"` + TLS struct { + Authority string `json:"ca"` + Certificate string `json:"crt"` + PrivateKey string `json:"key"` + } `json:"tls,omitempty"` + } `json:"wsman"` + + // AuthFile points to a Docker configuration file from which we draw registry authentication + AuthFile string `json:"authFile"` + + // BaseImageRepository configures repository where we'll push base images to. + BaseImageRepository string `json:"baseImageRepository"` + + // WorkspaceImageRepository configures the repository where we'll push the final workspace images to. + // Note that the workspace nodes/kubelets need access to this repository. + WorkspaceImageRepository string `json:"workspaceImageRepository"` + + // GitpodLayerLoc is the path to the Gitpod layer tar file + GitpodLayerLoc string `json:"gitpodLayerLoc"` + + // BuilderImage is an image ref to the workspace builder image + BuilderImage string `json:"builderImage"` + + // BuilderAuthKeyFile points to a keyfile shared by the builder workspaces and this service. + // The key is used to encypt authentication data shipped across environment varibales. + BuilderAuthKeyFile string `json:"builderAuthKeyFile,omitempty"` +} + +// NewOrchestratingBuilder creates a new orchestrating image builder +func NewOrchestratingBuilder(cfg Configuration) (res *Orchestrator, err error) { + var authentication auth.RegistryAuthenticator + if cfg.AuthFile != "" { + fn := cfg.AuthFile + if tproot := os.Getenv("TELEPRESENCE_ROOT"); tproot != "" { + fn = filepath.Join(tproot, fn) + } + + authentication, err = auth.NewDockerConfigFileAuth(fn) + if err != nil { + return + } + } + + gplayerHash, err := computeGitpodLayerHash(cfg.GitpodLayerLoc) + if err != nil { + return + } + + var builderAuthKey [32]byte + if cfg.BuilderAuthKeyFile != "" { + fn := cfg.BuilderAuthKeyFile + if tproot := os.Getenv("TELEPRESENCE_ROOT"); tproot != "" { + fn = filepath.Join(tproot, fn) + } + + var data []byte + data, err = ioutil.ReadFile(fn) + if err != nil { + return + } + if len(data) != 32 { + err = fmt.Errorf("builder auth key must be exactly 32 bytes long") + return + } + copy(builderAuthKey[:], data) + } + + opts := []grpc.DialOption{ + grpc.WithUnaryInterceptor(grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer()))), + grpc.WithStreamInterceptor(grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer()))), + } + if cfg.WorkspaceManager.TLS.Authority != "" || cfg.WorkspaceManager.TLS.Certificate != "" && cfg.WorkspaceManager.TLS.PrivateKey != "" { + ca := cfg.WorkspaceManager.TLS.Authority + crt := cfg.WorkspaceManager.TLS.Certificate + key := cfg.WorkspaceManager.TLS.PrivateKey + + // Telepresence (used for debugging only) requires special paths to load files from + if root := os.Getenv("TELEPRESENCE_ROOT"); root != "" { + ca = filepath.Join(root, ca) + crt = filepath.Join(root, crt) + key = filepath.Join(root, key) + } + + rootCA, err := os.ReadFile(ca) + if err != nil { + return nil, xerrors.Errorf("could not read ca certificate: %s", err) + } + certPool := x509.NewCertPool() + if ok := certPool.AppendCertsFromPEM(rootCA); !ok { + return nil, xerrors.Errorf("failed to append ca certs") + } + + certificate, err := tls.LoadX509KeyPair(crt, key) + if err != nil { + log.WithField("config", cfg.WorkspaceManager.TLS).Error("Cannot load ws-manager certs - this is a configuration issue.") + return nil, xerrors.Errorf("cannot load ws-manager certs: %w", err) + } + + creds := credentials.NewTLS(&tls.Config{ + ServerName: "ws-manager", + Certificates: []tls.Certificate{certificate}, + RootCAs: certPool, + MinVersion: tls.VersionTLS12, + }) + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + opts = append(opts, grpc.WithInsecure()) + } + conn, err := grpc.Dial(cfg.WorkspaceManager.Address, opts...) + if err != nil { + return + } + + return &Orchestrator{ + Config: cfg, + Auth: authentication, + AuthResolver: auth.Resolver{ + BaseImageRepository: cfg.BaseImageRepository, + WorkspaceImageRepository: cfg.WorkspaceImageRepository, + }, + RefResolver: &resolve.StandaloneRefResolver{}, + + wsman: wsmanapi.NewWorkspaceManagerClient(conn), + gplayerHash: gplayerHash, + buildListener: make(map[string]map[buildListener]struct{}), + logListener: make(map[string]map[logListener]struct{}), + censorship: make(map[string][]string), + builderAuthKey: builderAuthKey, + }, nil +} + +func computeGitpodLayerHash(gitpodLayerLoc string) (string, error) { + if tproot := os.Getenv("TELEPRESENCE_ROOT"); tproot != "" { + gitpodLayerLoc = filepath.Join(tproot, gitpodLayerLoc) + } + if fn := os.Getenv("GITPOD_LAYER_LOC"); fn != "" { + gitpodLayerLoc = fn + } + + inpt, err := os.OpenFile(gitpodLayerLoc, os.O_RDONLY, 0600) + if err != nil { + return "", xerrors.Errorf("cannot compute gitpod layer hash: %w", err) + } + defer inpt.Close() + + hash := sha256.New() + _, err = io.Copy(hash, inpt) + if err != nil { + return "", xerrors.Errorf("cannot compute gitpod layer hash: %w", err) + } + return fmt.Sprintf("%x", hash.Sum([]byte{})), nil +} + +// Orchestrator runs image builds by orchestrating headless build workspaces +type Orchestrator struct { + Config Configuration + Auth auth.RegistryAuthenticator + AuthResolver auth.Resolver + RefResolver resolve.DockerRefResolver + + gplayerHash string + wsman wsmanapi.WorkspaceManagerClient + + builderAuthKey [32]byte + buildListener map[string]map[buildListener]struct{} + logListener map[string]map[logListener]struct{} + censorship map[string][]string + mu sync.RWMutex + + protocol.UnimplementedImageBuilderServer +} + +// Start fires up the internals of this image builder +func (o *Orchestrator) Start(ctx context.Context) error { + go o.monitor() + return nil +} + +// ResolveBaseImage returns the "digest" form of a Docker image tag thereby making it absolute. +func (o *Orchestrator) ResolveBaseImage(ctx context.Context, req *protocol.ResolveBaseImageRequest) (resp *protocol.ResolveBaseImageResponse, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "ResolveBaseImage") + defer tracing.FinishSpan(span, &err) + + tracing.LogRequestSafe(span, req) + + reqauth := o.AuthResolver.ResolveRequestAuth(req.Auth) + + refstr, err := o.getAbsoluteImageRef(ctx, req.Ref, reqauth) + if err != nil { + return nil, status.Errorf(codes.Internal, "cannot resolve base image ref: %v", err) + } + + return &protocol.ResolveBaseImageResponse{ + Ref: refstr, + }, nil +} + +// ResolveWorkspaceImage returns information about a build configuration without actually attempting to build anything. +func (o *Orchestrator) ResolveWorkspaceImage(ctx context.Context, req *protocol.ResolveWorkspaceImageRequest) (resp *protocol.ResolveWorkspaceImageResponse, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "ResolveWorkspaceImage") + defer tracing.FinishSpan(span, &err) + tracing.LogRequestSafe(span, req) + + reqauth := o.AuthResolver.ResolveRequestAuth(req.Auth) + baseref, err := o.getBaseImageRef(ctx, req.Source, reqauth) + if err != nil { + return nil, status.Errorf(codes.Internal, "cannot resolve base image: %s", err.Error()) + } + refstr, err := o.getWorkspaceImageRef(ctx, baseref, reqauth) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "cannot produce image ref: %v", err) + } + span.LogKV("refstr", refstr, "baseref", baseref) + + // to check if the image exists we must have access to the image caching registry and the refstr we check here does not come + // from the user. Thus we can safely use auth.AllowedAuthForAll here. + auth, err := auth.AllowedAuthForAll.GetAuthFor(o.Auth, refstr) + if err != nil { + return nil, status.Errorf(codes.Internal, "cannot get workspace image authentication: %v", err) + } + exists, err := o.checkImageExists(ctx, refstr, auth) + if err != nil { + return nil, status.Errorf(codes.Internal, "cannot resolve workspace image: %s", err.Error()) + } + + var status protocol.BuildStatus + if exists { + status = protocol.BuildStatus_done_success + } else { + status = protocol.BuildStatus_unknown + } + + return &protocol.ResolveWorkspaceImageResponse{ + Status: status, + Ref: refstr, + }, nil +} + +// Build initiates the build of a Docker image using a build configuration. If a build of this +// configuration is already ongoing no new build will be started. +func (o *Orchestrator) Build(req *protocol.BuildRequest, resp protocol.ImageBuilder_BuildServer) (err error) { + span, ctx := opentracing.StartSpanFromContext(resp.Context(), "Build") + defer tracing.FinishSpan(span, &err) + tracing.LogRequestSafe(span, req) + + // resolve build request authentication + reqauth := o.AuthResolver.ResolveRequestAuth(req.Auth) + + baseref, err := o.getBaseImageRef(ctx, req.Source, reqauth) + if xerrors.Is(err, resolve.ErrNotFound) { + return status.Error(codes.NotFound, "cannot resolve base image") + } + if err != nil { + return status.Errorf(codes.Internal, "cannot resolve base image: %q", err) + } + wsrefstr, err := o.getWorkspaceImageRef(ctx, baseref, reqauth) + if err != nil { + return status.Errorf(codes.Internal, "cannot produce workspace image ref: %q", err) + } + wsrefAuth, err := auth.AllowedAuthForAll.GetAuthFor(o.Auth, wsrefstr) + if err != nil { + return status.Errorf(codes.Internal, "cannot get workspace image authentication: %q", err) + } + + // check if needs build -> early return + exists, err := o.checkImageExists(ctx, wsrefstr, wsrefAuth) + if err != nil { + return status.Errorf(codes.Internal, "cannot check if image is already built: %q", err) + } + if exists && !req.GetForceRebuild() { + // If the workspace image exists, so should the baseimage if we've built it. + // If we didn't build it and the base image doesn't exist anymore, getWorkspaceImageRef will have failed to resolve the baseref. + baserefAbsolute, err := o.getAbsoluteImageRef(ctx, baseref, auth.AllowedAuthForAll) + if err != nil { + return status.Errorf(codes.Internal, "cannot resolve base image ref: %q", err) + } + + // image has already been built - no need for us to start building + err = resp.Send(&protocol.BuildResponse{ + Status: protocol.BuildStatus_done_success, + Ref: wsrefstr, + BaseRef: baserefAbsolute, + }) + if err != nil { + return err + } + return nil + } + + // Once a build is running we don't want it cancelled becuase the server disconnected i.e. during deployment. + // Instead we want to impose our own timeout/lifecycle on the build. Using context.WithTimeout does not shadow its parent's + // cancelation (see https://play.golang.org/p/N3QBIGlp8Iw for an example/experiment). + ctx, cancel := context.WithTimeout(&parentCantCancelContext{Delegate: ctx}, maxBuildRuntime) + defer cancel() + + var ( + buildID = computeBuildID(wsrefstr) + buildBase = "false" + contextPath = "." + dockerfilePath = "Dockerfile" + ) + var initializer *csapi.WorkspaceInitializer = &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Empty{ + Empty: &csapi.EmptyInitializer{}, + }, + } + if fsrc := req.Source.GetFile(); fsrc != nil { + buildBase = "true" + initializer = fsrc.Source + contextPath = fsrc.ContextPath + dockerfilePath = fsrc.DockerfilePath + } + dockerfilePath = filepath.Join("/workspace", dockerfilePath) + + if contextPath == "" { + contextPath = filepath.Dir(dockerfilePath) + } + contextPath = filepath.Join("/workspace", strings.TrimPrefix(contextPath, "/workspace")) + + baseLayerAuth, err := o.getAuthFor(reqauth) + if err != nil { + return + } + gplayerAuth, err := o.getAuthFor(auth.AllowedAuthForAll, wsrefstr, baseref) + if err != nil { + return + } + + o.censor(buildID, []string{ + wsrefstr, + baseref, + strings.Split(wsrefstr, ":")[0], + strings.Split(baseref, ":")[0], + }) + + // push some log to the client before starting the job, just in case the build workspace takes a while to start up + o.publishLog(buildID, "starting image build") + + err = retryIfUnavailable(ctx, func(ctx context.Context) (err error) { + _, err = o.wsman.StartWorkspace(ctx, &wsmanapi.StartWorkspaceRequest{ + Id: buildID, + Metadata: &wsmanapi.WorkspaceMetadata{ + MetaId: buildID, + Annotations: map[string]string{ + "ref": wsrefstr, + }, + // TODO(cw): use the actual image build owner here and move to annotation based filter + // when retrieving running image builds. + Owner: buildWorkspaceOwnerID, + }, + Spec: &wsmanapi.StartWorkspaceSpec{ + CheckoutLocation: ".", + Initializer: initializer, + Timeout: maxBuildRuntime.String(), + WorkspaceImage: o.Config.BuilderImage, + IdeImage: o.Config.BuilderImage, + WorkspaceLocation: contextPath, + Envvars: []*wsmanapi.EnvironmentVariable{ + {Name: "BOB_TARGET_REF", Value: wsrefstr}, + {Name: "BOB_BASE_REF", Value: baseref}, + {Name: "BOB_BUILD_BASE", Value: buildBase}, + {Name: "BOB_BASELAYER_AUTH", Value: baseLayerAuth}, + {Name: "BOB_GPLAYER_AUTH", Value: gplayerAuth}, + {Name: "BOB_DOCKERFILE_PATH", Value: dockerfilePath}, + {Name: "BOB_CONTEXT_DIR", Value: contextPath}, + {Name: "BOB_AUTH_KEY", Value: string(o.builderAuthKey[:])}, + {Name: "GITPOD_TASKS", Value: `[{"name": "build", "init": "sudo -E /app/bob build"}]`}, + }, + }, + Type: wsmanapi.WorkspaceType_IMAGEBUILD, + }) + return + }, 1*time.Second, 5) + if err != nil && status.Code(err) != codes.AlreadyExists { + return status.Errorf(codes.Internal, "cannot start build: %q", err) + } + + updates, cancel := o.registerBuildListener(buildID) + defer cancel() + for { + update := <-updates + if update == nil { + // channel was closed unexpectatly + return status.Error(codes.Aborted, "subscription canceled - please try again") + } + + err := resp.Send(update) + if err != nil { + log.WithError(err).Error("cannot forward build update - dropping listener") + return status.Errorf(codes.Unknown, "cannot send update: %v", err) + } + + if update.Status == protocol.BuildStatus_done_failure || update.Status == protocol.BuildStatus_done_success { + // build is done + o.clearListener(buildID) + break + } + } + + return nil +} + +// Logs listens to the build output of an ongoing Docker build identified build the build ID +func (o *Orchestrator) Logs(req *protocol.LogsRequest, resp protocol.ImageBuilder_LogsServer) (err error) { + span, ctx := opentracing.StartSpanFromContext(resp.Context(), "Build") + defer tracing.FinishSpan(span, &err) + tracing.LogRequestSafe(span, req) + + rb, err := o.getAllRunningBuilds(ctx) + var found bool + for _, bld := range rb { + if bld.Ref == req.BuildRef { + found = true + break + } + } + if !found { + return status.Error(codes.NotFound, "build not found") + } + + buildID := computeBuildID(req.BuildRef) + logs, cancel := o.registerLogListener(buildID) + defer cancel() + for { + update := <-logs + if update == nil { + break + } + + err := resp.Send(update) + if err != nil { + log.WithError(err).Error("cannot forward log output - dropping listener") + return status.Errorf(codes.Unknown, "cannot send log output: %v", err) + } + } + + return +} + +// ListBuilds returns a list of currently running builds +func (o *Orchestrator) ListBuilds(ctx context.Context, req *protocol.ListBuildsRequest) (resp *protocol.ListBuildsResponse, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "ListBuilds") + defer tracing.FinishSpan(span, &err) + + res, err := o.getAllRunningBuilds(ctx) + if err != nil { + return + } + + return &protocol.ListBuildsResponse{Builds: res}, nil +} + +func extractBuildStats(ws *wsmanapi.WorkspaceStatus) *protocol.BuildInfo { + return &protocol.BuildInfo{ + Ref: ws.Metadata.Annotations["ref"], + StartedAt: ws.Metadata.StartedAt.Seconds, + Status: protocol.BuildStatus_running, + } +} + +func (o *Orchestrator) getAllRunningBuilds(ctx context.Context) (res []*protocol.BuildInfo, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "getAllRunningBuilds") + defer tracing.FinishSpan(span, &err) + + wss, err := o.wsman.GetWorkspaces(ctx, &wsmanapi.GetWorkspacesRequest{ + MustMatch: &wsmanapi.MetadataFilter{ + Owner: buildWorkspaceOwnerID, + }, + }) + if err != nil { + return + } + + res = make([]*protocol.BuildInfo, len(wss.Status)) + for i, ws := range wss.Status { + res[i] = extractBuildStats(ws) + } + + return +} + +func (o *Orchestrator) checkImageExists(ctx context.Context, ref string, authentication *auth.Authentication) (exists bool, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "checkImageExists") + defer tracing.FinishSpan(span, &err) + span.SetTag("ref", ref) + + _, err = o.RefResolver.Resolve(ctx, ref, resolve.WithAuthentication(authentication)) + if err == resolve.ErrNotFound { + return false, nil + } + if err != nil { + return false, err + } + + return true, nil +} + +// getAbsoluteImageRef returns the "digest" form of an image, i.e. contains no mutable image tags +func (o *Orchestrator) getAbsoluteImageRef(ctx context.Context, ref string, allowedAuth auth.AllowedAuthFor) (res string, err error) { + auth, err := allowedAuth.GetAuthFor(o.Auth, ref) + if err != nil { + return "", xerrors.Errorf("cannt resolve base image ref: %w", err) + } + + return o.RefResolver.Resolve(ctx, ref, resolve.WithAuthentication(auth)) +} + +func (o *Orchestrator) getBaseImageRef(ctx context.Context, bs *protocol.BuildSource, allowedAuth auth.AllowedAuthFor) (res string, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "getBaseImageRef") + defer tracing.FinishSpan(span, &err) + + switch src := bs.From.(type) { + case *protocol.BuildSource_Ref: + return o.getAbsoluteImageRef(ctx, src.Ref.Ref, allowedAuth) + + case *protocol.BuildSource_File: + manifest := map[string]string{ + "DockerfilePath": src.File.DockerfilePath, + "DockerfileVersion": src.File.DockerfileVersion, + "ContextPath": src.File.ContextPath, + } + // workspace starter will only ever send us Git sources. Should that ever change, we'll need to add + // manifest support for the other initializer types. + if src.File.Source.GetGit() != nil { + fsrc := src.File.Source.GetGit() + manifest["Source"] = "git" + manifest["CloneTarget"] = fsrc.CloneTaget + manifest["RemoteURI"] = fsrc.RemoteUri + } else { + return "", xerrors.Errorf("unsupported context initializer") + } + // Go maps do NOT maintain their order - we must sort the keys to maintain a stable order + var keys []string + for k := range manifest { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] }) + var dfl string + for _, k := range keys { + dfl += fmt.Sprintf("%s: %s\n", k, manifest[k]) + } + span.LogKV("manifest", dfl) + + hash := sha256.New() + n, err := hash.Write([]byte(dfl)) + if err != nil { + return "", xerrors.Errorf("cannot compute src image ref: %w", err) + } + if n < len(dfl) { + return "", xerrors.Errorf("cannot compute src image ref: short write") + } + + // the mkII image builder supported an image hash salt. That salt broke other assumptions, + // which is why this mkIII implementation does not support it anymore. We need to stay compatible + // with the previous means of computing the hash though. This is why we add an extra breakline here, + // basically defaulting to an empty salt string. + _, err = fmt.Fprintln(hash, "") + if err != nil { + return "", xerrors.Errorf("cannot compute src image ref: %w", err) + } + + return fmt.Sprintf("%s:%x", o.Config.BaseImageRepository, hash.Sum([]byte{})), nil + + default: + return "", xerrors.Errorf("invalid base image") + } +} + +func (o *Orchestrator) getWorkspaceImageRef(ctx context.Context, baseref string, allowedAuth auth.AllowedAuthFor) (ref string, err error) { + //nolint:staticcheck,ineffassign + span, ctx := opentracing.StartSpanFromContext(ctx, "getWorkspaceImageRef") + defer tracing.FinishSpan(span, &err) + + cnt := []byte(fmt.Sprintf("%s\n%s\n", baseref, o.gplayerHash)) + hash := sha256.New() + n, err := hash.Write(cnt) + if err != nil { + return "", xerrors.Errorf("cannot produce workspace image name: %w", err) + } + if n < len(cnt) { + return "", xerrors.Errorf("cannot produce workspace image name: %w", io.ErrShortWrite) + } + + dst := hash.Sum([]byte{}) + return fmt.Sprintf("%s:%x", o.Config.WorkspaceImageRepository, dst), nil +} + +// parentCantCancelContext is a bit of a hack. We have some operations which we want to keep alive even after clients +// disconnect. gRPC cancels the context once a client disconnects, thus we intercept the cancelation and act as if +// nothing had happened. +// +// This cannot be the best way to do this. Ideally we'd like to intercept client disconnect, but maintain the usual +// cancelation mechanism such as deadlines, timeouts, explicit cancelation. +type parentCantCancelContext struct { + Delegate context.Context + done chan struct{} +} + +func (*parentCantCancelContext) Deadline() (deadline time.Time, ok bool) { + // return ok==false which means there's no deadline set + return time.Time{}, false +} + +func (c *parentCantCancelContext) Done() <-chan struct{} { + return c.done +} + +func (c *parentCantCancelContext) Err() error { + err := c.Delegate.Err() + if err == context.Canceled { + return nil + } + + return err +} + +func (c *parentCantCancelContext) Value(key interface{}) interface{} { + return c.Delegate.Value(key) +} + +func computeBuildID(ref string) string { + // The buildID will be used as workspaceID which must not be longer than 63 characters because it's a kubernetes label. + // Using sha224 makes sure our hash is shorter than 63 charts. SHA256 would be 64 chars when printed as hex. + return fmt.Sprintf("%x", sha256.Sum224([]byte(ref))) +} + +// source: https://astaxie.gitbooks.io/build-web-application-with-golang/en/09.6.html +func encrypt(plaintext []byte, key [32]byte) ([]byte, error) { + c, err := aes.NewCipher(key[:]) + if err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + nonce := make([]byte, gcm.NonceSize()) + if _, err = io.ReadFull(rand.Reader, nonce); err != nil { + return nil, err + } + + return gcm.Seal(nonce, nonce, plaintext, nil), nil +} + +func (o *Orchestrator) getAuthFor(inp auth.AllowedAuthFor, refs ...string) (res string, err error) { + buildauth, err := inp.GetImageBuildAuthFor(o.Auth, refs) + if err != nil { + return + } + resb, err := json.Marshal(buildauth) + if err != nil { + return + } + res = string(resb) + + if len(o.builderAuthKey) > 0 { + resb, err = encrypt(resb, o.builderAuthKey) + if err != nil { + return + } + + // I know this call is really backwards, but the Encode() API is so difficult to use properly. + res = base64.RawStdEncoding.EncodeToString(resb) + } + + return +} diff --git a/components/image-builder-mk3/pkg/resolve/resolve.go b/components/image-builder-mk3/pkg/resolve/resolve.go new file mode 100644 index 00000000000000..1a599922621ed5 --- /dev/null +++ b/components/image-builder-mk3/pkg/resolve/resolve.go @@ -0,0 +1,170 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package resolve + +import ( + "context" + "fmt" + "strings" + "sync" + "time" + + "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/common-go/tracing" + "github.com/gitpod-io/gitpod/image-builder/pkg/auth" + + dockerremote "github.com/containerd/containerd/remotes/docker" + "github.com/docker/distribution/reference" + "github.com/opentracing/opentracing-go" + "golang.org/x/xerrors" +) + +// ErrNotFound is returned when the reference was not found +var ErrNotFound = fmt.Errorf("not found") + +// StandaloneRefResolver can resolve image references without a Docker daemon +type StandaloneRefResolver struct{} + +// Resolve resolves a mutable Docker tag to its absolute digest form by asking the corresponding Docker registry +func (*StandaloneRefResolver) Resolve(ctx context.Context, ref string, opts ...DockerRefResolverOption) (res string, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "StandaloneRefResolver.Resolve") + defer func() { + var rerr error + if err != ErrNotFound { + rerr = err + } + tracing.FinishSpan(span, &rerr) + }() + + options := getOptions(opts) + + r := dockerremote.NewResolver(dockerremote.ResolverOptions{ + Authorizer: dockerremote.NewDockerAuthorizer(dockerremote.WithAuthCreds(func(host string) (username, password string, err error) { + if options.Auth == nil { + return + } + + return options.Auth.Username, options.Auth.Password, nil + })), + }) + + // The ref may be what Docker calls a "familiar" name, e.g. ubuntu:latest instead of docker.io/library/ubuntu:latest. + // To make this a valid digested form we first need to normalize that familiar name. + pref, err := reference.ParseNormalizedNamed(ref) + if err != nil { + return "", xerrors.Errorf("cannt resolve image ref: %w", err) + } + + // The reference is already in digest form we don't have to do anything + if _, ok := pref.(reference.Canonical); ok { + span.LogKV("result", ref) + return ref, nil + } + + nref := pref.String() + span.LogKV("normalized-ref", nref) + + res, _, err = r.Resolve(ctx, nref) + if err != nil && strings.Contains(err.Error(), "not found") { + err = ErrNotFound + } + + return +} + +type opts struct { + Auth *auth.Authentication +} + +// DockerRefResolverOption configures reference resolution +type DockerRefResolverOption func(o *opts) + +// WithAuthentication sets a base64 encoded authentication for accessing a Docker registry +func WithAuthentication(auth *auth.Authentication) DockerRefResolverOption { + return func(o *opts) { + o.Auth = auth + } +} + +func getOptions(o []DockerRefResolverOption) *opts { + var res opts + for _, opt := range o { + opt(&res) + } + return &res +} + +// DockerRefResolver resolves a mutable Docker tag to its absolute digest form. +// For example: gitpod/workspace-full:latest becomes docker.io/gitpod/workspace-full@sha256:sha-hash-goes-here +type DockerRefResolver interface { + // Resolve resolves a mutable Docker tag to its absolute digest form. + Resolve(ctx context.Context, ref string, opts ...DockerRefResolverOption) (res string, err error) +} + +// PrecachingRefResolver regularly resolves a set of references and returns the cached value when asked to resolve that reference. +type PrecachingRefResolver struct { + Resolver DockerRefResolver + Candidates []string + + mu sync.RWMutex + cache map[string]string +} + +var _ DockerRefResolver = &PrecachingRefResolver{} + +// StartCaching starts the precaching of resolved references at the given interval. This function blocks until the context is canceled +// and is intended to run as a Go routine. +func (pr *PrecachingRefResolver) StartCaching(ctx context.Context, interval time.Duration) { + span, ctx := opentracing.StartSpanFromContext(ctx, "PrecachingRefResolver.StartCaching") + defer tracing.FinishSpan(span, nil) + + t := time.NewTicker(interval) + + log.WithField("interval", interval.String()).WithField("refs", pr.Candidates).Info("starting Docker ref pre-cache") + + pr.cache = make(map[string]string) + for { + for _, c := range pr.Candidates { + res, err := pr.Resolver.Resolve(ctx, c) + if err != nil { + log.WithError(err).WithField("ref", c).Warn("unable to precache reference") + continue + } + + pr.mu.Lock() + pr.cache[c] = res + pr.mu.Unlock() + + log.WithField("ref", c).WithField("resolved-to", res).Debug("pre-cached Docker ref") + } + + select { + case <-t.C: + case <-ctx.Done(): + log.Debug("context cancelled - shutting down Docker ref pre-caching") + return + } + } +} + +// Resolve aims to resolve a ref using its own cache first and asks the underlying resolver otherwise +func (pr *PrecachingRefResolver) Resolve(ctx context.Context, ref string, opts ...DockerRefResolverOption) (res string, err error) { + span, ctx := opentracing.StartSpanFromContext(ctx, "PrecachingRefResolver.Resolve") + defer tracing.FinishSpan(span, &err) + + pr.mu.RLock() + defer pr.mu.RUnlock() + + if pr.cache == nil { + return pr.Resolver.Resolve(ctx, ref, opts...) + } + + res, ok := pr.cache[ref] + if !ok { + return pr.Resolver.Resolve(ctx, ref, opts...) + } + + return res, nil +} diff --git a/components/image-builder-mk3/telepresence.sh b/components/image-builder-mk3/telepresence.sh new file mode 100755 index 00000000000000..6e9abe629909e7 --- /dev/null +++ b/components/image-builder-mk3/telepresence.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +leeway build --save /tmp/gplayer.tgz components/image-builder/workspace-image-layer:pack +export GITPOD_LAYER_LOC=/tmp/gplayer.tgz + +if [ "$1" == "intp" ]; then + echo "starting delve" + dlv debug --listen=127.0.0.1:32991 --headless --api-version=2 github.com/gitpod-io/gitpod/image-builder -- run -v --config /tmp/imgblddebug/config/image-builder.json + exit $? +fi + +if [ "$1" == "run" ]; then + telepresence --mount /tmp/imgblddebug --swap-deployment image-builder --method vpn-tcp --run go run main.go run -v --config /tmp/imgblddebug/config/image-builder.json + exit $? +fi + +if [ "$1" == "debug" ]; then + telepresence --mount /tmp/imgblddebug --swap-deployment image-builder --method vpn-tcp --run "$0" intp + exit $? +fi + +echo "usage: $0 run|debug" +exit 1 \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/BUILD.yaml b/components/image-builder-mk3/workspace-image-layer/BUILD.yaml new file mode 100644 index 00000000000000..48fede063ee56e --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/BUILD.yaml @@ -0,0 +1,15 @@ +packages: + - name: pack + type: generic + srcs: + - "gitpod-layer/**" + - "scripts/**" + deps: + - components/gitpod-cli:app + config: + commands: + - ["mkdir", "pack"] + - ["mv", "components-gitpod-cli--app/gitpod-cli", "pack/gitpod-cli"] + - ["mv", "gitpod-layer", "scripts", "pack/"] + - ["rm", "-r", "components-gitpod-cli--app"] + - ["tar", "cvfz", "pack.tar", "-C", "pack", "."] diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/Dockerfile b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/Dockerfile new file mode 100644 index 00000000000000..19818e6ada924d --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/Dockerfile @@ -0,0 +1,34 @@ +# Copyright (c) 2021 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +ARG baseref +FROM ${baseref} AS prep + +USER root + +# Copy config and layer script +COPY . /var/gitpod + +# Run layer +WORKDIR /var/gitpod +RUN mv /var/gitpod/gitpod-cli /usr/bin/gp \ + && sh /var/gitpod/build.sh + +# Switch to user gitpod +USER gitpod + +# Configure user shell +# TODO Remove this in the near future when we do not need ~/.bashrc appends/prepends any more +RUN \ + # REALLY do not print motd + touch ~/.hushlogin && \ + # Configure shell + BASH_RC=~/.bashrc; if [ -f "$BASH_RC" ]; then cp "$BASH_RC" ~/.bashrc-org; else touch ~/.bashrc-org; fi && \ + cat /var/gitpod/gitpod/.bashrc-prepend > "$BASH_RC" && \ + cat ~/.bashrc-org >> "$BASH_RC" && \ + cat /var/gitpod/gitpod/.bashrc-append >> "$BASH_RC" + +USER root +RUN rm -rf /var/gitpod +USER gitpod diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/Dockerfile b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/Dockerfile new file mode 100644 index 00000000000000..b2fe09d1943532 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/Dockerfile @@ -0,0 +1,34 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# 'FROM ${BASE_IMAGE}' prepended here + +############################################################################### +# REQUIRED +############################################################################### +# !!! We expect users to configure their containers as root !!! +USER root + +# Copy config and layer script +COPY ./gitpod /var/gitpod + +# Run layer +RUN /var/gitpod/layer.sh \ + # Remove the script itself + # TODO Really necessary? + && rm -f /var/gitpod/layer.sh + +# Switch to user gitpod +USER gitpod + +# Configure user shell +# TODO Remove this in the near future when we do not need ~/.bashrc appends/prepends any more +RUN \ + # REALLY do not print motd + touch ~/.hushlogin && \ + # Configure shell + BASH_RC=~/.bashrc; if [ -f "$BASH_RC" ]; then cp "$BASH_RC" ~/.bashrc-org; else touch ~/.bashrc-org; fi && \ + cat /var/gitpod/.bashrc-prepend > "$BASH_RC" && \ + cat ~/.bashrc-org >> "$BASH_RC" && \ + cat /var/gitpod/.bashrc-append >> "$BASH_RC" diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-append b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-append new file mode 100644 index 00000000000000..b9cf898682b6a5 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-append @@ -0,0 +1,27 @@ + +############################################################################### +########## Gitpod - append - begin +############################################################################### + +export GEM_HOME=/workspace/.rvm +export GEM_PATH=$GEM_HOME:$GEM_PATH +export PATH=/workspace/.rvm/bin:$PATH + +export PIPENV_VENV_IN_PROJECT=true +export PIP_USER=yes +export PYTHONUSERBASE=/workspace/.pip-modules +export PATH=$PYTHONUSERBASE/bin:$PATH +unset PIP_TARGET +unset PYTHONPATH + +# Set CARGO_HOME to reside in workspace if: +# - it's RUNTIME (/workspace present) +if [ -d /workspace ]; then + export CARGO_HOME=/workspace/.cargo + export PATH=$CARGO_HOME/bin:$PATH +fi + +############################################################################### +########## Gitpod - append - end +############################################################################### + diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-prepend b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-prepend new file mode 100644 index 00000000000000..a500a0b1c76d72 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/.bashrc-prepend @@ -0,0 +1,37 @@ + +############################################################################### +########## Gitpod - prepend +############################################################################### + +# Prompt color and bash_completion +export PS1='\[\e]0;\u \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u\[\033[00m\] \[\033[01;34m\]\w \$ \[\033[00m\]' + +# editor config - should be removed when registry facade is default +if [ -z "$EDITOR" ]; then + export EDITOR="gp open -w" +fi +if [ -z "$VISUAL" ]; then + export VISUAL="$EDITOR" +fi +if [ -z "$GIT_EDITOR" ]; then + export GIT_EDITOR="$EDITOR" +fi + +# Workaround Java pre v10 by explicitly setting "-Xmx" for all Hotspot/openJDK VMs +if [ -n "$GITPOD_MEMORY" ]; then + export JAVA_TOOL_OPTIONS="-Xmx${GITPOD_MEMORY}m"; +fi + +# Completion for gp command +. <(gp completion) +# ide cli config - should be removed when registry facade is default +if [ ! -d "/ide/bin/" ]; then + alias open='gp open' + alias code='gp open' +fi + +export BROWSER="${BROWSER:=gp-preview}" + +############################################################################### +########## Gitpod - prepend +############################################################################### diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/layer.sh b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/layer.sh new file mode 100755 index 00000000000000..7bb5ba38a72f95 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/alpine/gitpod/layer.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# >>> Expects to be run as root + +# Quit immediately on non-zero exit code +set -e; + +# Install necessary tools only if they are not yet installed +INSTALLED_PACKAGES=$(apk list -I git bash | wc -l) +if [ "$INSTALLED_PACKAGES" != 2 ]; then + # Install + apk add --no-cache --update \ + git \ + bash +fi + +# Disable root login +# +# Note: The root account should already be disabled by default, at least in Ubuntu. +# Source: https://askubuntu.com/a/20453 +# +# In the past, we used to set a password here, when Gitpod managed workspaces via SSH. +# Now, it doesn't really matter if root is locked or not, because we prevent privilege +# escalation in containers with "allowPrivilegeEscalation=false" anyway: +# https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation +passwd -l root || true + +# Create gp-preview symlink required for the browser variable +ln -s /usr/bin/gp /usr/bin/gp-preview + +# Create Gitpod user +if ! id -u gitpod; then + # user doesn't exist, let's add it. + echo "Creating new user 'gitpod'."; + addgroup -g 33333 gitpod; + adduser -D -h /home/gitpod -s /bin/sh -u 33333 -G gitpod gitpod; + echo "gitpod:gitpod" | chpasswd; + + # To allow users to not know anything about our gitpod user, copy over all stuff from the previous user (root) + cp -R /root/. /home/gitpod; + chown -R gitpod:gitpod /home/gitpod/; +else + USER_ID=$(id -u gitpod) + if [ "$USER_ID" -eq 33333 ]; then + # users exists and has user id 33333. We hope that the user does not have ID 0, because that grants root privileges + echo "Found user 'gitpod'. Reusing it."; + echo "gitpod:gitpod" | chpasswd; + else + # error + echo "Error: User 'gitpod' exists but does not have user-id 33333. The user-id is $(id -u)"; + exit 1; + fi +fi diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/Dockerfile b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/Dockerfile new file mode 100644 index 00000000000000..5a0f247827a7d7 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/Dockerfile @@ -0,0 +1,38 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# 'FROM ${BASE_IMAGE}' prepended here + +############################################################################### +# REQUIRED +############################################################################### +# !!! We expect users to configure their containers as root !!! +USER root + +# Copy config and layer script +# FIXME(Kreyren): This is a duplicate code that should be present in all distros +COPY ./gitpod /var/gitpod + +# Run layer +# FIXME(Kreyren): This is a duplicate code that should be present in all distros +RUN /var/gitpod/layer.sh \ + # Remove the script itself + # TODO Really necessary? + && rm -f /var/gitpod/layer.sh + +# Switch to user gitpod +# FIXME(Kreyren): This is a duplicate code that should be present in all distros +USER gitpod + +# Configure user shell +# TODO Remove this in the near future when we do not need ~/.bashrc appends/prepends any more +# FIXME(Kreyren): This is a duplicate code that should be present in all distros +RUN \ + # REALLY do not print motd + touch ~/.hushlogin && \ + # Configure shell + BASH_RC=~/.bashrc; if [ -f "$BASH_RC" ]; then cp "$BASH_RC" ~/.bashrc-org; else touch ~/.bashrc-org; fi && \ + cat /var/gitpod/.bashrc-prepend > "$BASH_RC" && \ + cat ~/.bashrc-org >> "$BASH_RC" && \ + cat /var/gitpod/.bashrc-append >> "$BASH_RC" diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/cla.md.gpg b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/cla.md.gpg new file mode 100644 index 0000000000000000000000000000000000000000..0e27a7cc8bff711510a1d4210f9e61c590962e15 GIT binary patch literal 6131 zcmVPeOLs6{QJj8)&A?Tt9mwdu@IBV?X4zvszi+6|p5pma|#n zUHj?1E9u2g@4dVa$=c0k1}M!WFd@)P=?sN*mOu$hLV(b;0cKhfXem%yLWYpSP}&9p zZE4y`1{yx5=iK|=(|fX<^^%y<`VU#UALpEV?)mtgbMJcfD=yl3@lPMQ^vw^RyXW$Y z?>}^V<&~0d(s)BY`N;M8gY{7&s!C0p5+thG)D)&8yAB%D*P65)wMbUiY*VQ?wr-L+ z1y)#;WNId*4OmQMYQat_lPXM0-cm)^EMn`#Fm=OJs4bdpn3O5etE8sbhAu}AChDWp zk%RT|ZrFm%&q3pq0s#iW+5 zHYrgo%K36hUbMy24D1MhB}&aH&QtsiIh=L-DsOit?r3BD5{oD)-?D< zV2==>D-01u25L%G0Xak~9f|DOGwY}-(ZmK#@7Y7%AWC|L95pL+4d-&PhN!4Gu?FS? z`Z#1N>$+{(j;!c$=@hQX>JBhy-D%C+i!>Oo>6p7TSNlB#*BN{A{C|CmU0$rj} zbmV5A%)*%BgVunHP;*U?TZZ$idW(pfOz64+928q^6WbIut4d9a?PfZ#>WYDEY~*7Z zRDuIbVZtu6?#rx#zHz5i7vYlPOu+$_Nr5{8(wc6gBvgXia2*5%C8BS&C@b=5)pfP& zXt3Wu82l79B4idxeo-KYGmH7f5ppbFK3ZHVlVh1uDN`utbBm-{BH3bLCST4M3-D`} zWD3X0wfVx#2%%u^aQh$*_=ZJLzy|1u$|FS4Bo!`9tBsHrtkNADe5;|@BFZsB@Z2rY z1U1?UWjjGmS>bLEx+v$%bGZ>xC>CNQUzjcB3rBMExk7n_%;!qkqaa%5aDFadK0bnb zXY=JkZgG*!f~*;`kSUe(*`>Kmi7YIY7K)2Gu-g9q{!SbME}k6+l;c}_K=}$N3Ei`S zLdi-M?wo>Ak*Wf!tx>pl5$^%)Z54cVwd0uZD`rUz77C_`rB`h@E(POXU0p>w5&R&r z7_1|r7c5kKOqT^DU)fg7n9kx;5TQ@Hd!vt6k!F>YZHw^(6%7o zUjtKDUroUGV%46M`JomezCZ?mOTydoz`-^gklk%iomt-~7-y?a(V_g)xaUQt8auZ} zMacDzjXPR(1SFKmI*aHU1)sS!5wD0=-IR!Epc`2U*PkpFFB>|#)b?DQdq=s<+}v?b zCcs^=x}n=}++DWrfRaJNx?|Nnp+C4#&a0z5S8ux@k{n$rWv6^KOcJF^Zp7Oc z2HZ)3oR~yiLY6jyqyCSq7`lx~O;ia*n#OFTg-auV$)5Qy2@yBKL%88I|f1uWQjrmq;2ScFeRYK!BI;$*DOPn+~wpZ2d1ll z@T~2yWq=5!;|s-np-gTR5*Vw+1mGfSHWdr7=m`js^D{7IIvV^qZw~IQ{NDMp=h`i0 zW^sIM-`;(Dx15=Ka|$HsREj0(?a9CXA0bD0o{72f3cge*M22nP`oC}#)af=HXd13Qvq zV>c#KlVhWeF^8`YARk_L9&eu z^L%;=az_pdx?;&sr;%aIJ??q<+>}s*f)?~kVl7B9RVBFn`uyTjX0G>kJ~!p_=-zuI zUtW1J_MQ1|8h9eO{P1!5NQ`3U1^e_-x*R6#BZ1HwK3DVUp;xMU1yZB|7$+{%s_3YY zbg-tSn3Uc0+-rxZDxwuvYeWES1jF2DVA>RoI{XJqwe9v4R+6Hfj_%F^|J`-`XHlEP zc4r6M0D|<^&~Diq+-;HFS?tAVgS#bj2!0G!bj*ILLx&FT7PV=2WfbU(m5NE5z_tN3 zws0O{C1B3MKpdbKBu6479Lr2p6!3B*FdgI5=c9+{H;&yLxZKlldke*x6}&_Q%qxY= zeD2JaC{XPC^dga)&*bMiG;X=YtqC?>sAnWu-wk*V&%kC&L&Q)KCkF@lZ+FE|WSHF^ zv-PQ{YxGfX6wya;)c5)$x%ri&#rfP+!iPACxY=xk7A$1SN2dn7rRf20tP?wMK^FzQ zi1Ywo)>)We$Q7<%xgJ0Ag_VU;@eR3bdCE2&8eGFPHr1w9XYhFWXt999SgMD38Hy2u z4B@E3xQk<(CR zGLI4l@<$5AQf`G6V*=@$BB_pJ?b^lq096uY(`m>{%UTpRrGVTnEVOY=KPeQ;`7AHx zu#WSjwSpZVzpTV9JaX+qM>_*z0XTAMVXBu81o{q4TW%P-{ z_@{0e8zR0=GUd!%M~G2@OitpW(Y>8Di@EGlDPKO`W7(b|{M@xEH8xAv!6j38ItzSc z7{A~MKk^xFG&$CwDcD>1fKH;Ebj0l;4v9wGqf_lC-R4{%w z^)>!}py^r+nSdNr?dB6^v$51)6g9YP466Y6EfNHTf$u&+5FMpW zp{z{Dpe~OIY=K{$#cqD|vKWFrmRi{XSMVp)8f;Dojw|w%Fou6ZaCgnr9V4)e{qD8D z7Th1Q25RUQmPPE9&xX~kTjevl)69N$^)2WO;B#>!d-?g1a!cZMB zVnn=gIpH!?s1?T%e#pFL+1L?dX&lU^sQ@5_t#AxJ5o@!#UiarM@r?u*xNcb!rpy*qOlP<3(sV3g7opYz@HWX%m7xN7uP6+ zb_AfD8Jxq2R|~!|^}dXdl{kL5xBvxhA|OYMeztbsKQ8$A8(mW)101~z zE)w-J`XW`UF_!$(n+6u|x&q=v&%ZAU(GEO2#QK*TqBb`NhHzlQ@=x)y#UplkV=q}i z*X=q2LM)|}=#FhTP+(MpmdWK^KEJ@rL5ZVjGBC(CU)V{9gpIJWBPJS0Z+l?o5Wtcf zR`J}~+eC0KEEb@+E+ON4Trs<_@dlGYVkAtv>pq;&eK=cBZY)!5Zb-ih$GFfG$LMaJ z;c)tV32s(*v`#GbcCeDm*POu1>tmELBC(jJ#{enB6e#8xj_ZMzYPu?FHTaiMEXx7N zlp32D-_Je8TQ2L873bX!wg;r7s&07yW9)U>O7IofPg})EC?@=LuDs2|&Jym##n`e+%U2jkzg#Ti) zf?ag{nh4*u;O`1D^v0Yp1aLYKU?V&T00Ed~W(TDzmfUqPc-}a3Ot?D0tXNo*m@JV@ z?2TgVR5Eq|hS;*0lu8bD$lz_GiiALq%uNKmb?yOXgwh+)N#KMV!HI7{n_`nqePe@5 zgaFA)@~ygPL771{R~R{5@^@Lk4@d&81jCF`FIV!7@34xN%GCMto4A*}x)tq)jSdLK z$rk)GvFfclmU~EWLjM$QA&b3$msil(Gvd;=C}|BuWO{=dEMK(zS~VnQU$)KjRubv*wULhqhyll7{Mb z1G?iuHL!9h%5Io-?ujtRvKa>F&e1}S;N6Lw)_ZXI*>-SS`1%ste62##=Y;n?@}+aaZ68C69JrZQ%84BDv+qEB;2M>7YaJi3)IwBC)l>%+1!7+XkK0*V(hTsI}3DJ1-nB_WTff zNeOhx8e*GS0}mGp_CsV=_pmo!xX#qAXbl)UMAKq`^nzY3dOTTRqUiBj!PJe6g6|Ya zi#6}u=LzI?odf(8fIG4RN`mO^zF?f9rrtS2@FlJH3&Lhi{Qnc}*KO#jZsRk<=Dk}M z#+iM%h8}on;5hkypnY zma}ICk1^vJ4dHtz+P9^+@sLfpnAo%+;q{0c2x2j-PT@wGirH=Q@`InH_qn>X#3$13 zTMJYaQr*pj>{+s(ly$&9s?Jr&{2K8nzIlK*v;km&hQ*4GInoK#7StR8-!s4?n+VlF zNXvF05ik!%^I_(IFpFKyAo?A?oJw#XC6d6OiFoL=D7;k1rxsWc5<9dkG3nr;1Z+GJyK0SN(OlOJ$_r6EmT#y`O?9zJ z32;b`Ks1y@nB*&KP}A8wF5)9o6YQgg50bmOuZP#~Ve2I&%3(j4J+tHsxlpb&sHsz-A{S{FjJy4CuN9mZ9tfssqkJ)^4x^8;kbQ%-*fsxc08D^i5!AUzXYp8oPZ?fJDLQqPSxL3JaK*74~$Pc8OTF4&WO*Fpg?to0cJz zXaZ{gH4EY~O>jEVNQ|v-LP;Xyr$Yf<0x(rX4Q^Fb4TM{_kfp**ZZ==Y&0u8R!g@h$ zoYI8QMiL>+C;CXNy5W$XR}lQ0$uE{m#VNtxD?|vhDK?AEMNwwDU|0|`j>&>BgP}|> zJOp&}K>uQP$o7J280PlqL}CHf1A|xt#5Ax@D{&G?4#tOv1`^Augc0qg3(g)C`hvE? z!N5!jUfPnTRNF2USFy}QM#o3?l41Bvje?C32~Q#n@O1**ELTcU0)87pXJT>^SPXOB zZNOzgP=wJ3u?^OovS`ZP@^T`=GP~VnL2!@GDZ3=oWL}hc7pPZLkAq!B_d==H+Z#WS z>=5%#!qKqMnV7_s!M+LH)Ifv{=XYm9=SNMBjgL%_;qfGV_EsddLb@z`R}RG6oCajF?LvPRovb>H5JOm1c@IX;?7Wk>gqr;;-h+3|h*XS0Vh$?^T8hm)DZ z2WC^r)%fj~j9q%s#XB#0{gr)}HsAQ~$-}St?C)Ow#AE9}edN+NKX~q*%XeII@{#NF z7e#hm?u~ryEtmc5s-5Y3FIFFW@I8;;b;Yay`>p%eqQhSwzVi7`+0R_O{M!9@|Ly+P z$!~r8p_|z4f`*^$pPb zTd(+V_Pf75_WZ&XYoGbaxnqa!_{MvG=k+^2{lWuJ#NTFT3n%stT=(U-zxT?sU-`;F zS^Y`--^M46JEZ3_cR%~oWq+R#_OEdKRXpM7?A_%{cmPp|*kziQ7tu;c9y+;rgKk==x$A9|pQ^!93bpW1ovmp*#u;@2KJ^Xz@=H@wfz-)fG$Dv`MF$L}0`I=<)kPgI7!`LR!1Al&;7^eYUbN+D;_Y%`mb1gQ|5zXe{#on&h35r Fe*gw-_2B>j literal 0 HcmV?d00001 diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-append b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-append new file mode 100644 index 00000000000000..a437676f8f4b02 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-append @@ -0,0 +1,11 @@ + + +############################################################################### +########## Gitpod - append - begin +############################################################################### + + +############################################################################### +########## Gitpod - append - end +############################################################################### + diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-prepend b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-prepend new file mode 100644 index 00000000000000..c1b70b76754e50 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/.bashrc-prepend @@ -0,0 +1,53 @@ + + +############################################################################### +########## Gitpod - prepend +############################################################################### + +# Prompt color and bash_completion +export PS1='\[\e]0;\u \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u\[\033[00m\] \[\033[01;34m\]\w \$ \[\033[00m\]' +#source /etc/bash_completion + +# editor config - should be removed when registry facade is default +if [ -z "$EDITOR" ]; then + export EDITOR="gp open -w" +fi +if [ -z "$VISUAL" ]; then + export VISUAL="$EDITOR" +fi +if [ -z "$GIT_EDITOR" ]; then + export GIT_EDITOR="$EDITOR" +fi + +# Completion for gp command +. <(gp completion) +# ide cli config - should be removed when registry facade is default +if [ ! -d "/ide/bin/" ]; then + alias open='gp open' + alias code='gp open' +fi + +export GEM_HOME=/workspace/.rvm +export GEM_PATH=$GEM_HOME:$GEM_PATH +export PATH=/workspace/.rvm/bin:$PATH + +export PIPENV_VENV_IN_PROJECT=true +export PIP_USER=yes +export PYTHONUSERBASE=/workspace/.pip-modules +export PATH=$PYTHONUSERBASE/bin:$PATH +unset PIP_TARGET +unset PYTHONPATH + +# Set CARGO_HOME to reside in workspace if: +# - it's RUNTIME (/workspace present) +if [ -d /workspace ]; then + export CARGO_HOME=/workspace/.cargo + export PATH=$CARGO_HOME/bin:$PATH +fi + +export BROWSER="${BROWSER:=gp-preview}" + +############################################################################### +########## Gitpod - prepend +############################################################################### + diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/layer.sh b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/layer.sh new file mode 100755 index 00000000000000..cf2c71086af398 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/amazon/gitpod/layer.sh @@ -0,0 +1,156 @@ +#!/bin/sh +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# Created by Jacob Hrbek under WTFPL license + +###! This script is designed to be run in docker environment + +# Required for docker to terminate the build on failure +set -e + +myName="amazonlinux Layer" + +efixme() { + if [ "$IGNORE_FIXME" != 1 ]; then + printf 'FIXME: %s\n' "$1" + else + # NOTICE(Krey): Terminates the script otherwise + true + fi +} +edebug() { + if [ "$DEBUG" = 1 ]; then + printf 'DEBUG: %s\n' "$1" + else + # NOTICE(Krey): Terminates the script otherwise + true + fi +} +die() { + case "$1" in + 1|3) printf 'FATAL: %s\n' "$2" ;; + 26) printf 'SECURITY: %s\n' "$2" ;; + *) + printf 'FATAL: %s\n' "$2" + exit 1 + esac + + exit "$1" +} + +# Expects to be run as root +if [ "$(id -u)" != 0 ]; then + die 3 "Amazonlinux wrapper is not expected to be invoked on non-root" +elif [ "$(id -u)" = 0 ]; then + # FIXME(Kreyren): Sanitization needed + true +else + die 255 "Checking for root acces in amazonlinux layer" +fi + +# Disable root login +# Notice(Krey): Not a big deal according to jankermones +if ! command -v passwd; then + true +elif command -v passwd; then + passwd -l root || true +else + die 255 "Unexpected happend while checking for passwd command" +fi + +# Create gp-preview symlink required for the browser variable +ln -s /usr/bin/gp /usr/bin/gp-preview || die 1 "Unable to symlink gp to gp-preview" + +## Gitpod user +expected_user="gitpod" +expected_uid="33333" +## Gitpod group +expected_group="gitpod" +expected_gid="33333" + +# Disable repository protection +# HOTFIX(Krey): Results in `packages excluded due to repository priority protections` on gitpod for unknown reason +printf '%s\n' "[main]" "enabled = 0" > /etc/yum/pluginconf.d/priorities.conf + +# Install git and vim +yum install -y git || die 1 "Unable to install required git package" +yum install -y vim || die 1 "Unable to install required vim package" +# DNM(Krey): Hotfix due weird behaviour +##yum install -y bash || die 1 "Unable to install required bash package" + +# Create Gitpod user +# INFO(Kreyren): This is stripped from https://github.com/jankeromnes/gitpod-layers/pull/3 +# Resolve expected group +if grep -q "$expected_group:.*:$expected_gid:" /etc/group; then + edebug "Expected group $expected_group with gid $expected_gid is already present, skipping resolution logic" +elif ! grep -q "$expected_group:.*:$expected_gid:" /etc/group; then + edebug "Expected group '$expected_group' with expected gid '$expected_gid' is not present, resolving.." + # CORE - Make a new group if needed + if command -v groupadd >/dev/null; then + edebug "Detected that command 'groupadd' is available for us to use" + groupadd \ + --gid "$expected_gid" \ + "$expected_group" \ + || die 1 "Command groupadd failed to create expected group $expected_group with expected gid $expected_gid" + edebug "Command groupadd returned true for creating expected group $expected_group with expected gid $expected_gid" + elif ! command -v groupadd; then + die 1 "Expected command 'groupadd' is not present, unable to create expected group $expected_group with gid $expected_gid" + else + die 255 "processing expected group $expected_group with expected id $expected_gid in $myName" + fi +fi + +# Self-check: Resolve expected group +edebug "processing 'Self-check: Resolve expected group' step in $myName" +if grep -q "$expected_group:.*:$expected_gid:" /etc/group; then + edebug "Expected group $expected_group with expected gid $expected_gid passed self-check" +elif ! grep -q "$expected_group:.*:$expected_gid:" /etc/group; then + die 23 "Expected group $expected_group with expected gid $expected_gid failed self-check, see output of command 'grep -q \"$expected_group:.*:$expected_gid:\" /etc/group': $(grep "$expected_group:.*:$expected_gid:" /etc/group)" +else + die 255 "self-checking Resolve expected group step" +fi + +# Resolve expected user +if grep -q "$expected_user:.*:$expected_uid:$expected_gid:.*" /etc/passwd; then + edebug "Expected user $expected_user with expected uid $expected_uid is already present, skipping resolution.." +elif ! grep -q "$expected_user:.*:$expected_uid:$expected_gid:.*" /etc/passwd; then + edebug "Expected user $expected_user with expected uid $expected_uid is not present, resolving.." + # CORE - Make a new user if needed + if command -v useradd >/dev/null; then + edebug "Found command useradd for resolution" + # We need --no-log-init due https://github.com/golang/go/issues/13548, see https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user + # FIXME: Implement logic that applies --no-log-init based on provided bug state + useradd \ + --create-home --home-dir "/home/$expected_user" \ + --no-log-init \ + --uid "$expected_uid" \ + --gid "$expected_group" \ + --password "$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c10)" \ + --comment "Created by $myName for gitpod usage" \ + "$expected_user" \ + || die 1 "Command useradd failed to create expected user $expected_user with uid $expected_uid" + edebug "Expected user $expected_user with expected uid $expected_uid has been created according to command useradd" + elif command -v adduser >/dev/null; then + # FIXME: Blocked by https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user + die 23 "Command useradd is not available and we are refusing to sue adduser due to the https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user" + elif ! command -v useradd >/dev/null && ! command -v adduser >/dev/null; then + die 23 "Neither of expected commands useradd nor adduser are available on this environment, this usage of gitpod is unexpected and most likely malicious injection of altered dockerfile. Instance $GITPOD_WORKSPACE_ID with user $GITPOD_GIT_USER_EMAIL has been reported to upstream" + else + die 255 "Resolving expected user" + fi +else + die 255 "Checking if expected user is present" +fi + +# Self-check +if grep -q "$expected_user:.*:$expected_uid:$expected_gid:.*" /etc/passwd; then + edebug "Expected user $expected_user with expected uid $expected_uid passed self-check" +elif ! grep -q "$expected_user:.*:$expected_uid:$expected_gid:.*" /etc/passwd; then + edebug "Output of 'grep \"$expected_user\" /etc/passwd' is: '$(grep "$expected_user" /etc/passwd)'" + efixme "Logic for self-check of expected user is required" + #die 23 "Expected user $expected_user with expected uid $expected_uid failed self-check" +else + die 255 "Self-checking expected user" +fi \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh new file mode 100644 index 00000000000000..314204894268ff --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (c) 2021 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + + +set -e + +if [ ! -f /etc/os-release ]; then + DISTRO="UNDEFINED" +else + # Read the line starting with 'ID=' from /etc/os-release and print the rest of the line + DISTRO="$(sed -nr 's/^ID=(.+)$/\1/p' /etc/os-release)" +fi + +# Unify DISTRO values +case "$DISTRO" in + "debian" | "ubuntu" | "linuxmint") + DISTRO="debian" + ;; + + # NOTICE(Kreyren): Amazonlinux has non-standard /etc/os-release + "\"amzn\"") + # Kreyren: Made for https://github.com/gitpod-io/gitpod/issues/1490 + DISTRO="amazon" + ;; + + "alpine") + DISTRO="alpine" + ;; + + *) + DISTRO="UNDEFINED" + ;; +esac + +if [ ! -d "$DISTRO" ]; then + echo "Error: unsupported distro: $DISTRO" +fi + +ln -s $DISTRO/gitpod gitpod +sh gitpod/layer.sh \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/Dockerfile b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/Dockerfile new file mode 100644 index 00000000000000..b2fe09d1943532 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/Dockerfile @@ -0,0 +1,34 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# 'FROM ${BASE_IMAGE}' prepended here + +############################################################################### +# REQUIRED +############################################################################### +# !!! We expect users to configure their containers as root !!! +USER root + +# Copy config and layer script +COPY ./gitpod /var/gitpod + +# Run layer +RUN /var/gitpod/layer.sh \ + # Remove the script itself + # TODO Really necessary? + && rm -f /var/gitpod/layer.sh + +# Switch to user gitpod +USER gitpod + +# Configure user shell +# TODO Remove this in the near future when we do not need ~/.bashrc appends/prepends any more +RUN \ + # REALLY do not print motd + touch ~/.hushlogin && \ + # Configure shell + BASH_RC=~/.bashrc; if [ -f "$BASH_RC" ]; then cp "$BASH_RC" ~/.bashrc-org; else touch ~/.bashrc-org; fi && \ + cat /var/gitpod/.bashrc-prepend > "$BASH_RC" && \ + cat ~/.bashrc-org >> "$BASH_RC" && \ + cat /var/gitpod/.bashrc-append >> "$BASH_RC" diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-append b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-append new file mode 100644 index 00000000000000..a437676f8f4b02 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-append @@ -0,0 +1,11 @@ + + +############################################################################### +########## Gitpod - append - begin +############################################################################### + + +############################################################################### +########## Gitpod - append - end +############################################################################### + diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-prepend b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-prepend new file mode 100644 index 00000000000000..60e7b3cabd69b4 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/.bashrc-prepend @@ -0,0 +1,58 @@ + + +############################################################################### +########## Gitpod - prepend +############################################################################### + +# Prompt color and bash_completion +export PS1='\[\e]0;\u \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u\[\033[00m\] \[\033[01;34m\]\w \$ \[\033[00m\]' +#source /etc/bash_completion + +# editor config - should be removed when registry facade is default +if [ -z "$EDITOR" ]; then + export EDITOR="gp open -w" +fi +if [ -z "$VISUAL" ]; then + export VISUAL="$EDITOR" +fi +if [ -z "$GIT_EDITOR" ]; then + export GIT_EDITOR="$EDITOR" +fi + +# Workaround Java pre v10 by explicitly setting "-Xmx" for all Hotspot/openJDK VMs +if [ -n "$GITPOD_MEMORY" ]; then + export JAVA_TOOL_OPTIONS="-Xmx${GITPOD_MEMORY}m"; +fi + +# Completion for gp command +. <(gp completion) +# ide cli config - should be removed when registry facade is default +if [ ! -d "/ide/bin/" ]; then + alias open='gp open' + alias code='gp open' +fi + +export GEM_HOME=/workspace/.rvm +export GEM_PATH=$GEM_HOME:$GEM_PATH +export PATH=/workspace/.rvm/bin:$PATH + +export PIPENV_VENV_IN_PROJECT=true +export PIP_USER=yes +export PYTHONUSERBASE=/workspace/.pip-modules +export PATH=$PYTHONUSERBASE/bin:$PATH +unset PIP_TARGET +unset PYTHONPATH + +# Set CARGO_HOME to reside in workspace if: +# - it's RUNTIME (/workspace present) +if [ -d /workspace ]; then + export CARGO_HOME=/workspace/.cargo + export PATH=$CARGO_HOME/bin:$PATH +fi + +export BROWSER="${BROWSER:=gp-preview}" + +############################################################################### +########## Gitpod - prepend +############################################################################### + diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/layer.sh b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/layer.sh new file mode 100755 index 00000000000000..86821df942953b --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/debian/gitpod/layer.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# >>> Expects to be run as root + +# Quit immediately on non-zero exit code +set -e; + +# Install necessary tools only if they are not yet installed +INSTALLED_PACKAGES=$(dpkg-query -f '${Package} ${Status}\n' -W bash-completion git | wc -l) +if [ "$INSTALLED_PACKAGES" != 2 ]; then + # The first 'clean' is needed to avoid apt-get detecting package meta data changes + # (like changed labels) which result in errors and broken builds/workspaces! + apt-get clean && rm -rf /var/lib/apt/lists/*; + + apt-get update --allow-insecure-repositories; + apt-get install -yq \ + bash-completion \ + git + + # Cleanup to keep the image as small as possible + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*; +fi + +# Disable root login +# +# Note: The root account should already be disabled by default, at least in Ubuntu. +# Source: https://askubuntu.com/a/20453 +# +# In the past, we used to set a password here, when Gitpod managed workspaces via SSH. +# Now, it doesn't really matter if root is locked or not, because we prevent privilege +# escalation in containers with "allowPrivilegeEscalation=false" anyway: +# https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation +passwd -l root || true + +# Create gp-preview symlink required for the browser variable +ln -s /usr/bin/gp /usr/bin/gp-preview + +# Create Gitpod user +if ! id -u gitpod; then + # user doesn't exist, let's add it. + echo "Creating new user 'gitpod'."; + addgroup --gid 33333 gitpod; + # '--no-log-init': see https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user + useradd --no-log-init --create-home --home-dir /home/gitpod --shell /bin/bash --uid 33333 --gid 33333 gitpod; + echo "gitpod:gitpod" | chpasswd; + + # To allow users to not know anything about our gitpod user, copy over all stuff from the previous user (root) + cp -R /root/. /home/gitpod; + chown -R gitpod:gitpod /home/gitpod/; +else + USER_ID=$(id -u gitpod) + if [ "$USER_ID" -eq 33333 ]; then + # users exists and has user id 33333. We hope that the user does not have ID 0, because that grants root privileges + echo "Found user 'gitpod'. Reusing it."; + echo "gitpod:gitpod" | chpasswd; + else + # error + echo "Error: User 'gitpod' exists but does not have user-id 33333. The user-id is $UID"; + exit 1; + fi +fi diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/prepend.dockerfile b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/prepend.dockerfile new file mode 100644 index 00000000000000..146aaffa18c97f --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/prepend.dockerfile @@ -0,0 +1,7 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + + +USER ROOT +COPY ./gitpod-cli /usr/bin/gp \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/scripts/detect-distro.sh b/components/image-builder-mk3/workspace-image-layer/scripts/detect-distro.sh new file mode 100755 index 00000000000000..5a7c0f9836bac6 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/scripts/detect-distro.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# This script is run inside the base image provided by the user. +# It should detect the name of the distro by looking at /etc/os-release. +# The goal here is to determine the set of tools that are available to us to install the necessary dependencies for gitpod into the image +# E.g., which package manager to use etc. +# Dependencies: +# - /bin/sh +# - sed +# - /etc/os-release to contain the distro 'ID=' +# Postconditions: +# - stores result in file '/workspace/distro' +# - valid values: debian | alpine | "amzn" | UNDEFINED + +if [ ! -f /etc/os-release ]; then + DISTRO="UNDEFINED" +else + # Read the line starting with 'ID=' from /etc/os-release and print the rest of the line + DISTRO="$(sed -nr 's/^ID=(.+)$/\1/p' /etc/os-release)" +fi + +# Unify DISTRO values +case "$DISTRO" in + "debian" | "ubuntu" | "linuxmint") + DISTRO="debian" + ;; + + # NOTICE(Kreyren): Amazonlinux has non-standard /etc/os-release + "\"amzn\"") + # Kreyren: Made for https://github.com/gitpod-io/gitpod/issues/1490 + DISTRO="amazon" + ;; + + "alpine") + DISTRO="alpine" + ;; + + *) + DISTRO="UNDEFINED" + ;; +esac + +OUT_FILE="/workspace/distro" +printf '%s\n' "$DISTRO" > "$OUT_FILE" +printf '%s\n' "Found distro: $DISTRO. Wrote file $OUT_FILE." \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/scripts/generate-dockerfile.sh b/components/image-builder-mk3/workspace-image-layer/scripts/generate-dockerfile.sh new file mode 100755 index 00000000000000..24e60ffbfcf5a8 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/scripts/generate-dockerfile.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +# Parameters: +# $1: BASE_IMAGE +BASE_DIR="$( cd "$( dirname "$0" )/.." >/dev/null 2>&1 && pwd )" +BASE_IMAGE=$1 + +# 1. Read distro value +DISTRO_IN_FILE="/workspace/distro" +if [ ! -f "$DISTRO_IN_FILE" ]; then + echo "Unable to find file $DISTRO_IN_FILE. Exit with code 1."; + exit 1; +fi +DISTRO=$(cat $DISTRO_IN_FILE) +if [ -z "$DISTRO" ] || [ "$DISTRO" = "UNDEFINED" ]; then + echo "Distro value '$DISTRO'! Exit with code 1."; + exit 1; +fi +# The file has served it's purpose, now move it out of the way +rm -f $DISTRO_IN_FILE + +# 2. Copy distro-specific files into workspace (default path in Google Cloud Container builder: /workspace) +DISTRO_PATH="$BASE_DIR/gitpod-layer/$DISTRO" +cp -R "$DISTRO_PATH"/. ./ + +# 3. Copy the gitpod-cli into the workspaace +cp "$BASE_DIR"/gitpod-cli gitpod-cli + +# 4. Create Dockerfile in /workspace starting from BASE_IMAGE and append the distro-specific part +echo "FROM $BASE_IMAGE" > Dockerfile +(cat "$BASE_DIR/gitpod-layer/prepend.dockerfile"; echo) >> Dockerfile +cat "$DISTRO_PATH/Dockerfile" >> Dockerfile + +echo "Generated Dockerfile with BASE_IMAGE: $BASE_IMAGE" diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/alpine-withuser.dockerfile b/components/image-builder-mk3/workspace-image-layer/tests/positive/alpine-withuser.dockerfile new file mode 100644 index 00000000000000..2614287f74042c --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/alpine-withuser.dockerfile @@ -0,0 +1,6 @@ +FROM alpine:3.13 + +RUN apk add --no-cache --update bash + +RUN addgroup -g 33333 gitpod +RUN adduser -D -h /home/gitpod -s /bin/sh -u 33333 -G gitpod gitpod \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/alpine.dockerfile b/components/image-builder-mk3/workspace-image-layer/tests/positive/alpine.dockerfile new file mode 100644 index 00000000000000..a70195ff8af1f5 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/alpine.dockerfile @@ -0,0 +1,3 @@ +FROM alpine:3.13 + +RUN apk add --no-cache --update bash \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-bionic.dockerfile b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-bionic.dockerfile new file mode 100644 index 00000000000000..a47d2861734b1f --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-bionic.dockerfile @@ -0,0 +1 @@ +FROM buildpack-deps:bionic \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser-sudo.dockerfile b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser-sudo.dockerfile new file mode 100644 index 00000000000000..2aefcc2c0eed80 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser-sudo.dockerfile @@ -0,0 +1,6 @@ +FROM buildpack-deps:xenial + +RUN addgroup --gid 33333 gitpod +# '--no-log-init': see https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user +RUN useradd --no-log-init --create-home --home-dir /home/gitpod --shell /bin/bash --uid 33333 --gid 33333 gitpod +RUN usermod -a -G sudo gitpod diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser.dockerfile b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser.dockerfile new file mode 100644 index 00000000000000..3c2fddd3819531 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial-withuser.dockerfile @@ -0,0 +1,5 @@ +FROM buildpack-deps:xenial + +RUN addgroup --gid 33333 gitpod +# '--no-log-init': see https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user +RUN useradd --no-log-init --create-home --home-dir /home/gitpod --shell /bin/bash --uid 33333 --gid 33333 gitpod diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial.dockerfile b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial.dockerfile new file mode 100644 index 00000000000000..2af3eb86cce42a --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/ubuntu-xenial.dockerfile @@ -0,0 +1 @@ +FROM buildpack-deps:xenial \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/tests/positive/verify.sh b/components/image-builder-mk3/workspace-image-layer/tests/positive/verify.sh new file mode 100755 index 00000000000000..16bed08c4a0b45 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/positive/verify.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +USER_ID=$(id -u gitpod) +if [ "$USER_ID" -ne 33333 ]; then + echo "user 'gitpod' not present or wrong user-id." + exit 1 +fi + +if [ -z "$(command -v git)" ]; then + echo "git not installed!" +fi + +if [ -z "$(command -v bash)" ]; then + echo "bash not installed!" +fi + +echo "Tests passed successfully!" +exit 0 \ No newline at end of file diff --git a/components/image-builder-mk3/workspace-image-layer/tests/runtests.sh b/components/image-builder-mk3/workspace-image-layer/tests/runtests.sh new file mode 100755 index 00000000000000..34436f287050f7 --- /dev/null +++ b/components/image-builder-mk3/workspace-image-layer/tests/runtests.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Quit immediately on non-zero exit code +set -e; + +BASE=$(pwd) + +cd positive + +for DOCKERFILE in ls *.dockerfile; do + echo "********* BEGIN TEST $DOCKERFILE ************" + BASE_IMG="$DOCKERFILE:test" + WORKSPACE_IMG="$DOCKERFILE:layered" + WORKSPACE="$(sudo rm -rf .tmp; mkdir .tmp; cd .tmp; pwd)" + + cp "$BASE/"../scripts/* "$WORKSPACE" + cp "$BASE/positive/verify.sh" "$WORKSPACE" + docker build -f "$DOCKERFILE" -t "$BASE_IMG" . + docker run -v "$WORKSPACE":/workspace "$BASE_IMG" /workspace/detect-distro.sh + # Fake-satisfy generate-dockerfile.sh dependency + touch "$BASE/../gitpod-cli" + docker run -v "$WORKSPACE":/workspace -v "$BASE/..":/base "$BASE_IMG" sh -c "cd /workspace && /base/scripts/generate-dockerfile.sh $BASE_IMG" + + docker build -f "$WORKSPACE/Dockerfile" -t "$WORKSPACE_IMG" "$WORKSPACE" + + echo "docker run -v $WORKSPACE:/workspace $WORKSPACE_IMG /workspace/verify.sh" + if ! docker run -v "$WORKSPACE:/workspace" --entrypoint="" "$WORKSPACE_IMG" /workspace/verify.sh; then + echo "verify.sh failed." + exit 1 + fi + sudo rm -rf "$WORKSPACE" + rm -f "$BASE/../gitpod-cli" + echo "********* END TEST $DOCKERFILE ************" +done diff --git a/components/image-builder/README.md b/components/image-builder/README.md new file mode 100644 index 00000000000000..7e405299284010 --- /dev/null +++ b/components/image-builder/README.md @@ -0,0 +1,3 @@ +# This component is deprecated. + +Please use image-builder-mk3 instead. \ No newline at end of file diff --git a/components/ws-manager/pkg/manager/annotations.go b/components/ws-manager/pkg/manager/annotations.go index 89fb15a7e5d104..305aed246b649e 100644 --- a/components/ws-manager/pkg/manager/annotations.go +++ b/components/ws-manager/pkg/manager/annotations.go @@ -84,7 +84,7 @@ const ( nodeNameAnnotation = "gitpod.io/nodeName" // workspaceAnnotationPrefix prefixes pod annotations that contain annotations specified during the workspaces start request - workspaceAnnotationPrefix = "gitpod/annotation." + workspaceAnnotationPrefix = "gitpod.io/annotation." ) // markWorkspaceAsReady adds annotations to a workspace pod diff --git a/components/ws-manager/pkg/manager/config.go b/components/ws-manager/pkg/manager/config.go index e975e6c8b42869..fdf526b13b27f3 100644 --- a/components/ws-manager/pkg/manager/config.go +++ b/components/ws-manager/pkg/manager/config.go @@ -132,6 +132,8 @@ type WorkspacePodTemplateConfiguration struct { ProbePath string `json:"probePath,omitempty"` // GhostPath is a path to an additional workspace pod template YAML file for ghost workspaces GhostPath string `json:"ghostPath,omitempty"` + // ImagebuildPath is a path to an additional workspace pod template YAML file for imagebuild workspaces + ImagebuildPath string `json:"imagebuildPath,omitempty"` } // WorkspaceDaemonConfiguration configures our connection to the workspace sync daemons runnin on the nodes diff --git a/components/ws-manager/pkg/manager/status.go b/components/ws-manager/pkg/manager/status.go index b092654066bce0..b5a911a2aaefea 100644 --- a/components/ws-manager/pkg/manager/status.go +++ b/components/ws-manager/pkg/manager/status.go @@ -343,10 +343,18 @@ func getContainer(pod *corev1.Pod, name string) *corev1.Container { // getWorkspaceMetadata extracts a workspace's metadata from pod labels func getWorkspaceMetadata(pod *corev1.Pod) *api.WorkspaceMetadata { started := timestamppb.New(pod.CreationTimestamp.Time) + annotations := make(map[string]string) + for k, v := range pod.Annotations { + if !strings.HasPrefix(k, workspaceAnnotationPrefix) { + continue + } + annotations[strings.TrimPrefix(k, workspaceAnnotationPrefix)] = v + } return &api.WorkspaceMetadata{ - Owner: pod.ObjectMeta.Labels[wsk8s.OwnerLabel], - MetaId: pod.ObjectMeta.Labels[wsk8s.MetaIDLabel], - StartedAt: started, + Owner: pod.ObjectMeta.Labels[wsk8s.OwnerLabel], + MetaId: pod.ObjectMeta.Labels[wsk8s.MetaIDLabel], + StartedAt: started, + Annotations: annotations, } } diff --git a/components/ws-manager/pkg/manager/testdata/status_metadata.golden b/components/ws-manager/pkg/manager/testdata/status_metadata.golden new file mode 100644 index 00000000000000..05b4b0abc02efc --- /dev/null +++ b/components/ws-manager/pkg/manager/testdata/status_metadata.golden @@ -0,0 +1,35 @@ +{ + "status": { + "id": "foobas", + "metadata": { + "owner": "foobar", + "meta_id": "metameta", + "started_at": { + "seconds": 1552236488 + }, + "annotations": { + "foo": "barbar" + } + }, + "spec": { + "workspace_image": "nginx:latest", + "url": "http://10.0.0.114:8082", + "exposed_ports": [ + { + "port": 8080 + } + ] + }, + "phase": 4, + "conditions": { + "service_exists": 1, + "deployed": 1 + }, + "runtime": { + "node_name": "minikube", + "pod_name": "ws-foobas", + "node_ip": "10.0.2.15" + }, + "auth": {} + } +} \ No newline at end of file diff --git a/components/ws-manager/pkg/manager/testdata/status_metadata.json b/components/ws-manager/pkg/manager/testdata/status_metadata.json new file mode 100644 index 00000000000000..88f4a8b6b3dbbd --- /dev/null +++ b/components/ws-manager/pkg/manager/testdata/status_metadata.json @@ -0,0 +1,358 @@ +{ + "pod": { + "metadata": { + "name": "ws-foobas", + "namespace": "default", + "selfLink": "/api/v1/namespaces/default/pods/ws-foobas", + "uid": "486e5f88-4354-11e9-aee4-080027861af1", + "resourceVersion": "64953", + "creationTimestamp": "2019-03-10T16:48:08Z", + "labels": { + "gpwsman": "true", + "headless": "false", + "owner": "foobar", + "metaID": "metameta", + "workspaceID": "foobas", + "workspaceType": "regular" + }, + "annotations": { + "gitpod.io/annotation.foo": "barbar", + "gitpod/id": "foobas", + "gitpod/servicePrefix": "foobas", + "gitpod/url": "http://10.0.0.114:8082", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "23000", + "prometheus.io/scrape": "true" + } + }, + "spec": { + "volumes": [ + { + "name": "vol-this-workspace", + "hostPath": { + "path": "/tmp/workspaces/foobas", + "type": "DirectoryOrCreate" + } + }, + { + "name": "vol-this-theia", + "hostPath": { + "path": "/tmp/theia/theia-xyz", + "type": "Directory" + } + }, + { + "name": "vol-sync-tmp", + "hostPath": { + "path": "/tmp/workspaces/sync-tmp", + "type": "DirectoryOrCreate" + } + }, + { + "name": "default-token-6qnvx", + "secret": { + "secretName": "default-token-6qnvx", + "defaultMode": 420 + } + } + ], + "containers": [ + { + "name": "workspace", + "image": "nginx:latest", + "ports": [ + { + "containerPort": 23000, + "protocol": "TCP" + } + ], + "env": [ + { + "name": "THEIA_WORKSPACE_ROOT", + "value": "/workspace" + }, + { + "name": "GITPOD_THEIA_PORT", + "value": "23000" + }, + { + "name": "GITPOD_HOST", + "value": "gitpod.io" + }, + { + "name": "GITPOD_INTERVAL", + "value": "30" + }, + { + "name": "GITPOD_WSSYNC_APITOKEN", + "value": "c17a7eaf-e5de-4e9d-815a-7919379e2bf8" + }, + { + "name": "GITPOD_WSSYNC_APIPORT", + "value": "44444" + }, + { + "name": "GITPOD_REPO_ROOT", + "value": "/workspace" + }, + { + "name": "GITPOD_CLI_APITOKEN", + "value": "690516e2-c416-4a28-ba74-e36f125922aa" + }, + { + "name": "GITPOD_WORKSPACE_ID", + "value": "foobas" + }, + { + "name": "GITPOD_GIT_USER_NAME", + "value": "32leaves" + }, + { + "name": "GITPOD_GIT_USER_EMAIL", + "value": "christian.weichel@typefox.io" + } + ], + "resources": { + "limits": { + "cpu": "100m", + "memory": "100Mi" + }, + "requests": { + "cpu": "100m", + "memory": "100Mi" + } + }, + "volumeMounts": [ + { + "name": "vol-this-workspace", + "mountPath": "/workspace" + }, + { + "name": "vol-this-theia", + "mountPath": "/theia" + }, + { + "name": "default-token-6qnvx", + "readOnly": true, + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" + } + ], + "livenessProbe": { + "httpGet": { + "path": "/", + "port": 23000, + "scheme": "HTTP" + }, + "timeoutSeconds": 1, + "periodSeconds": 30, + "successThreshold": 1, + "failureThreshold": 3 + }, + "readinessProbe": { + "httpGet": { + "path": "/", + "port": 23000, + "scheme": "HTTP" + }, + "timeoutSeconds": 1, + "periodSeconds": 1, + "successThreshold": 1, + "failureThreshold": 3 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "IfNotPresent" + }, + { + "name": "sync", + "image": "csweichel/noop:latest", + "env": [ + { + "name": "WSSYNCD", + "value": "{\"workspace\":{\"location\":\"/workspace\",\"name\":\"foobas\",\"cleanup\":true},\"remoteStorage\":{\"kind\":\"\"},\"gcloud\":{\"credentialsFile\":\"\",\"region\":\"\",\"project\":\"\",\"tmpdir\":\"\",\"maximumBackupSize\":0,\"maximumBackupCount\":0},\"initializer\":{\"kind\":\"\",\"git\":{\"remoteURI\":\"\",\"targetMode\":\"\"}},\"notification\":{\"url\":\"http://localhost:23000/gitpod/syncd\"},\"syncDisabled\":true,\"apiserver\":{\"enabled\":true,\"host\":\"127.0.0.1\",\"port\":44444,\"apitoken\":\"c17a7eaf-e5de-4e9d-815a-7919379e2bf8\"}}" + } + ], + "resources": { + "limits": { + "cpu": "100m", + "memory": "100Mi" + }, + "requests": { + "cpu": "100m", + "memory": "100Mi" + } + }, + "volumeMounts": [ + { + "name": "vol-sync-tmp", + "mountPath": "/tmp/sync" + }, + { + "name": "vol-this-workspace", + "mountPath": "/workspace" + }, + { + "name": "default-token-6qnvx", + "readOnly": true, + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" + } + ], + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "imagePullPolicy": "IfNotPresent" + } + ], + "restartPolicy": "Always", + "terminationGracePeriodSeconds": 30, + "dnsPolicy": "ClusterFirst", + "serviceAccountName": "default", + "serviceAccount": "default", + "nodeName": "minikube", + "securityContext": {}, + "schedulerName": "default-scheduler", + "tolerations": [ + { + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + }, + { + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "effect": "NoExecute", + "tolerationSeconds": 300 + } + ] + }, + "status": { + "phase": "Running", + "conditions": [ + { + "type": "Initialized", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2019-03-10T16:48:08Z" + }, + { + "type": "Ready", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2019-03-10T16:48:13Z" + }, + { + "type": "PodScheduled", + "status": "True", + "lastProbeTime": null, + "lastTransitionTime": "2019-03-10T16:48:08Z" + } + ], + "hostIP": "10.0.2.15", + "podIP": "172.17.0.5", + "startTime": "2019-03-10T16:48:08Z", + "containerStatuses": [ + { + "name": "sync", + "state": { + "running": { + "startedAt": "2019-03-10T16:48:13Z" + } + }, + "lastState": {}, + "ready": true, + "restartCount": 0, + "image": "csweichel/noop:latest", + "imageID": "docker-pullable://csweichel/noop@sha256:aaa6b993f4c853fac7101aa7fc087926f829004e62cbce6e1852e5a3aac87c52", + "containerID": "docker://9961f75ea72f36bb0ba1e42b3b2da98eb44a9dc12e7c7e8edfb52512b3b04016" + }, + { + "name": "workspace", + "state": { + "running": { + "startedAt": "2019-03-10T16:48:12Z" + } + }, + "lastState": {}, + "ready": true, + "restartCount": 0, + "image": "nginx:latest", + "imageID": "docker-pullable://nginx@sha256:98efe605f61725fd817ea69521b0eeb32bef007af0e3d0aeb6258c6e6fe7fc1a", + "containerID": "docker://e7080b843a47db414d6c94cfda7f657b99d8aa5bbf7c9c118ec98c0eefb6c0df" + } + ], + "qosClass": "Guaranteed" + } + }, + "theiaService": { + "metadata": { + "name": "foobas-theia", + "namespace": "default", + "selfLink": "/api/v1/namespaces/default/services/foobas-theia", + "uid": "48687212-4354-11e9-aee4-080027861af1", + "resourceVersion": "64923", + "creationTimestamp": "2019-03-10T16:48:08Z", + "labels": { + "gpwsman": "true", + "headless": "false", + "owner": "foobar", + "metaID": "metameta", + "workspaceID": "foobas" + } + }, + "spec": { + "ports": [ + { + "name": "theia", + "protocol": "TCP", + "port": 23000, + "targetPort": 23000 + } + ], + "selector": { + "gpwsman": "true", + "headless": "false", + "owner": "foobar", + "workspaceID": "foobas" + }, + "clusterIP": "10.103.194.121", + "type": "ClusterIP", + "sessionAffinity": "None" + }, + "status": { + "loadBalancer": {} + } + }, + "portsService": { + "metadata": { + "name": "foobas-ports", + "namespace": "default", + "selfLink": "/api/v1/namespaces/default/services/foobas-ports", + "uid": "486cb304-4354-11e9-aee4-080027861af1", + "resourceVersion": "64926", + "creationTimestamp": "2019-03-10T16:48:08Z", + "labels": { + "gpwsman": "true", + "workspaceID": "foobas" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 8080, + "targetPort": 8080 + } + ], + "selector": { + "gpwsman": "true", + "workspaceID": "foobas" + }, + "clusterIP": "10.110.184.222", + "type": "ClusterIP", + "sessionAffinity": "None" + }, + "status": { + "loadBalancer": {} + } + } +} \ No newline at end of file diff --git a/gitpod-ws.code-workspace b/gitpod-ws.code-workspace index 7c350c5c6a013b..af2b2d51292b76 100644 --- a/gitpod-ws.code-workspace +++ b/gitpod-ws.code-workspace @@ -10,6 +10,8 @@ { "path": "components/gitpod-cli" }, { "path": "components/gitpod-protocol" }, { "path": "components/image-builder" }, + { "path": "components/image-builder-bob" }, + { "path": "components/image-builder-mk3" }, { "path": "components/licensor" }, { "path": "components/local-app" }, { "path": "components/registry-facade" }, From 5de3d7feed1b5378ce616dae0dc2fbd2d011c069 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Fri, 18 Jun 2021 13:05:23 +0000 Subject: [PATCH 03/15] [chart] Add image builder mk3 --- chart/templates/image-builder-configmap.yaml | 10 -- .../image-builder-mk3-authkey-secret.yaml | 15 +++ .../image-builder-mk3-configmap.yaml | 67 +++++++++++ .../image-builder-mk3-deployment.yaml | 107 ++++++++++++++++++ .../image-builder-mk3-networkpolicy.yaml | 37 ++++++ .../image-builder-mk3-psp-clusterrole.yaml | 20 ++++ .../image-builder-mk3-rolebinding.yaml | 39 +++++++ .../templates/image-builder-mk3-service.yaml | 4 + .../image-builder-mk3-serviceaccount.yaml | 12 ++ chart/templates/workspace-template.yaml | 4 + chart/values.yaml | 12 ++ components/image-builder-bob/BUILD.yaml | 6 +- 12 files changed, 320 insertions(+), 13 deletions(-) create mode 100644 chart/templates/image-builder-mk3-authkey-secret.yaml create mode 100644 chart/templates/image-builder-mk3-configmap.yaml create mode 100644 chart/templates/image-builder-mk3-deployment.yaml create mode 100644 chart/templates/image-builder-mk3-networkpolicy.yaml create mode 100644 chart/templates/image-builder-mk3-psp-clusterrole.yaml create mode 100644 chart/templates/image-builder-mk3-rolebinding.yaml create mode 100644 chart/templates/image-builder-mk3-service.yaml create mode 100644 chart/templates/image-builder-mk3-serviceaccount.yaml diff --git a/chart/templates/image-builder-configmap.yaml b/chart/templates/image-builder-configmap.yaml index 981510a2b953bc..ade8a3acb0b2d8 100644 --- a/chart/templates/image-builder-configmap.yaml +++ b/chart/templates/image-builder-configmap.yaml @@ -4,16 +4,6 @@ {{ $comp := .Values.components.imageBuilder -}} {{- $this := dict "root" . "gp" $.Values "comp" $comp -}} -{{- define "registry-name" -}} -{{- $comp := .comp -}} -{{- $ := .root -}} -{{- if eq $comp.registry.name "builtin" -}} -{{ template "gitpod.builtinRegistry.name" $ }} -{{- else -}} -{{ $comp.registry.name }} -{{- end -}} -{{- end -}} - {{- if not $comp.disabled -}} apiVersion: v1 kind: ConfigMap diff --git a/chart/templates/image-builder-mk3-authkey-secret.yaml b/chart/templates/image-builder-mk3-authkey-secret.yaml new file mode 100644 index 00000000000000..62a4b79f713a90 --- /dev/null +++ b/chart/templates/image-builder-mk3-authkey-secret.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +apiVersion: v1 +kind: Secret +metadata: + name: image-builder-mk3-authkey + labels: + app: {{ template "gitpod.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +type: Opaque +data: + keyfile: {{ randAlphaNum 32 | b64enc }} \ No newline at end of file diff --git a/chart/templates/image-builder-mk3-configmap.yaml b/chart/templates/image-builder-mk3-configmap.yaml new file mode 100644 index 00000000000000..8f0200e09d3b6d --- /dev/null +++ b/chart/templates/image-builder-mk3-configmap.yaml @@ -0,0 +1,67 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +{{ $comp := .Values.components.imageBuilderMk3 -}} +{{ $compImgbldr := .Values.components.imageBuilder -}} +{{- $this := dict "root" . "gp" $.Values "comp" $comp "compImgbldr" $compImgbldr -}} + +{{- define "registry-name" -}} +{{- $comp := .comp -}} +{{- $compImgbldr := .compImgbldr -}} +{{- $ := .root -}} +{{- if eq (default $comp.registry $compImgbldr.registry).name "builtin" -}} +{{ template "gitpod.builtinRegistry.name" $ }} +{{- else -}} +{{ (default $comp.registry $compImgbldr.registry).name }} +{{- end -}} +{{- end -}} + +{{- if not $comp.disabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: image-builder-mk3-config + labels: + app: {{ template "gitpod.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +data: + image-builder.json: |- + { + "orchestrator": { + {{- if (default $comp.registry $compImgbldr.registry).secretName -}}"authFile": "/config/pull-secret.json",{{- end -}} + "gitpodLayerLoc": "/app/workspace-image-layer.tar.gz", + "baseImageRepository": "{{ or (default $comp.registry $compImgbldr.registry).baseImageName (print (include "registry-name" $this) "/base-images") }}", + "workspaceImageRepository": "{{ or (default $comp.registry $compImgbldr.registry).workspaceImageName (print (include "registry-name" $this) "/workspace-images") }}", + "imageBuildSalt": "{{ $comp.imageBuildSalt | default "" }}", + {{- if $comp.wsman -}} + {{ $comp.wsman | fromYaml | toJson }} + {{- else -}} + "wsman": { + "address": "ws-manager:8080", + "tls": { + "ca": "/wsman-certs/ca.crt", + "crt": "/wsman-certs/tls.crt", + "key": "/wsman-certs/tls.key" + } + }, + {{- end -}} + "builderImage": "{{ template "gitpod.comp.imageFull" (dict "root" . "gp" $.Values "comp" $comp.builderImage) }}", + "builderAuthKeyFile": "/config/authkey" + }, + "refCache": { + "interval": "6h", + "refs": ["{{ template "gitpod.comp.imageFull" (dict "root" . "gp" $.Values "comp" .Values.components.workspace.defaultImage) }}"] + }, + "pprof": { + "address": ":6060" + }, + "prometheus": { + "address": "127.0.0.1:9500" + }, + "service": { + "address": ":8080" + } + } +{{- end -}} \ No newline at end of file diff --git a/chart/templates/image-builder-mk3-deployment.yaml b/chart/templates/image-builder-mk3-deployment.yaml new file mode 100644 index 00000000000000..0f048149c2cb1b --- /dev/null +++ b/chart/templates/image-builder-mk3-deployment.yaml @@ -0,0 +1,107 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +{{ $comp := .Values.components.imageBuilderMk3 -}} +{{ $compImgbldr := .Values.components.imageBuilder -}} +{{- $this := dict "root" . "gp" $.Values "comp" $comp "compImgbldr" $compImgbldr -}} +{{- if not $comp.disabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: image-builder-mk3 + labels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: deployment + stage: {{ .Values.installation.stage }} +spec: + selector: + matchLabels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: pod + stage: {{ .Values.installation.stage }} + replicas: {{ $comp.replicas | default 1 }} + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + name: image-builder-mk3 + labels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: pod + stage: {{ .Values.installation.stage }} + annotations: +{{- if index .Values "docker-registry" "enabled" }} + checksum/builtin-registry-auth: {{ include (print $.Template.BasePath "/builtin-registry-auth-secret.yaml") . | sha256sum }} +{{- end -}} +{{ include "gitpod.pod.dependsOn" $this | indent 8 }} + spec: +{{ include "gitpod.workspaceAffinity" $this | indent 6 }} + serviceAccountName: image-builder-mk3 + volumes: + - name: configuration + configMap: + name: {{ template "gitpod.comp.configMap" $this }} + - name: authkey + secret: + secretName: image-builder-mk3-authkey + {{- if (default $compImgbldr.registry).secretName }} + - name: pull-secret + secret: + secretName: {{ (default $compImgbldr.registry).secretName }} + {{- end }} +{{- range $idx, $sec := (default $comp.registryCerts $compImgbldr.registryCerts) }} + - name: docker-tls-certs-{{ $idx }} + secret: + secretName: {{ $sec.secret }} +{{- end }} + - name: wsman-tls-certs + secret: + secretName: {{ .Values.components.wsManager.tls.server.secretName }} + enableServiceLinks: false + containers: +{{ include "gitpod.kube-rbac-proxy" $this | indent 6 }} + - name: image-builder-mk3 +{{ include "gitpod.container.defaultEnv" $this | indent 8 }} +{{ include "gitpod.container.tracingEnv" $this | indent 8 }} + image: {{ template "gitpod.comp.imageFull" $this }} + args: + - "run" + - "-v" + - "--config" + - "/config/image-builder.json" +{{ include "gitpod.container.imagePullPolicy" $this | indent 8 }} + volumeMounts: + - mountPath: /config/image-builder.json + subPath: "image-builder.json" + name: configuration + - mountPath: /config/authkey + subPath: "keyfile" + name: authkey + - mountPath: /wsman-certs + name: wsman-tls-certs + readOnly: true +{{- if (default $comp $compImgbldr).registry }} +{{- if (default $comp $compImgbldr).registry.secretName }} + - mountPath: /config/pull-secret.json + subPath: .dockerconfigjson + name: pull-secret +{{- end }} +{{- end }} + resources: + requests: + cpu: {{ $.Values.resources.default.cpu }} + memory: {{ $.Values.resources.default.memory }} +{{ include "gitpod.container.ports" $this | indent 8 }} + securityContext: + runAsUser: 33333 + privileged: false +{{ include "gitpod.container.defaultEnv" $this | indent 8 }} +{{ include "gitpod.container.tracingEnv" $this | indent 8 }} +{{ toYaml .Values.defaults | indent 6 }} +{{ end }} diff --git a/chart/templates/image-builder-mk3-networkpolicy.yaml b/chart/templates/image-builder-mk3-networkpolicy.yaml new file mode 100644 index 00000000000000..934052fa9d5797 --- /dev/null +++ b/chart/templates/image-builder-mk3-networkpolicy.yaml @@ -0,0 +1,37 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +{{ if .Values.installNetworkPolicies -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: image-builder-mk3 + labels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: networkpolicy + stage: {{ .Values.installation.stage }} +spec: + podSelector: + matchLabels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + policyTypes: + - Ingress + - Egress + ingress: + # server + - from: + - podSelector: + matchLabels: + app: {{ template "gitpod.fullname" $ }} + component: {{ .Values.components.server.name }} + egress: + - to: + # Allow egress to everywhere, except... + - ipBlock: + cidr: 0.0.0.0/0 + except: + # Google Compute engine special, reserved VM metadata IP + - 169.254.169.254/32 +{{- end -}} diff --git a/chart/templates/image-builder-mk3-psp-clusterrole.yaml b/chart/templates/image-builder-mk3-psp-clusterrole.yaml new file mode 100644 index 00000000000000..3f713464210842 --- /dev/null +++ b/chart/templates/image-builder-mk3-psp-clusterrole.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +{{ if .Values.installPodSecurityPolicies -}} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Namespace }}-ns-image-builder-mk3 + labels: + app: {{ template "gitpod.fullname" . }} + component: cluster + kind: clusterrole + stage: {{ .Values.installation.stage }} +rules: + - apiGroups: ["policy"] + resources: ["podsecuritypolicies"] + verbs: ["use"] + resourceNames: + - {{ .Release.Namespace }}-ns-privileged-unconfined +{{- end -}} \ No newline at end of file diff --git a/chart/templates/image-builder-mk3-rolebinding.yaml b/chart/templates/image-builder-mk3-rolebinding.yaml new file mode 100644 index 00000000000000..365b7e7b873501 --- /dev/null +++ b/chart/templates/image-builder-mk3-rolebinding.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: image-builder-mk3-rb + labels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: role-binding + stage: {{ .Values.installation.stage }} +subjects: +- kind: ServiceAccount + name: image-builder-mk3 +roleRef: + kind: ClusterRole + name: {{ .Release.Namespace }}-ns-image-builder-mk3 + apiGroup: rbac.authorization.k8s.io + +--- + +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Namespace }}-image-builder-mk3-kube-rbac-proxy + labels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: role-binding + stage: {{ .Values.installation.stage }} +subjects: +- kind: ServiceAccount + name: image-builder-mk3 + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ .Release.Namespace }}-kube-rbac-proxy + apiGroup: rbac.authorization.k8s.io diff --git a/chart/templates/image-builder-mk3-service.yaml b/chart/templates/image-builder-mk3-service.yaml new file mode 100644 index 00000000000000..59bf0a905cec6b --- /dev/null +++ b/chart/templates/image-builder-mk3-service.yaml @@ -0,0 +1,4 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +{{ template "gitpod.service.default" dict "root" . "gp" .Values "comp" .Values.components.imageBuilderMk3 }} \ No newline at end of file diff --git a/chart/templates/image-builder-mk3-serviceaccount.yaml b/chart/templates/image-builder-mk3-serviceaccount.yaml new file mode 100644 index 00000000000000..43e0aa3260933b --- /dev/null +++ b/chart/templates/image-builder-mk3-serviceaccount.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2020 Gitpod GmbH. All rights reserved. +# Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: image-builder-mk3 + labels: + app: {{ template "gitpod.fullname" . }} + component: image-builder-mk3 + kind: service-account + stage: {{ .Values.installation.stage }} diff --git a/chart/templates/workspace-template.yaml b/chart/templates/workspace-template.yaml index 80beebb3425081..0962ddf12b1324 100644 --- a/chart/templates/workspace-template.yaml +++ b/chart/templates/workspace-template.yaml @@ -53,6 +53,10 @@ data: "ghost.yaml": | {{ dict | merge ($comp.templates.ghost | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "ghost") | fromYaml) | toJson | indent 4 }} {{- end }} +{{ if (or $comp.templates.imagebuild $comp.affinity) }} + "imagebuild.yaml": | +{{ dict | merge ($comp.templates.imagebuild | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "imagebuild") | fromYaml) | toJson | indent 4 }} +{{- end }} {{ if (or $comp.templates.regular $comp.affinity) }} "regular.yaml": | {{ dict | merge ($comp.templates.regular | default dict) (include "coreWorkspaceAffinity" (dict "comp" $comp "tpe" "regular") | fromYaml) | toJson | indent 4 }} diff --git a/chart/values.yaml b/chart/values.yaml index d97841bae1911f..780cd4ecc641d3 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -234,6 +234,18 @@ components: expose: true containerPort: 8080 + imageBuilderMk3: + name: "image-builder-mk3" + dependsOn: + - "image-builder-mk3-configmap.yaml" + alpineImage: alpine:3.13 + builderImage: + imageName: "image-builder-mk3/bob" + ports: + rpc: + expose: true + containerPort: 8080 + kedge: name: "kedge" disabled: true diff --git a/components/image-builder-bob/BUILD.yaml b/components/image-builder-bob/BUILD.yaml index 6d7e64c50d949a..c55982451cf931 100644 --- a/components/image-builder-bob/BUILD.yaml +++ b/components/image-builder-bob/BUILD.yaml @@ -26,7 +26,7 @@ packages: - imageRepoBase dockerfile: leeway.Dockerfile metadata: - helm-component: imageBuilderMk3.bob + helm-component: imageBuilderMk3.builderImage image: - - ${imageRepoBase}/image-builder/bob:${version} - - ${imageRepoBase}/image-builder/bob:${__git_commit} + - ${imageRepoBase}/image-builder-mk3/bob:${version} + - ${imageRepoBase}/image-builder-mk3/bob:${__git_commit} From 5b97e574ca7d1d6b3d60447f6201b3e9341aad76 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Sun, 20 Jun 2021 11:14:16 +0000 Subject: [PATCH 04/15] [ws-manager] Handle AlreadyExists in StartWorkspace --- components/ws-manager/pkg/manager/manager.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/ws-manager/pkg/manager/manager.go b/components/ws-manager/pkg/manager/manager.go index 26a042c7ec6a6d..e01165768d2bac 100644 --- a/components/ws-manager/pkg/manager/manager.go +++ b/components/ws-manager/pkg/manager/manager.go @@ -29,6 +29,7 @@ import ( "google.golang.org/grpc/peer" "google.golang.org/grpc/status" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" k8serr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -151,7 +152,7 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq return nil, xerrors.Errorf("cannot start workspace: %w", err) } if exists { - return nil, xerrors.Errorf("workspace %s exists already", req.Id) + return nil, status.Error(codes.AlreadyExists, "workspace instance already exists") } span.LogKV("event", "workspace does not exist") err = validateStartWorkspaceRequest(req) @@ -178,6 +179,11 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq m, _ := json.Marshal(pod) safePod, _ := log.RedactJSON(m) + if errors.IsAlreadyExists(err) { + clog.WithError(err).WithField("req", req).WithField("pod", safePod).Warn("was unable to start workspace which already exists") + return nil, status.Error(codes.AlreadyExists, "workspace instance already exists") + } + clog.WithError(err).WithField("req", req).WithField("pod", safePod).Error("was unable to start workspace") return nil, err } From dbf448866c9fc0ca204dd1ad7e5984b32b717d3c Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Sun, 20 Jun 2021 10:39:55 +0000 Subject: [PATCH 05/15] [image-builder] Add integration tests --- test/pkg/integration/apis.go | 25 +++- test/pkg/integration/integration.go | 2 + test/tests/imagebuilder/builder_test.go | 152 ++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 test/tests/imagebuilder/builder_test.go diff --git a/test/pkg/integration/apis.go b/test/pkg/integration/apis.go index 6680a4c6562016..ecc313f07ed7a7 100644 --- a/test/pkg/integration/apis.go +++ b/test/pkg/integration/apis.go @@ -573,15 +573,36 @@ OuterLoop: return &config, nil } +// APIImageBuilderOpt configures the image builder API access +type APIImageBuilderOpt func(*apiImageBuilderOpts) + +// SelectImageBuilderMK3 selects the image builder mk3 +func SelectImageBuilderMK3(o *apiImageBuilderOpts) { + o.SelectMK3 = true +} + +type apiImageBuilderOpts struct { + SelectMK3 bool +} + // ImageBuilder provides access to the image builder service. -func (c *ComponentAPI) ImageBuilder() imgbldr.ImageBuilderClient { +func (c *ComponentAPI) ImageBuilder(opts ...APIImageBuilderOpt) imgbldr.ImageBuilderClient { + var cfg apiImageBuilderOpts + for _, o := range opts { + o(&cfg) + } + if c.imgbldStatus.Client != nil { return c.imgbldStatus.Client } err := func() error { if c.imgbldStatus.Port == 0 { - pod, _, err := c.t.selectPod(ComponentImageBuilder, selectPodOptions{}) + cmp := ComponentImageBuilder + if cfg.SelectMK3 { + cmp = ComponentImageBuilderMK3 + } + pod, _, err := c.t.selectPod(cmp, selectPodOptions{}) if err != nil { return err } diff --git a/test/pkg/integration/integration.go b/test/pkg/integration/integration.go index 768cc729e14ed1..d608206a07ce2e 100644 --- a/test/pkg/integration/integration.go +++ b/test/pkg/integration/integration.go @@ -635,4 +635,6 @@ const ( ComponentWorkspace ComponentType = "workspace" // ComponentImageBuilder points to the image-builder ComponentImageBuilder ComponentType = "image-builder" + // ComponentImageBuilder points to the image-builder-mk3 + ComponentImageBuilderMK3 ComponentType = "image-builder-mk3" ) diff --git a/test/tests/imagebuilder/builder_test.go b/test/tests/imagebuilder/builder_test.go new file mode 100644 index 00000000000000..e34ef8fd05425f --- /dev/null +++ b/test/tests/imagebuilder/builder_test.go @@ -0,0 +1,152 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package imagerbuilder_test + +import ( + "context" + "fmt" + "io" + "testing" + "time" + + csapi "github.com/gitpod-io/gitpod/content-service/api" + imgapi "github.com/gitpod-io/gitpod/image-builder/api" + "github.com/gitpod-io/gitpod/test/pkg/integration" + "golang.org/x/sync/errgroup" +) + +func TestBaseImageBuild(t *testing.T) { + it, ctx := integration.NewTest(t, 5*time.Minute) + defer it.Done() + + client := it.API().ImageBuilder(integration.SelectImageBuilderMK3) + bld, err := client.Build(ctx, &imgapi.BuildRequest{ + ForceRebuild: true, + Source: &imgapi.BuildSource{ + From: &imgapi.BuildSource_File{ + File: &imgapi.BuildSourceDockerfile{ + DockerfileVersion: "some-version", + DockerfilePath: ".gitpod.Dockerfile", + ContextPath: ".", + Source: &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Git{ + Git: &csapi.GitInitializer{ + RemoteUri: "https://github.com/gitpod-io/dazzle.git", + TargetMode: csapi.CloneTargetMode_REMOTE_BRANCH, + CloneTaget: "main", + Config: &csapi.GitConfig{ + Authentication: csapi.GitAuthMethod_NO_AUTH, + }, + }, + }, + }, + }, + }, + }, + }) + if err != nil { + t.Fatal("cannot start build", err) + } + + for { + msg, err := bld.Recv() + if err != nil && err != io.EOF { + t.Fatal(err) + } + + if msg.Status == imgapi.BuildStatus_done_success { + break + } else if msg.Status == imgapi.BuildStatus_done_failure { + t.Fatalf("image build failed: %s", msg.Message) + } else { + t.Logf("build output: %s", msg.Message) + } + } +} + +func TestParallelBaseImageBuild(t *testing.T) { + it, ctx := integration.NewTest(t, 5*time.Minute) + defer it.Done() + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + client := it.API().ImageBuilder(integration.SelectImageBuilderMK3) + req := &imgapi.BuildRequest{ + ForceRebuild: true, + Source: &imgapi.BuildSource{ + From: &imgapi.BuildSource_File{ + File: &imgapi.BuildSourceDockerfile{ + DockerfileVersion: "some-version", + DockerfilePath: ".gitpod.Dockerfile", + ContextPath: ".", + Source: &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Git{ + Git: &csapi.GitInitializer{ + RemoteUri: "https://github.com/gitpod-io/dazzle.git", + TargetMode: csapi.CloneTargetMode_REMOTE_BRANCH, + CloneTaget: "main", + Config: &csapi.GitConfig{ + Authentication: csapi.GitAuthMethod_NO_AUTH, + }, + }, + }, + }, + }, + }, + }, + } + + bld0, err := client.Build(ctx, req) + if err != nil { + t.Fatal("cannot start build", err) + return + } + bld1, err := client.Build(ctx, req) + if err != nil { + t.Fatal("cannot start build", err) + return + } + + watchBuild := func(cl imgapi.ImageBuilder_BuildClient) error { + for { + msg, err := cl.Recv() + if err != nil && err != io.EOF { + return fmt.Errorf("image builder error: %v", err) + } + if err := ctx.Err(); err != nil { + return fmt.Errorf("context error: %v", err) + } + + if msg.Status == imgapi.BuildStatus_done_success { + break + } else if msg.Status == imgapi.BuildStatus_done_failure { + return fmt.Errorf("image build failed: %s", msg.Message) + } else { + t.Logf("build output: %s", msg.Message) + } + } + return nil + } + + var eg errgroup.Group + eg.Go(func() error { return watchBuild(bld0) }) + eg.Go(func() error { return watchBuild(bld1) }) + + blds, err := client.ListBuilds(ctx, &imgapi.ListBuildsRequest{}) + if err != nil { + t.Fatal("cannot list builds", err) + } + + // TODO(cw): make this assertion resiliant against other on-going builds + if l := len(blds.Builds); l != 1 { + t.Errorf("image builder is running not just one build, but %d", l) + } + + err = eg.Wait() + if err != nil { + t.Fatal(err) + } +} From 3ebfe4ecb181a2ef7080e91d8057e0e3fcb16cdc Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Sun, 20 Jun 2021 11:49:15 +0000 Subject: [PATCH 06/15] [image-builder] Maintain local runnig build state --- .../pkg/orchestrator/monitor.go | 25 +++++++++++ .../pkg/orchestrator/orchestrator.go | 44 ++++++++++--------- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/components/image-builder-mk3/pkg/orchestrator/monitor.go b/components/image-builder-mk3/pkg/orchestrator/monitor.go index a48b4730f382b0..b4e1b1f9e19fcd 100644 --- a/components/image-builder-mk3/pkg/orchestrator/monitor.go +++ b/components/image-builder-mk3/pkg/orchestrator/monitor.go @@ -21,6 +21,23 @@ import ( func (o *Orchestrator) monitor() { ctx := context.Background() for { + wss, err := o.wsman.GetWorkspaces(ctx, &wsmanapi.GetWorkspacesRequest{ + MustMatch: &wsmanapi.MetadataFilter{ + Owner: buildWorkspaceOwnerID, + }, + }) + if err != nil { + log.WithError(err).Info("cannot get running builds from ws-manager - retrying") + time.Sleep(5 * time.Second) + continue + } + o.runningBuildsMu.Lock() + o.runningBuilds = make(map[string]*api.BuildInfo, len(wss.Status)) + for _, ws := range wss.Status { + o.runningBuilds[ws.Id] = extractBuildStatus(ws) + } + o.runningBuildsMu.Unlock() + sub, err := o.wsman.Subscribe(ctx, &wsmanapi.SubscribeRequest{ MustMatch: &wsmanapi.MetadataFilter{ Owner: buildWorkspaceOwnerID, @@ -138,6 +155,14 @@ func (o *Orchestrator) publishStatus(msg *wsmanapi.WorkspaceStatus) { } resp := extractBuildResponse(msg) + o.runningBuildsMu.Lock() + if resp.Status != api.BuildStatus_running { + delete(o.runningBuilds, msg.Id) + } else { + o.runningBuilds[msg.Id] = extractBuildStatus(msg) + } + o.runningBuildsMu.Unlock() + for l := range listener { select { case l <- resp: diff --git a/components/image-builder-mk3/pkg/orchestrator/orchestrator.go b/components/image-builder-mk3/pkg/orchestrator/orchestrator.go index 32b0c4e2ea4572..52b0647bd4329b 100644 --- a/components/image-builder-mk3/pkg/orchestrator/orchestrator.go +++ b/components/image-builder-mk3/pkg/orchestrator/orchestrator.go @@ -179,6 +179,7 @@ func NewOrchestratingBuilder(cfg Configuration) (res *Orchestrator, err error) { gplayerHash: gplayerHash, buildListener: make(map[string]map[buildListener]struct{}), logListener: make(map[string]map[logListener]struct{}), + runningBuilds: make(map[string]*protocol.BuildInfo), censorship: make(map[string][]string), builderAuthKey: builderAuthKey, }, nil @@ -216,11 +217,13 @@ type Orchestrator struct { gplayerHash string wsman wsmanapi.WorkspaceManagerClient - builderAuthKey [32]byte - buildListener map[string]map[buildListener]struct{} - logListener map[string]map[logListener]struct{} - censorship map[string][]string - mu sync.RWMutex + builderAuthKey [32]byte + buildListener map[string]map[buildListener]struct{} + logListener map[string]map[logListener]struct{} + runningBuilds map[string]*protocol.BuildInfo + runningBuildsMu sync.RWMutex + censorship map[string][]string + mu sync.RWMutex protocol.UnimplementedImageBuilderServer } @@ -426,8 +429,16 @@ func (o *Orchestrator) Build(req *protocol.BuildRequest, resp protocol.ImageBuil }) return }, 1*time.Second, 5) - if err != nil && status.Code(err) != codes.AlreadyExists { + if status.Code(err) == codes.AlreadyExists { + // build is already running - do not add it to the list of builds + } else if err != nil { return status.Errorf(codes.Internal, "cannot start build: %q", err) + } else { + o.runningBuilds[buildID] = &protocol.BuildInfo{ + Ref: wsrefstr, + Status: protocol.BuildStatus_running, + StartedAt: time.Now().Unix(), + } } updates, cancel := o.registerBuildListener(buildID) @@ -505,7 +516,7 @@ func (o *Orchestrator) ListBuilds(ctx context.Context, req *protocol.ListBuildsR return &protocol.ListBuildsResponse{Builds: res}, nil } -func extractBuildStats(ws *wsmanapi.WorkspaceStatus) *protocol.BuildInfo { +func extractBuildStatus(ws *wsmanapi.WorkspaceStatus) *protocol.BuildInfo { return &protocol.BuildInfo{ Ref: ws.Metadata.Annotations["ref"], StartedAt: ws.Metadata.StartedAt.Seconds, @@ -514,21 +525,12 @@ func extractBuildStats(ws *wsmanapi.WorkspaceStatus) *protocol.BuildInfo { } func (o *Orchestrator) getAllRunningBuilds(ctx context.Context) (res []*protocol.BuildInfo, err error) { - span, ctx := opentracing.StartSpanFromContext(ctx, "getAllRunningBuilds") - defer tracing.FinishSpan(span, &err) - - wss, err := o.wsman.GetWorkspaces(ctx, &wsmanapi.GetWorkspacesRequest{ - MustMatch: &wsmanapi.MetadataFilter{ - Owner: buildWorkspaceOwnerID, - }, - }) - if err != nil { - return - } + o.runningBuildsMu.RLock() + defer o.runningBuildsMu.RUnlock() - res = make([]*protocol.BuildInfo, len(wss.Status)) - for i, ws := range wss.Status { - res[i] = extractBuildStats(ws) + res = make([]*protocol.BuildInfo, 0, len(o.runningBuilds)) + for _, ws := range o.runningBuilds { + res = append(res, ws) } return From 6e9899432c783b72271f50980b32b732c0c3755a Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Sun, 20 Jun 2021 12:05:17 +0000 Subject: [PATCH 07/15] [server] Use image-builder-mk3 by default --- components/server/src/container-module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/server/src/container-module.ts b/components/server/src/container-module.ts index 7d1f3ad18e568a..ac04e35d7474bc 100644 --- a/components/server/src/container-module.ts +++ b/components/server/src/container-module.ts @@ -129,7 +129,7 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo ).inSingletonScope(); bind(ImageBuilderClientConfig).toDynamicValue(() => { - return { address: "image-builder:8080" } + return { address: "image-builder-mk3:8080" } }); bind(CachingImageBuilderClientProvider).toSelf().inSingletonScope(); bind(ImageBuilderClientProvider).toService(CachingImageBuilderClientProvider); From b378f40e3099a2ad67605b2ab22578bcbf0e8a83 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Thu, 24 Jun 2021 12:50:29 +0000 Subject: [PATCH 08/15] [server] Properly use image builder ref --- components/image-builder-api/typescript/src/sugar.ts | 11 +++++++---- test/tests/imagebuilder/builder_test.go | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/components/image-builder-api/typescript/src/sugar.ts b/components/image-builder-api/typescript/src/sugar.ts index bfb2782e886b62..4cabafe309c035 100644 --- a/components/image-builder-api/typescript/src/sugar.ts +++ b/components/image-builder-api/typescript/src/sugar.ts @@ -137,16 +137,19 @@ export class PromisifiedImageBuilderClient { stream.on('data', (resp: BuildResponse) => { log.debug("stream resp", resp) - if (resp.getStatus() == BuildStatus.RUNNING) { - resultResp.actuallyNeedsBuild = true; + if (!resultResp.ref || resultResp.ref === "unknown") { resultResp.ref = resp.getRef(); + } + if (!resultResp.baseRef || resultResp.baseRef === "unknown") { resultResp.baseRef = resp.getBaseRef(); + } + + if (resp.getStatus() == BuildStatus.RUNNING) { + resultResp.actuallyNeedsBuild = true; result.resolve(resultResp); } else if (resp.getStatus() == BuildStatus.DONE_FAILURE || resp.getStatus() == BuildStatus.DONE_SUCCESS) { if (!result.isResolved) { resultResp.actuallyNeedsBuild = false; - resultResp.ref = resp.getRef(); - resultResp.baseRef = resp.getBaseRef(); result.resolve(resultResp); buildResult.resolve(resp); } else { diff --git a/test/tests/imagebuilder/builder_test.go b/test/tests/imagebuilder/builder_test.go index e34ef8fd05425f..ebeeb2d051bcd2 100644 --- a/test/tests/imagebuilder/builder_test.go +++ b/test/tests/imagebuilder/builder_test.go @@ -50,12 +50,14 @@ func TestBaseImageBuild(t *testing.T) { t.Fatal("cannot start build", err) } + var ref string for { msg, err := bld.Recv() if err != nil && err != io.EOF { t.Fatal(err) } + ref = msg.Ref if msg.Status == imgapi.BuildStatus_done_success { break } else if msg.Status == imgapi.BuildStatus_done_failure { @@ -64,6 +66,9 @@ func TestBaseImageBuild(t *testing.T) { t.Logf("build output: %s", msg.Message) } } + if ref == "" { + t.Error("ref was empty") + } } func TestParallelBaseImageBuild(t *testing.T) { From 67f695e09f95551751e656e72e076ee86a3b0a66 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Sun, 18 Jul 2021 12:28:09 +0000 Subject: [PATCH 09/15] [image-builder-mk3] Adapt to new log infrastructure --- .../image-builder-api/go/imgbuilder.pb.go | 173 +++-- components/image-builder-api/imgbuilder.proto | 11 +- .../typescript/src/imgbuilder_pb.d.ts | 9 + .../typescript/src/imgbuilder_pb.js | 83 ++- components/image-builder-bob/go.mod | 60 +- components/image-builder-bob/go.sum | 141 +++- components/image-builder-bob/ide-startup.sh | 0 components/image-builder-mk3/BUILD.yaml | 3 +- components/image-builder-mk3/cmd/root.go | 6 +- components/image-builder-mk3/go.mod | 55 +- components/image-builder-mk3/go.sum | 14 +- .../image-builder.code-workspace | 3 +- .../pkg/orchestrator/monitor.go | 440 +++++++----- .../pkg/orchestrator/monitor_test.go | 116 ++++ .../pkg/orchestrator/orchestrator.go | 244 +++++-- .../gitpod-layer/build.sh | 0 components/ws-manager-api/core.proto | 3 + components/ws-manager-api/go/core.pb.go | 647 +++++++++--------- .../typescript/src/core_pb.d.ts | 3 + .../ws-manager-api/typescript/src/core_pb.js | 32 +- components/ws-manager/pkg/manager/manager.go | 5 +- .../manager/testdata/cdwp_imagebuild.golden | 2 +- dev/gpctl/cmd/imagebuilds-build.go | 16 +- dev/gpctl/cmd/imagebuilds.go | 8 +- 24 files changed, 1383 insertions(+), 691 deletions(-) mode change 100644 => 100755 components/image-builder-bob/ide-startup.sh create mode 100644 components/image-builder-mk3/pkg/orchestrator/monitor_test.go mode change 100644 => 100755 components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh diff --git a/components/image-builder-api/go/imgbuilder.pb.go b/components/image-builder-api/go/imgbuilder.pb.go index f8852d93bc73c6..f746819d26abfc 100644 --- a/components/image-builder-api/go/imgbuilder.pb.go +++ b/components/image-builder-api/go/imgbuilder.pb.go @@ -753,10 +753,15 @@ type BuildResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - BaseRef string `protobuf:"bytes,4,opt,name=base_ref,json=baseRef,proto3" json:"base_ref,omitempty"` + // deprecated(cw): expect this field to go away in a future version. + // it's redundant with the build info. + Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` + BaseRef string `protobuf:"bytes,4,opt,name=base_ref,json=baseRef,proto3" json:"base_ref,omitempty"` + // deprecated(cw): expect this field to go away in a future version. + // it's redundant with the build info. Status BuildStatus `protobuf:"varint,2,opt,name=status,proto3,enum=builder.BuildStatus" json:"status,omitempty"` Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` + Info *BuildInfo `protobuf:"bytes,5,opt,name=info,proto3" json:"info,omitempty"` } func (x *BuildResponse) Reset() { @@ -819,6 +824,13 @@ func (x *BuildResponse) GetMessage() string { return "" } +func (x *BuildResponse) GetInfo() *BuildInfo { + if x != nil { + return x.Info + } + return nil +} + type LogsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1012,6 +1024,7 @@ type BuildInfo struct { unknownFields protoimpl.UnknownFields Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` + BaseRef string `protobuf:"bytes,4,opt,name=base_ref,json=baseRef,proto3" json:"base_ref,omitempty"` Status BuildStatus `protobuf:"varint,2,opt,name=status,proto3,enum=builder.BuildStatus" json:"status,omitempty"` StartedAt int64 `protobuf:"varint,3,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"` } @@ -1055,6 +1068,13 @@ func (x *BuildInfo) GetRef() string { return "" } +func (x *BuildInfo) GetBaseRef() string { + if x != nil { + return x.BaseRef + } + return "" +} + func (x *BuildInfo) GetStatus() BuildStatus { if x != nil { return x.Status @@ -1155,7 +1175,7 @@ var file_imgbuilder_proto_rawDesc = []byte{ 0x65, 0x72, 0x65, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x72, 0x65, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x6e, 0x79, 0x5f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, - 0x6e, 0x79, 0x4f, 0x66, 0x22, 0x84, 0x01, 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, + 0x6e, 0x79, 0x4f, 0x66, 0x22, 0xac, 0x01, 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, @@ -1163,60 +1183,64 @@ var file_imgbuilder_proto_rawDesc = []byte{ 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x46, 0x0a, 0x0b, 0x4c, - 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x65, 0x64, 0x22, 0x28, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x13, 0x0a, - 0x11, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x40, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x65, 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x73, 0x22, 0x6a, 0x0a, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x72, 0x65, 0x66, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x2a, 0x4b, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x0b, 0x0a, 0x07, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, - 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x64, 0x6f, 0x6e, - 0x65, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x64, - 0x6f, 0x6e, 0x65, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x03, 0x32, 0x91, 0x03, - 0x0a, 0x0c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x59, - 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x12, 0x20, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x68, 0x0a, 0x15, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x12, 0x25, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x15, 0x2e, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, - 0x37, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x14, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, - 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x61, - 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x69, + 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, + 0x6e, 0x66, 0x6f, 0x22, 0x46, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x66, 0x12, + 0x1a, 0x0a, 0x08, 0x63, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x63, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x65, 0x64, 0x22, 0x28, 0x0a, 0x0c, 0x4c, + 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x40, 0x0a, 0x12, 0x4c, 0x69, + 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x22, 0x85, 0x01, 0x0a, + 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, + 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x19, 0x0a, 0x08, + 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x66, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, + 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x2a, 0x4b, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x10, 0x0a, + 0x0c, 0x64, 0x6f, 0x6e, 0x65, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, 0x02, 0x12, + 0x10, 0x0a, 0x0c, 0x64, 0x6f, 0x6e, 0x65, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, + 0x03, 0x32, 0x91, 0x03, 0x0a, 0x0c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x65, 0x72, 0x12, 0x59, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x42, 0x61, 0x73, + 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x20, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6d, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x68, 0x0a, + 0x15, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x25, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x12, 0x15, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, + 0x72, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x37, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x14, 0x2e, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x15, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0a, + 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, + 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2d, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1267,23 +1291,24 @@ var file_imgbuilder_proto_depIdxs = []int32{ 10, // 9: builder.BuildRegistryAuth.total:type_name -> builder.BuildRegistryAuthTotal 11, // 10: builder.BuildRegistryAuth.selective:type_name -> builder.BuildRegistryAuthSelective 0, // 11: builder.BuildResponse.status:type_name -> builder.BuildStatus - 17, // 12: builder.ListBuildsResponse.builds:type_name -> builder.BuildInfo - 0, // 13: builder.BuildInfo.status:type_name -> builder.BuildStatus - 4, // 14: builder.ImageBuilder.ResolveBaseImage:input_type -> builder.ResolveBaseImageRequest - 6, // 15: builder.ImageBuilder.ResolveWorkspaceImage:input_type -> builder.ResolveWorkspaceImageRequest - 8, // 16: builder.ImageBuilder.Build:input_type -> builder.BuildRequest - 13, // 17: builder.ImageBuilder.Logs:input_type -> builder.LogsRequest - 15, // 18: builder.ImageBuilder.ListBuilds:input_type -> builder.ListBuildsRequest - 5, // 19: builder.ImageBuilder.ResolveBaseImage:output_type -> builder.ResolveBaseImageResponse - 7, // 20: builder.ImageBuilder.ResolveWorkspaceImage:output_type -> builder.ResolveWorkspaceImageResponse - 12, // 21: builder.ImageBuilder.Build:output_type -> builder.BuildResponse - 14, // 22: builder.ImageBuilder.Logs:output_type -> builder.LogsResponse - 16, // 23: builder.ImageBuilder.ListBuilds:output_type -> builder.ListBuildsResponse - 19, // [19:24] is the sub-list for method output_type - 14, // [14:19] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 17, // 12: builder.BuildResponse.info:type_name -> builder.BuildInfo + 17, // 13: builder.ListBuildsResponse.builds:type_name -> builder.BuildInfo + 0, // 14: builder.BuildInfo.status:type_name -> builder.BuildStatus + 4, // 15: builder.ImageBuilder.ResolveBaseImage:input_type -> builder.ResolveBaseImageRequest + 6, // 16: builder.ImageBuilder.ResolveWorkspaceImage:input_type -> builder.ResolveWorkspaceImageRequest + 8, // 17: builder.ImageBuilder.Build:input_type -> builder.BuildRequest + 13, // 18: builder.ImageBuilder.Logs:input_type -> builder.LogsRequest + 15, // 19: builder.ImageBuilder.ListBuilds:input_type -> builder.ListBuildsRequest + 5, // 20: builder.ImageBuilder.ResolveBaseImage:output_type -> builder.ResolveBaseImageResponse + 7, // 21: builder.ImageBuilder.ResolveWorkspaceImage:output_type -> builder.ResolveWorkspaceImageResponse + 12, // 22: builder.ImageBuilder.Build:output_type -> builder.BuildResponse + 14, // 23: builder.ImageBuilder.Logs:output_type -> builder.LogsResponse + 16, // 24: builder.ImageBuilder.ListBuilds:output_type -> builder.ListBuildsResponse + 20, // [20:25] is the sub-list for method output_type + 15, // [15:20] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_imgbuilder_proto_init() } diff --git a/components/image-builder-api/imgbuilder.proto b/components/image-builder-api/imgbuilder.proto index be10a1218b757a..54998b8e7bd281 100644 --- a/components/image-builder-api/imgbuilder.proto +++ b/components/image-builder-api/imgbuilder.proto @@ -85,10 +85,18 @@ message BuildRegistryAuthSelective { } message BuildResponse { + // deprecated(cw): expect this field to go away in a future version. + // it's redundant with the build info. string ref = 1; + string base_ref = 4; + + // deprecated(cw): expect this field to go away in a future version. + // it's redundant with the build info. BuildStatus status = 2; + string message = 3; + BuildInfo info = 5; } enum BuildStatus { @@ -115,6 +123,7 @@ message ListBuildsResponse { message BuildInfo { string ref = 1; + string base_ref = 4; BuildStatus status = 2; int64 started_at = 3; -} \ No newline at end of file +} diff --git a/components/image-builder-api/typescript/src/imgbuilder_pb.d.ts b/components/image-builder-api/typescript/src/imgbuilder_pb.d.ts index f09fe69a3be62f..8d580665c83308 100644 --- a/components/image-builder-api/typescript/src/imgbuilder_pb.d.ts +++ b/components/image-builder-api/typescript/src/imgbuilder_pb.d.ts @@ -332,6 +332,11 @@ export class BuildResponse extends jspb.Message { getMessage(): string; setMessage(value: string): BuildResponse; + hasInfo(): boolean; + clearInfo(): void; + getInfo(): BuildInfo | undefined; + setInfo(value?: BuildInfo): BuildResponse; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): BuildResponse.AsObject; static toObject(includeInstance: boolean, msg: BuildResponse): BuildResponse.AsObject; @@ -348,6 +353,7 @@ export namespace BuildResponse { baseRef: string, status: BuildStatus, message: string, + info?: BuildInfo.AsObject, } } @@ -438,6 +444,8 @@ export namespace ListBuildsResponse { export class BuildInfo extends jspb.Message { getRef(): string; setRef(value: string): BuildInfo; + getBaseRef(): string; + setBaseRef(value: string): BuildInfo; getStatus(): BuildStatus; setStatus(value: BuildStatus): BuildInfo; getStartedAt(): number; @@ -456,6 +464,7 @@ export class BuildInfo extends jspb.Message { export namespace BuildInfo { export type AsObject = { ref: string, + baseRef: string, status: BuildStatus, startedAt: number, } diff --git a/components/image-builder-api/typescript/src/imgbuilder_pb.js b/components/image-builder-api/typescript/src/imgbuilder_pb.js index b3b3c1dc84258f..e1ed7e9ebe004c 100644 --- a/components/image-builder-api/typescript/src/imgbuilder_pb.js +++ b/components/image-builder-api/typescript/src/imgbuilder_pb.js @@ -2543,7 +2543,8 @@ proto.builder.BuildResponse.toObject = function(includeInstance, msg) { ref: jspb.Message.getFieldWithDefault(msg, 1, ""), baseRef: jspb.Message.getFieldWithDefault(msg, 4, ""), status: jspb.Message.getFieldWithDefault(msg, 2, 0), - message: jspb.Message.getFieldWithDefault(msg, 3, "") + message: jspb.Message.getFieldWithDefault(msg, 3, ""), + info: (f = msg.getInfo()) && proto.builder.BuildInfo.toObject(includeInstance, f) }; if (includeInstance) { @@ -2596,6 +2597,11 @@ proto.builder.BuildResponse.deserializeBinaryFromReader = function(msg, reader) var value = /** @type {string} */ (reader.readString()); msg.setMessage(value); break; + case 5: + var value = new proto.builder.BuildInfo; + reader.readMessage(value,proto.builder.BuildInfo.deserializeBinaryFromReader); + msg.setInfo(value); + break; default: reader.skipField(); break; @@ -2653,6 +2659,14 @@ proto.builder.BuildResponse.serializeBinaryToWriter = function(message, writer) f ); } + f = message.getInfo(); + if (f != null) { + writer.writeMessage( + 5, + f, + proto.builder.BuildInfo.serializeBinaryToWriter + ); + } }; @@ -2728,6 +2742,43 @@ proto.builder.BuildResponse.prototype.setMessage = function(value) { }; +/** + * optional BuildInfo info = 5; + * @return {?proto.builder.BuildInfo} + */ +proto.builder.BuildResponse.prototype.getInfo = function() { + return /** @type{?proto.builder.BuildInfo} */ ( + jspb.Message.getWrapperField(this, proto.builder.BuildInfo, 5)); +}; + + +/** + * @param {?proto.builder.BuildInfo|undefined} value + * @return {!proto.builder.BuildResponse} returns this +*/ +proto.builder.BuildResponse.prototype.setInfo = function(value) { + return jspb.Message.setWrapperField(this, 5, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.builder.BuildResponse} returns this + */ +proto.builder.BuildResponse.prototype.clearInfo = function() { + return this.setInfo(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.builder.BuildResponse.prototype.hasInfo = function() { + return jspb.Message.getField(this, 5) != null; +}; + + @@ -3336,6 +3387,7 @@ proto.builder.BuildInfo.prototype.toObject = function(opt_includeInstance) { proto.builder.BuildInfo.toObject = function(includeInstance, msg) { var f, obj = { ref: jspb.Message.getFieldWithDefault(msg, 1, ""), + baseRef: jspb.Message.getFieldWithDefault(msg, 4, ""), status: jspb.Message.getFieldWithDefault(msg, 2, 0), startedAt: jspb.Message.getFieldWithDefault(msg, 3, 0) }; @@ -3378,6 +3430,10 @@ proto.builder.BuildInfo.deserializeBinaryFromReader = function(msg, reader) { var value = /** @type {string} */ (reader.readString()); msg.setRef(value); break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setBaseRef(value); + break; case 2: var value = /** @type {!proto.builder.BuildStatus} */ (reader.readEnum()); msg.setStatus(value); @@ -3422,6 +3478,13 @@ proto.builder.BuildInfo.serializeBinaryToWriter = function(message, writer) { f ); } + f = message.getBaseRef(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } f = message.getStatus(); if (f !== 0.0) { writer.writeEnum( @@ -3457,6 +3520,24 @@ proto.builder.BuildInfo.prototype.setRef = function(value) { }; +/** + * optional string base_ref = 4; + * @return {string} + */ +proto.builder.BuildInfo.prototype.getBaseRef = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.builder.BuildInfo} returns this + */ +proto.builder.BuildInfo.prototype.setBaseRef = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); +}; + + /** * optional BuildStatus status = 2; * @return {!proto.builder.BuildStatus} diff --git a/components/image-builder-bob/go.mod b/components/image-builder-bob/go.mod index c5641c65059199..318055c65b1fdd 100644 --- a/components/image-builder-bob/go.mod +++ b/components/image-builder-bob/go.mod @@ -33,62 +33,50 @@ replace ( replace github.com/gitpod-io/gitpod/common-go => ../common-go // leeway -replace k8s.io/api => k8s.io/api v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/api => k8s.io/api v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/apimachinery => k8s.io/apimachinery v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/apimachinery => k8s.io/apimachinery v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/apiserver => k8s.io/apiserver v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/apiserver => k8s.io/apiserver v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/client-go => k8s.io/client-go v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/client-go => k8s.io/client-go v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/code-generator => k8s.io/code-generator v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/code-generator => k8s.io/code-generator v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/component-base => k8s.io/component-base v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/component-base => k8s.io/component-base v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cri-api => k8s.io/cri-api v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cri-api => k8s.io/cri-api v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kubelet => k8s.io/kubelet v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kubelet => k8s.io/kubelet v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/metrics => k8s.io/metrics v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/metrics => k8s.io/metrics v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/component-helpers => k8s.io/component-helpers v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/component-helpers => k8s.io/component-helpers v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/controller-manager => k8s.io/controller-manager v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/controller-manager => k8s.io/controller-manager v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kubectl => k8s.io/kubectl v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kubectl => k8s.io/kubectl v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/mount-utils => k8s.io/mount-utils v0.21.0 // leeway indirect from components/common-go:lib - -// copied from https://github.com/moby/buildkit/blob/master/go.mod#L73-L82 -replace ( - // protobuf: corresponds to containerd - github.com/golang/protobuf => github.com/golang/protobuf v1.3.5 - github.com/hashicorp/go-immutable-radix => github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe - github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 - // genproto: corresponds to containerd - google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 - // grpc: corresponds to protobuf - google.golang.org/grpc => google.golang.org/grpc v1.30.0 -) +replace k8s.io/mount-utils => k8s.io/mount-utils v0.21.1 // leeway indirect from components/common-go:lib diff --git a/components/image-builder-bob/go.sum b/components/image-builder-bob/go.sum index 14501d63fcd2d3..7c659035fde57c 100644 --- a/components/image-builder-bob/go.sum +++ b/components/image-builder-bob/go.sum @@ -1,6 +1,7 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.2/go.mod h1:H8IAquKe2L30IxoupDgqTaQvKSwF/c8prYHynGIWQbA= @@ -208,6 +209,7 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= @@ -380,7 +382,11 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -474,14 +480,31 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4-0.20210608040537-544b4180ac70 h1:yxuuMouxXYv9V1HprM9jTODJPGrTrC0FYVtPSnyIXxs= @@ -601,6 +624,8 @@ github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FK github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -610,6 +635,7 @@ github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -634,6 +660,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea/go.mod h1:QMdK4dGB3YhEW2BmA1wgGpPYI3HZy/5gD705PXKUVSg= github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s= @@ -1005,14 +1032,12 @@ github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf h1:L0ixhsTk9j+dVnIvF6aiVCxPiaFvwTOyJxqimPq44p8= github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf/go.mod h1:lJAxK//iyZ3yGbQswdrPTxugZIDM7sd4bEsD0x3XMHk= github.com/tonistiigi/go-actions-cache v0.0.0-20210714033416-b93d7f1b2e70/go.mod h1:dNS+PPTqGnSl80x3wEyWWCHeON5xiBGtcM0uD6CgHNU= -github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe/go.mod h1:/+MCh11CJf2oz0BXmlmqyopK/ad1rKkcOXPoYuPCJYU= github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939 h1:s6wDMZYNyWt8KvkjhrMpOthFPgI3JB8ipJS+eCV/psg= github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.0.0-20210714055410-d010b05b4939/go.mod h1:Vm5u/mtkj1OMhtao0v+BGo2LUoLCgHYXvRmj0jWITlE= github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/httptrace/otelhttptrace v0.0.0-20210714055410-d010b05b4939/go.mod h1:a9cocRplhIBkUAJmak+BPDx+LVL7cTmqUPB0uBcTA4k= github.com/tonistiigi/opentelemetry-go-contrib/instrumentation/net/http/otelhttp v0.0.0-20210714055410-d010b05b4939/go.mod h1:JQAtechjxLEL81EjmbRwxBq/XEzGaHcsPuDHAx54hg4= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= -github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c= github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc= github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -1145,7 +1170,10 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1153,8 +1181,9 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1165,11 +1194,13 @@ 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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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= golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1211,6 +1242,7 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1318,6 +1350,8 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210313202042-bd2e13477e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1333,6 +1367,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1345,13 +1380,16 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiT golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1453,10 +1491,78 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210518161634-ec7691c0a37d h1:bRz6UmsZEz/CzoTjUDp4ZcdguhSWi6CyU299wMQBpZU= +google.golang.org/genproto v0.0.0-20210518161634-ec7691c0a37d/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= @@ -1503,6 +1609,7 @@ gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1511,16 +1618,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= -k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= -k8s.io/cloud-provider v0.21.0/go.mod h1:z17TQgu3JgUFjcgby8sj5X86YdVK5Pbt+jm/eYMZU9M= -k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= -k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw= -k8s.io/controller-manager v0.21.0/go.mod h1:Ohy0GRNRKPVjB8C8G+dV+4aPn26m8HYUI6ejloUBvUA= -k8s.io/cri-api v0.21.0/go.mod h1:nJbXlTpXwYCYuGMR7v3PQb1Du4WOGj2I9085xMVjr3I= -k8s.io/csi-translation-lib v0.21.0/go.mod h1:edq+UMpgqEx3roTuGF/03uIuSOsI986jtu65+ytLlkA= +k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= +k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apiserver v0.21.1/go.mod h1:nLLYZvMWn35glJ4/FZRhzLG/3MPxAaZTgV4FJZdr+tY= +k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs= +k8s.io/cloud-provider v0.21.1/go.mod h1:GgiRu7hOsZh3+VqMMbfLJJS9ZZM9A8k/YiZG8zkWpX4= +k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= +k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA= +k8s.io/controller-manager v0.21.1/go.mod h1:8ugs8DCcHqybiwdVERhnnyGoS5Ksq/ea1p2B0CosHyc= +k8s.io/cri-api v0.21.1/go.mod h1:nJbXlTpXwYCYuGMR7v3PQb1Du4WOGj2I9085xMVjr3I= +k8s.io/csi-translation-lib v0.21.1/go.mod h1:y6NwcsxV1IsoqOm07G4hqANvCLXNDMC1t00lf+CqKRA= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= @@ -1532,7 +1639,7 @@ k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAlS1s8DJca5q4= +k8s.io/legacy-cloud-providers v0.21.1/go.mod h1:rpyWrAsPV1YNn7MmkZydMqleJijhay1Eqx+32K06Rd0= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= diff --git a/components/image-builder-bob/ide-startup.sh b/components/image-builder-bob/ide-startup.sh old mode 100644 new mode 100755 diff --git a/components/image-builder-mk3/BUILD.yaml b/components/image-builder-mk3/BUILD.yaml index 47341f892b47cf..f3086d3812afbd 100644 --- a/components/image-builder-mk3/BUILD.yaml +++ b/components/image-builder-mk3/BUILD.yaml @@ -10,6 +10,7 @@ packages: - components/content-service-api/go:lib - components/content-service:lib - components/image-builder-api/go:lib + - components/supervisor-api/go:lib - components/ws-manager-api/go:lib - components/registry-facade-api/go:lib env: @@ -30,4 +31,4 @@ packages: helm-component: imageBuilderMk3 image: - ${imageRepoBase}/image-builder-mk3:${version} - - ${imageRepoBase}/image-builder-mk3:${__git_commit} \ No newline at end of file + - ${imageRepoBase}/image-builder-mk3:commit-${__git_commit} \ No newline at end of file diff --git a/components/image-builder-mk3/cmd/root.go b/components/image-builder-mk3/cmd/root.go index 8054f8faeccb73..37d928df270ee9 100644 --- a/components/image-builder-mk3/cmd/root.go +++ b/components/image-builder-mk3/cmd/root.go @@ -25,7 +25,7 @@ import ( var ( // ServiceName is the name we use for tracing/logging - ServiceName = "image-builder" + ServiceName = "image-builder-mk3" // Version of this service - set during build Version = "" ) @@ -33,7 +33,7 @@ var ( var verbose bool var configFile string var rootCmd = &cobra.Command{ - Use: "image-builder", + Use: "image-builder-mk3", Short: "Workspace image-builder service", PersistentPreRun: func(cmd *cobra.Command, args []string) { log.Init(ServiceName, Version, verbose && !isatty.IsTerminal(os.Stdout.Fd()), verbose) @@ -42,7 +42,7 @@ var rootCmd = &cobra.Command{ // Execute runs this main command func Execute() { - closer := tracing.Init("image-builder") + closer := tracing.Init(ServiceName) if closer != nil { defer closer.Close() } diff --git a/components/image-builder-mk3/go.mod b/components/image-builder-mk3/go.mod index b6a0844c5a3d4f..d23c74903d8db9 100644 --- a/components/image-builder-mk3/go.mod +++ b/components/image-builder-mk3/go.mod @@ -15,13 +15,18 @@ require ( github.com/gitpod-io/gitpod/content-service/api v0.0.0-00010101000000-000000000000 github.com/gitpod-io/gitpod/image-builder/api v0.0.0-00010101000000-000000000000 github.com/gitpod-io/gitpod/ws-manager/api v0.0.0-00010101000000-000000000000 + github.com/google/go-cmp v0.5.6 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 + github.com/hashicorp/go-retryablehttp v0.7.0 github.com/mattn/go-isatty v0.0.9 github.com/opentracing/opentracing-go v1.2.0 github.com/prometheus/client_golang v1.11.0 github.com/spf13/cobra v0.0.5 + golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 + google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea // indirect google.golang.org/grpc v1.38.0 + google.golang.org/protobuf v1.26.0 gotest.tools v2.2.0+incompatible // indirect ) @@ -35,52 +40,54 @@ replace github.com/gitpod-io/gitpod/image-builder/api => ../image-builder-api/go replace github.com/gitpod-io/gitpod/registry-facade/api => ../registry-facade-api/go // leeway +replace github.com/gitpod-io/gitpod/supervisor/api => ../supervisor-api/go // leeway + replace github.com/gitpod-io/gitpod/ws-manager/api => ../ws-manager-api/go // leeway -replace k8s.io/api => k8s.io/api v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/api => k8s.io/api v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/apimachinery => k8s.io/apimachinery v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/apimachinery => k8s.io/apimachinery v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/apiserver => k8s.io/apiserver v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/apiserver => k8s.io/apiserver v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/client-go => k8s.io/client-go v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/client-go => k8s.io/client-go v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/code-generator => k8s.io/code-generator v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/code-generator => k8s.io/code-generator v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/component-base => k8s.io/component-base v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/component-base => k8s.io/component-base v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/cri-api => k8s.io/cri-api v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/cri-api => k8s.io/cri-api v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kubelet => k8s.io/kubelet v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kubelet => k8s.io/kubelet v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/metrics => k8s.io/metrics v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/metrics => k8s.io/metrics v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/component-helpers => k8s.io/component-helpers v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/component-helpers => k8s.io/component-helpers v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/controller-manager => k8s.io/controller-manager v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/controller-manager => k8s.io/controller-manager v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/kubectl => k8s.io/kubectl v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/kubectl => k8s.io/kubectl v0.21.1 // leeway indirect from components/common-go:lib -replace k8s.io/mount-utils => k8s.io/mount-utils v0.21.0 // leeway indirect from components/common-go:lib +replace k8s.io/mount-utils => k8s.io/mount-utils v0.21.1 // leeway indirect from components/common-go:lib diff --git a/components/image-builder-mk3/go.sum b/components/image-builder-mk3/go.sum index d3283160783cf9..834a040a1ddf25 100644 --- a/components/image-builder-mk3/go.sum +++ b/components/image-builder-mk3/go.sum @@ -118,6 +118,12 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -340,8 +346,9 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea h1:N98SvVh7Hdle2lgUVFuIkf0B3u29CUakMUQa7Hwz8Wc= +google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -356,6 +363,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= @@ -382,8 +390,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= +k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= diff --git a/components/image-builder-mk3/image-builder.code-workspace b/components/image-builder-mk3/image-builder.code-workspace index 429e3e35da341c..a706e6032e50ee 100644 --- a/components/image-builder-mk3/image-builder.code-workspace +++ b/components/image-builder-mk3/image-builder.code-workspace @@ -4,7 +4,8 @@ { "path": "../image-builder-mk3" }, { "path": "../ws-manager" }, { "path": "../server" }, - { "path": "../../test" } + { "path": "../../test" }, + { "path": "../../dev/gpctl" } ], "settings": { "typescript.tsdk": "gitpod/node_modules/typescript/lib", diff --git a/components/image-builder-mk3/pkg/orchestrator/monitor.go b/components/image-builder-mk3/pkg/orchestrator/monitor.go index b4e1b1f9e19fcd..7f8610a56710f7 100644 --- a/components/image-builder-mk3/pkg/orchestrator/monitor.go +++ b/components/image-builder-mk3/pkg/orchestrator/monitor.go @@ -5,23 +5,70 @@ package orchestrator import ( + "bufio" "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" "strings" + "sync" "time" "github.com/gitpod-io/gitpod/common-go/log" "github.com/gitpod-io/gitpod/common-go/tracing" "github.com/gitpod-io/gitpod/image-builder/api" wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "github.com/hashicorp/go-retryablehttp" + "golang.org/x/xerrors" ) -// monitor subscribes to the ws-manager, listens for build updates and distributes them internally -func (o *Orchestrator) monitor() { +const ( + annotationRef = "ref" + annotationBaseRef = "baseref" +) + +type orchestrator interface { + PublishStatus(buildID string, resp *api.BuildResponse) + PublishLog(buildID string, message string) +} + +func newBuildMonitor(o orchestrator, wsman wsmanapi.WorkspaceManagerClient) *buildMonitor { + return &buildMonitor{ + O: o, + wsman: wsman, + runningBuilds: make(map[string]*runningBuild), + logs: map[string]context.CancelFunc{}, + } +} + +type buildMonitor struct { + O orchestrator + + wsman wsmanapi.WorkspaceManagerClient + runningBuilds map[string]*runningBuild + runningBuildsMu sync.RWMutex + + logs map[string]context.CancelFunc +} + +type runningBuild struct { + Info api.BuildInfo + Logs buildLogs +} + +type buildLogs struct { + IdeURL string + OwnerToken string +} + +// Run subscribes to the ws-manager, listens for build updates and distributes them internally +func (m *buildMonitor) Run() { ctx := context.Background() for { - wss, err := o.wsman.GetWorkspaces(ctx, &wsmanapi.GetWorkspacesRequest{ + wss, err := m.wsman.GetWorkspaces(ctx, &wsmanapi.GetWorkspacesRequest{ MustMatch: &wsmanapi.MetadataFilter{ Owner: buildWorkspaceOwnerID, }, @@ -31,14 +78,14 @@ func (o *Orchestrator) monitor() { time.Sleep(5 * time.Second) continue } - o.runningBuildsMu.Lock() - o.runningBuilds = make(map[string]*api.BuildInfo, len(wss.Status)) + m.runningBuildsMu.Lock() + m.runningBuilds = make(map[string]*runningBuild, len(wss.Status)) + m.runningBuildsMu.Unlock() for _, ws := range wss.Status { - o.runningBuilds[ws.Id] = extractBuildStatus(ws) + m.handleStatusUpdate(ws) } - o.runningBuildsMu.Unlock() - sub, err := o.wsman.Subscribe(ctx, &wsmanapi.SubscribeRequest{ + sub, err := m.wsman.Subscribe(ctx, &wsmanapi.SubscribeRequest{ MustMatch: &wsmanapi.MetadataFilter{ Owner: buildWorkspaceOwnerID, }, @@ -57,23 +104,67 @@ func (o *Orchestrator) monitor() { break } - log := msg.GetLog() - if log != nil { - o.publishLog(log.Id, log.Message) - continue - } - status := msg.GetStatus() - if status != nil { - o.publishStatus(status) + if status == nil { continue } + + m.handleStatusUpdate(status) } } } -// retryIfUnavailable makes multiple attempts to execute op if op returns an UNAVAILABLE gRPC status code -func retryIfUnavailable(ctx context.Context, op func(ctx context.Context) error, initialBackoff time.Duration, retries int) (err error) { +func (m *buildMonitor) handleStatusUpdate(status *wsmanapi.WorkspaceStatus) { + var ( + bld = extractRunningBuild(status) + resp = extractBuildResponse(status) + ) + m.runningBuildsMu.Lock() + if resp.Status != api.BuildStatus_running { + delete(m.runningBuilds, status.Id) + } else { + m.runningBuilds[status.Id] = bld + } + m.runningBuildsMu.Unlock() + + m.O.PublishStatus(status.Id, resp) + + // handleStatusUpdate is called from a single go-routine, hence there's no need to synchronize + // access to m.logs + if bld.Info.Status == api.BuildStatus_running { + if _, ok := m.logs[status.Id]; !ok { + // we don't have a headless log listener yet, but need one + ctx, cancel := context.WithCancel(context.Background()) + go listenToHeadlessLogs(ctx, bld.Logs.IdeURL, bld.Logs.OwnerToken, m.handleHeadlessLogs(status.Id)) + m.logs[status.Id] = cancel + } + } else { + if cancel, ok := m.logs[status.Id]; ok { + // we have a headless log listener, and need to stop it + cancel() + delete(m.logs, status.Id) + } + } +} + +func (m *buildMonitor) handleHeadlessLogs(buildID string) listenToHeadlessLogsCallback { + return func(content []byte, err error) { + if err != nil && !errors.Is(err, context.Canceled) { + log.WithError(err).WithField("buildID", buildID).Warn("headless log listener failed") + m.O.PublishLog(buildID, "Build log listener failed. The image build is still running, but you won't see any log output.") + return + } + + if len(content) > 0 { + m.O.PublishLog(buildID, string(content)) + } + } +} + +var errOutOfRetries = fmt.Errorf("out of retries") + +// retry makes multiple attempts to execute op if op returns an UNAVAILABLE gRPC status code +func retry(ctx context.Context, op func(ctx context.Context) error, retry func(err error) bool, initialBackoff time.Duration, retries int) (err error) { span, ctx := tracing.FromContext(ctx, "retryIfUnavailable") defer tracing.FinishSpan(span, &err) @@ -81,13 +172,10 @@ func retryIfUnavailable(ctx context.Context, op func(ctx context.Context) error, err := op(ctx) span.LogKV("attempt", i) - if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable { - // service is unavailable - try again aftersme time + if retry(err) { time.Sleep(initialBackoff * time.Duration(1+i)) - log.WithField("attempt", i).Warn("ws-manager currently unavailable - retrying") continue } - if err != nil { return err } @@ -95,175 +183,211 @@ func retryIfUnavailable(ctx context.Context, op func(ctx context.Context) error, } // we've maxed out our retry attempts - return status.Error(codes.Unavailable, "workspace services are currently unavailable") -} - -func (o *Orchestrator) censor(buildID string, words []string) { - o.mu.Lock() - defer o.mu.Unlock() - - o.censorship[buildID] = words + return errOutOfRetries } -func (o *Orchestrator) publishLog(buildID string, message string) { - o.mu.RLock() - listener, ok := o.logListener[buildID] - o.mu.RUnlock() - - // we don't have any log listener for this build - if !ok { - return - } - - o.mu.RLock() - wds := o.censorship[buildID] - o.mu.RUnlock() - for _, w := range wds { - message = strings.ReplaceAll(message, w, "") - } - - for l := range listener { - select { - case l <- &api.LogsResponse{ - Content: []byte(message), - }: - continue - - case <-time.After(5 * time.Second): - log.Warn("timeout while forwarding log to listener - dropping listener") - o.mu.Lock() - ll := o.logListener[buildID] - // In the meantime the listener list may have been removed/cleared by a call to clearListener. - // We don't have to do any work in this case. - if ll != nil { - close(l) - delete(ll, l) - } - o.mu.Unlock() +func extractBuildStatus(status *wsmanapi.WorkspaceStatus) *api.BuildInfo { + s := api.BuildStatus_running + if status.Phase == wsmanapi.WorkspacePhase_STOPPING || status.Phase == wsmanapi.WorkspacePhase_STOPPED { + if status.Conditions.Failed == "" && status.Conditions.HeadlessTaskFailed == "" { + s = api.BuildStatus_done_success + } else { + s = api.BuildStatus_done_failure } } -} -func (o *Orchestrator) publishStatus(msg *wsmanapi.WorkspaceStatus) { - o.mu.RLock() - listener, ok := o.buildListener[msg.Id] - o.mu.RUnlock() - - // we don't have any log listener for this build - if !ok { - return + return &api.BuildInfo{ + Ref: status.Metadata.Annotations[annotationRef], + BaseRef: status.Metadata.Annotations[annotationBaseRef], + Status: s, + StartedAt: status.Metadata.StartedAt.Seconds, } +} - resp := extractBuildResponse(msg) - o.runningBuildsMu.Lock() - if resp.Status != api.BuildStatus_running { - delete(o.runningBuilds, msg.Id) - } else { - o.runningBuilds[msg.Id] = extractBuildStatus(msg) - } - o.runningBuildsMu.Unlock() - - for l := range listener { - select { - case l <- resp: - continue - - case <-time.After(5 * time.Second): - log.Warn("timeout while forwarding status to listener - dropping listener") - o.mu.Lock() - ll := o.buildListener[msg.Id] - // In the meantime the listener list may have been removed/cleared by a call to clearListener. - // We don't have to do any work in this case. - if ll != nil { - close(l) - delete(ll, l) - } - o.mu.Unlock() - } +func extractRunningBuild(status *wsmanapi.WorkspaceStatus) *runningBuild { + return &runningBuild{ + Info: *extractBuildStatus(status), + Logs: buildLogs{ + IdeURL: status.Spec.Url, + OwnerToken: status.Auth.OwnerToken, + }, } } func extractBuildResponse(status *wsmanapi.WorkspaceStatus) *api.BuildResponse { var ( - s = api.BuildStatus_running - msg = status.Message + info = extractBuildStatus(status) + msg = status.Message ) if status.Phase == wsmanapi.WorkspacePhase_STOPPING { - if status.Conditions.Failed == "" { - s = api.BuildStatus_done_success - } else { - s = api.BuildStatus_done_failure + if status.Conditions.Failed != "" { msg = status.Conditions.Failed + } else if status.Conditions.HeadlessTaskFailed != "" { + msg = status.Conditions.HeadlessTaskFailed } } return &api.BuildResponse{ - Ref: status.Metadata.Annotations["ref"], - BaseRef: status.Metadata.Annotations["baseref"], + Ref: info.Ref, // set for backwards compatibilty - new clients should consume Info + BaseRef: info.BaseRef, // set for backwards compatibilty - new clients should consume Info + Status: info.Status, Message: msg, - Status: s, + Info: info, } } -type buildListener chan *api.BuildResponse +func (m *buildMonitor) GetAllRunningBuilds(ctx context.Context) (res []*runningBuild, err error) { + m.runningBuildsMu.RLock() + defer m.runningBuildsMu.RUnlock() -type logListener chan *api.LogsResponse + res = make([]*runningBuild, 0, len(m.runningBuilds)) + for _, ws := range m.runningBuilds { + res = append(res, ws) + } -func (o *Orchestrator) registerBuildListener(buildID string) (c <-chan *api.BuildResponse, cancel func()) { - o.mu.Lock() - defer o.mu.Unlock() + return +} - l := make(buildListener) - ls := o.buildListener[buildID] - if ls == nil { - ls = make(map[buildListener]struct{}) +func (m *buildMonitor) RegisterNewBuild(buildID string, ref, baseRef, url, ownerToken string) { + m.runningBuildsMu.Lock() + defer m.runningBuildsMu.Unlock() + + bld := &runningBuild{ + Info: api.BuildInfo{ + Ref: ref, + BaseRef: baseRef, + Status: api.BuildStatus_running, + StartedAt: time.Now().Unix(), + }, + Logs: buildLogs{ + IdeURL: url, + OwnerToken: ownerToken, + }, } - ls[l] = struct{}{} - o.buildListener[buildID] = ls - - cancel = func() { - o.mu.Lock() - defer o.mu.Unlock() - ls := o.buildListener[buildID] - if ls == nil { - return + m.runningBuilds[buildID] = bld + log.WithField("build", bld).WithField("buildID", buildID).Debug("new build registered") +} + +type listenToHeadlessLogsCallback func(content []byte, err error) + +func listenToHeadlessLogs(ctx context.Context, url, authToken string, callback listenToHeadlessLogsCallback) { + var err error + defer func() { + if err != nil { + callback(nil, err) } - delete(ls, l) - o.buildListener[buildID] = ls + }() + + var logURL string + err = retry(ctx, func(ctx context.Context) (err error) { + logURL, err = findTaskLogURL(ctx, url, authToken) + return + }, func(err error) bool { + if err == nil { + return false + } + if errors.Is(err, io.EOF) { + // the network is not reliable + return true + } + if strings.Contains(err.Error(), "received non-200 status") { + // gRPC-web race in supervisor? + return true + } + return false + }, 1*time.Second, 10) + if err != nil { + return } - return l, cancel -} + log.WithField("logURL", logURL).Debug("found log URL") + callback([]byte("connecting to log output ...\n"), nil) -func (o *Orchestrator) registerLogListener(buildID string) (c <-chan *api.LogsResponse, cancel func()) { - o.mu.Lock() - defer o.mu.Unlock() + req, err := http.NewRequestWithContext(ctx, "GET", logURL, nil) + if err != nil { + return + } + req.Header.Set("x-gitpod-owner-token", authToken) + req.Header.Set("Cache", "no-cache") - l := make(logListener) - ls := o.logListener[buildID] - if ls == nil { - ls = make(map[logListener]struct{}) + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return } - ls[l] = struct{}{} - o.logListener[buildID] = ls - - cancel = func() { - o.mu.Lock() - defer o.mu.Unlock() - ls := o.logListener[buildID] - if ls == nil { - return + log.WithField("logURL", logURL).Debug("terminal log response received") + callback([]byte("connected to log output ...\n"), nil) + + defer resp.Body.Close() + + var line struct { + Result struct { + Data []byte `json:"data"` + } `json:"result"` + } + + r := bufio.NewScanner(resp.Body) + for r.Scan() { + err := json.Unmarshal(r.Bytes(), &line) + if err != nil { + callback(nil, err) + continue } - delete(ls, l) - o.logListener[buildID] = ls + callback(line.Result.Data, nil) + } + err = r.Err() + if errors.Is(err, io.EOF) { + // EOF is not an error in this case + err = nil + return + } + if err != nil { + return } - return l, cancel } -func (o *Orchestrator) clearListener(buildID string) { - o.mu.Lock() - defer o.mu.Unlock() +func findTaskLogURL(ctx context.Context, ideURL, authToken string) (taskLogURL string, err error) { + ideURL = strings.TrimSuffix(ideURL, "/") + tasksURL := ideURL + "/_supervisor/v1/status/tasks" + req, err := http.NewRequestWithContext(ctx, "GET", tasksURL, nil) + if err != nil { + return "", err + } + req.Header.Set("x-gitpod-owner-token", authToken) + req.Header.Set("Cache", "no-cache") + + client := retryablehttp.NewClient() + client.RetryMax = 10 + client.Logger = nil + + resp, err := client.StandardClient().Do(req) + if err != nil { + return "", xerrors.Errorf("cannot connect to supervisor: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", xerrors.Errorf("received non-200 status from %s: %v", tasksURL, resp.StatusCode) + } - delete(o.buildListener, buildID) - delete(o.logListener, buildID) - delete(o.censorship, buildID) + msg, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var respb struct { + Result struct { + Tasks []struct { + Terminal string `json:"terminal"` + } `json:"tasks"` + } `json:"result"` + } + err = json.Unmarshal(msg, &respb) + if err != nil { + return "", xerrors.Errorf("cannot decode supervisor status response: %w", err) + } + + if len(respb.Result.Tasks) == 0 { + return "", xerrors.Errorf("build workspace has no tasks") + } + return fmt.Sprintf("%s/_supervisor/v1/terminal/listen/%s", ideURL, respb.Result.Tasks[0].Terminal), nil } diff --git a/components/image-builder-mk3/pkg/orchestrator/monitor_test.go b/components/image-builder-mk3/pkg/orchestrator/monitor_test.go new file mode 100644 index 00000000000000..4e811629d9bdc2 --- /dev/null +++ b/components/image-builder-mk3/pkg/orchestrator/monitor_test.go @@ -0,0 +1,116 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package orchestrator + +import ( + "testing" + "time" + + "github.com/gitpod-io/gitpod/image-builder/api" + wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestExtractBuildResponse(t *testing.T) { + const ( + buildID = "build-id" + ref = "ref" + baseref = "base-ref" + startedAt int64 = 12345 + ) + tests := []struct { + Name string + Mod func(*wsmanapi.WorkspaceStatus) + Expectation func(*api.BuildResponse) + }{ + { + Name: "running", + Mod: func(ws *wsmanapi.WorkspaceStatus) {}, + Expectation: func(br *api.BuildResponse) {}, + }, + { + Name: "done", + Mod: func(ws *wsmanapi.WorkspaceStatus) { + ws.Phase = wsmanapi.WorkspacePhase_STOPPING + }, + Expectation: func(br *api.BuildResponse) { + br.Status = api.BuildStatus_done_success + br.Info.Status = br.Status + }, + }, + { + Name: "done stopped", + Mod: func(ws *wsmanapi.WorkspaceStatus) { + ws.Phase = wsmanapi.WorkspacePhase_STOPPED + }, + Expectation: func(br *api.BuildResponse) { + br.Status = api.BuildStatus_done_success + br.Info.Status = br.Status + }, + }, + { + Name: "done task failed", + Mod: func(ws *wsmanapi.WorkspaceStatus) { + ws.Phase = wsmanapi.WorkspacePhase_STOPPING + ws.Conditions.HeadlessTaskFailed = "image build failed" + }, + Expectation: func(br *api.BuildResponse) { + br.Status = api.BuildStatus_done_failure + br.Info.Status = br.Status + br.Message = "image build failed" + }, + }, + { + Name: "done workspace failed", + Mod: func(ws *wsmanapi.WorkspaceStatus) { + ws.Phase = wsmanapi.WorkspacePhase_STOPPING + ws.Conditions.Failed = "image build failed" + }, + Expectation: func(br *api.BuildResponse) { + br.Status = api.BuildStatus_done_failure + br.Info.Status = br.Status + br.Message = "image build failed" + }, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + status := &wsmanapi.WorkspaceStatus{ + Id: buildID, + Metadata: &wsmanapi.WorkspaceMetadata{ + Annotations: map[string]string{ + annotationRef: ref, + annotationBaseRef: baseref, + }, + StartedAt: timestamppb.New(time.Unix(startedAt, 0)), + }, + Conditions: &wsmanapi.WorkspaceConditions{}, + Phase: wsmanapi.WorkspacePhase_RUNNING, + } + test.Mod(status) + act := extractBuildResponse(status) + + exp := &api.BuildResponse{ + Ref: ref, + BaseRef: baseref, + Status: api.BuildStatus_running, + Info: &api.BuildInfo{ + Ref: ref, + BaseRef: baseref, + Status: api.BuildStatus_running, + StartedAt: startedAt, + }, + } + test.Expectation(exp) + + if diff := cmp.Diff(exp, act, cmpopts.IgnoreUnexported(api.BuildResponse{}, api.BuildInfo{})); diff != "" { + t.Errorf("extractBuildResponse() mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/components/image-builder-mk3/pkg/orchestrator/orchestrator.go b/components/image-builder-mk3/pkg/orchestrator/orchestrator.go index 52b0647bd4329b..fdbc532c4cf647 100644 --- a/components/image-builder-mk3/pkg/orchestrator/orchestrator.go +++ b/components/image-builder-mk3/pkg/orchestrator/orchestrator.go @@ -14,6 +14,7 @@ import ( "crypto/x509" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -27,6 +28,7 @@ import ( "github.com/gitpod-io/gitpod/common-go/log" "github.com/gitpod-io/gitpod/common-go/tracing" csapi "github.com/gitpod-io/gitpod/content-service/api" + "github.com/gitpod-io/gitpod/image-builder/api" protocol "github.com/gitpod-io/gitpod/image-builder/api" "github.com/gitpod-io/gitpod/image-builder/pkg/auth" "github.com/gitpod-io/gitpod/image-builder/pkg/resolve" @@ -166,7 +168,7 @@ func NewOrchestratingBuilder(cfg Configuration) (res *Orchestrator, err error) { return } - return &Orchestrator{ + o := &Orchestrator{ Config: cfg, Auth: authentication, AuthResolver: auth.Resolver{ @@ -179,10 +181,12 @@ func NewOrchestratingBuilder(cfg Configuration) (res *Orchestrator, err error) { gplayerHash: gplayerHash, buildListener: make(map[string]map[buildListener]struct{}), logListener: make(map[string]map[logListener]struct{}), - runningBuilds: make(map[string]*protocol.BuildInfo), censorship: make(map[string][]string), builderAuthKey: builderAuthKey, - }, nil + } + o.monitor = newBuildMonitor(o, o.wsman) + + return o, nil } func computeGitpodLayerHash(gitpodLayerLoc string) (string, error) { @@ -217,20 +221,20 @@ type Orchestrator struct { gplayerHash string wsman wsmanapi.WorkspaceManagerClient - builderAuthKey [32]byte - buildListener map[string]map[buildListener]struct{} - logListener map[string]map[logListener]struct{} - runningBuilds map[string]*protocol.BuildInfo - runningBuildsMu sync.RWMutex - censorship map[string][]string - mu sync.RWMutex + builderAuthKey [32]byte + buildListener map[string]map[buildListener]struct{} + logListener map[string]map[logListener]struct{} + censorship map[string][]string + mu sync.RWMutex + + monitor *buildMonitor protocol.UnimplementedImageBuilderServer } // Start fires up the internals of this image builder func (o *Orchestrator) Start(ctx context.Context) error { - go o.monitor() + go o.monitor.Run() return nil } @@ -392,15 +396,25 @@ func (o *Orchestrator) Build(req *protocol.BuildRequest, resp protocol.ImageBuil }) // push some log to the client before starting the job, just in case the build workspace takes a while to start up - o.publishLog(buildID, "starting image build") + o.PublishLog(buildID, "starting image build") - err = retryIfUnavailable(ctx, func(ctx context.Context) (err error) { - _, err = o.wsman.StartWorkspace(ctx, &wsmanapi.StartWorkspaceRequest{ - Id: buildID, + retryIfUnavailable1 := func(err error) bool { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable { + return true + } + return false + } + + var swr *wsmanapi.StartWorkspaceResponse + err = retry(ctx, func(ctx context.Context) (err error) { + swr, err = o.wsman.StartWorkspace(ctx, &wsmanapi.StartWorkspaceRequest{ + Id: buildID, + ServicePrefix: buildID, Metadata: &wsmanapi.WorkspaceMetadata{ MetaId: buildID, Annotations: map[string]string{ - "ref": wsrefstr, + annotationRef: wsrefstr, + annotationBaseRef: baseref, }, // TODO(cw): use the actual image build owner here and move to annotation based filter // when retrieving running image builds. @@ -428,17 +442,16 @@ func (o *Orchestrator) Build(req *protocol.BuildRequest, resp protocol.ImageBuil Type: wsmanapi.WorkspaceType_IMAGEBUILD, }) return - }, 1*time.Second, 5) + }, retryIfUnavailable1, 1*time.Second, 5) if status.Code(err) == codes.AlreadyExists { // build is already running - do not add it to the list of builds + } else if errors.Is(err, errOutOfRetries) { + return status.Error(codes.Unavailable, "workspace services are currently unavailable") } else if err != nil { return status.Errorf(codes.Internal, "cannot start build: %q", err) } else { - o.runningBuilds[buildID] = &protocol.BuildInfo{ - Ref: wsrefstr, - Status: protocol.BuildStatus_running, - StartedAt: time.Now().Unix(), - } + o.monitor.RegisterNewBuild(buildID, wsrefstr, baseref, swr.Url, swr.OwnerToken) + o.PublishLog(buildID, "starting image build ...\n") } updates, cancel := o.registerBuildListener(buildID) @@ -466,16 +479,49 @@ func (o *Orchestrator) Build(req *protocol.BuildRequest, resp protocol.ImageBuil return nil } +// publishStatus broadcasts a build status update to all listeners +func (o *Orchestrator) PublishStatus(buildID string, resp *api.BuildResponse) { + o.mu.RLock() + listener, ok := o.buildListener[buildID] + o.mu.RUnlock() + + // we don't have any log listener for this build + if !ok { + return + } + + log.WithField("buildID", buildID).WithField("resp", resp).Debug("publishing status") + + for l := range listener { + select { + case l <- resp: + continue + + case <-time.After(5 * time.Second): + log.Warn("timeout while forwarding status to listener - dropping listener") + o.mu.Lock() + ll := o.buildListener[buildID] + // In the meantime the listener list may have been removed/cleared by a call to clearListener. + // We don't have to do any work in this case. + if ll != nil { + close(l) + delete(ll, l) + } + o.mu.Unlock() + } + } +} + // Logs listens to the build output of an ongoing Docker build identified build the build ID func (o *Orchestrator) Logs(req *protocol.LogsRequest, resp protocol.ImageBuilder_LogsServer) (err error) { - span, ctx := opentracing.StartSpanFromContext(resp.Context(), "Build") + span, ctx := opentracing.StartSpanFromContext(resp.Context(), "Logs") defer tracing.FinishSpan(span, &err) tracing.LogRequestSafe(span, req) - rb, err := o.getAllRunningBuilds(ctx) + rb, err := o.monitor.GetAllRunningBuilds(ctx) var found bool for _, bld := range rb { - if bld.Ref == req.BuildRef { + if bld.Info.Ref == req.BuildRef { found = true break } @@ -508,32 +554,17 @@ func (o *Orchestrator) ListBuilds(ctx context.Context, req *protocol.ListBuildsR span, ctx := opentracing.StartSpanFromContext(ctx, "ListBuilds") defer tracing.FinishSpan(span, &err) - res, err := o.getAllRunningBuilds(ctx) + builds, err := o.monitor.GetAllRunningBuilds(ctx) if err != nil { return } - return &protocol.ListBuildsResponse{Builds: res}, nil -} - -func extractBuildStatus(ws *wsmanapi.WorkspaceStatus) *protocol.BuildInfo { - return &protocol.BuildInfo{ - Ref: ws.Metadata.Annotations["ref"], - StartedAt: ws.Metadata.StartedAt.Seconds, - Status: protocol.BuildStatus_running, + res := make([]*protocol.BuildInfo, 0, len(builds)) + for _, ws := range builds { + res = append(res, &ws.Info) } -} -func (o *Orchestrator) getAllRunningBuilds(ctx context.Context) (res []*protocol.BuildInfo, err error) { - o.runningBuildsMu.RLock() - defer o.runningBuildsMu.RUnlock() - - res = make([]*protocol.BuildInfo, 0, len(o.runningBuilds)) - for _, ws := range o.runningBuilds { - res = append(res, ws) - } - - return + return &protocol.ListBuildsResponse{Builds: res}, nil } func (o *Orchestrator) checkImageExists(ctx context.Context, ref string, authentication *auth.Authentication) (exists bool, err error) { @@ -677,8 +708,12 @@ func (c *parentCantCancelContext) Value(key interface{}) interface{} { func computeBuildID(ref string) string { // The buildID will be used as workspaceID which must not be longer than 63 characters because it's a kubernetes label. - // Using sha224 makes sure our hash is shorter than 63 charts. SHA256 would be 64 chars when printed as hex. - return fmt.Sprintf("%x", sha256.Sum224([]byte(ref))) + hash := fmt.Sprintf("%x", sha256.Sum256([]byte(ref))) + + // Truncating hashes is fine according to NIST - and StackOverflow :) + // Note: the buildID is also used as servicePrefix for the StartWorkspace request and must match + // the workspaceIDIdentifier regexp in ws-proxy + return fmt.Sprintf("%s-%s-%s", hash[0:16], hash[16:32], hash[32:40]) } // source: https://astaxie.gitbooks.io/build-web-application-with-golang/en/09.6.html @@ -724,3 +759,118 @@ func (o *Orchestrator) getAuthFor(inp auth.AllowedAuthFor, refs ...string) (res return } + +type buildListener chan *api.BuildResponse + +type logListener chan *api.LogsResponse + +func (o *Orchestrator) registerBuildListener(buildID string) (c <-chan *api.BuildResponse, cancel func()) { + o.mu.Lock() + defer o.mu.Unlock() + + l := make(buildListener) + ls := o.buildListener[buildID] + if ls == nil { + ls = make(map[buildListener]struct{}) + } + ls[l] = struct{}{} + o.buildListener[buildID] = ls + + cancel = func() { + o.mu.Lock() + defer o.mu.Unlock() + ls := o.buildListener[buildID] + if ls == nil { + return + } + delete(ls, l) + o.buildListener[buildID] = ls + } + return l, cancel +} + +func (o *Orchestrator) registerLogListener(buildID string) (c <-chan *api.LogsResponse, cancel func()) { + o.mu.Lock() + defer o.mu.Unlock() + + l := make(logListener) + ls := o.logListener[buildID] + if ls == nil { + ls = make(map[logListener]struct{}) + } + ls[l] = struct{}{} + o.logListener[buildID] = ls + log.WithField("buildID", buildID).WithField("listener", len(ls)).Debug("registered log listener") + + cancel = func() { + o.mu.Lock() + defer o.mu.Unlock() + ls := o.logListener[buildID] + if ls == nil { + return + } + delete(ls, l) + o.logListener[buildID] = ls + + log.WithField("buildID", buildID).WithField("listener", len(ls)).Debug("deregistered log listener") + } + return l, cancel +} + +// clearListener removes all listener for a particular build +func (o *Orchestrator) clearListener(buildID string) { + o.mu.Lock() + defer o.mu.Unlock() + + delete(o.buildListener, buildID) + delete(o.logListener, buildID) + delete(o.censorship, buildID) +} + +// censor registers tokens that are censored in the log output +func (o *Orchestrator) censor(buildID string, words []string) { + o.mu.Lock() + defer o.mu.Unlock() + + o.censorship[buildID] = words +} + +// PublishLog broadcasts log output to all registered listener +func (o *Orchestrator) PublishLog(buildID string, message string) { + o.mu.RLock() + listener, ok := o.logListener[buildID] + o.mu.RUnlock() + + // we don't have any log listener for this build + if !ok { + return + } + + o.mu.RLock() + wds := o.censorship[buildID] + o.mu.RUnlock() + for _, w := range wds { + message = strings.ReplaceAll(message, w, "") + } + + for l := range listener { + select { + case l <- &api.LogsResponse{ + Content: []byte(message), + }: + continue + + case <-time.After(5 * time.Second): + log.WithField("buildID", buildID).Warn("timeout while forwarding log to listener - dropping listener") + o.mu.Lock() + ll := o.logListener[buildID] + // In the meantime the listener list may have been removed/cleared by a call to clearListener. + // We don't have to do any work in this case. + if ll != nil { + close(l) + delete(ll, l) + } + o.mu.Unlock() + } + } +} diff --git a/components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh b/components/image-builder-mk3/workspace-image-layer/gitpod-layer/build.sh old mode 100644 new mode 100755 diff --git a/components/ws-manager-api/core.proto b/components/ws-manager-api/core.proto index 1ed0d31c3e38ca..9f863d4512d23f 100644 --- a/components/ws-manager-api/core.proto +++ b/components/ws-manager-api/core.proto @@ -92,6 +92,9 @@ message StartWorkspaceRequest { message StartWorkspaceResponse { // URL is the external URL of the workspace string url = 1; + + // OwnerToken is the token of the workspace owner used for authentication + string owner_token = 2; } // StopWorkspaceRequest requests that the workspace manager stops a workspace diff --git a/components/ws-manager-api/go/core.pb.go b/components/ws-manager-api/go/core.pb.go index 24c0a235855664..87dde6fc116bd5 100644 --- a/components/ws-manager-api/go/core.pb.go +++ b/components/ws-manager-api/go/core.pb.go @@ -684,6 +684,8 @@ type StartWorkspaceResponse struct { // URL is the external URL of the workspace Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + // OwnerToken is the token of the workspace owner used for authentication + OwnerToken string `protobuf:"bytes,2,opt,name=owner_token,json=ownerToken,proto3" json:"owner_token,omitempty"` } func (x *StartWorkspaceResponse) Reset() { @@ -725,6 +727,13 @@ func (x *StartWorkspaceResponse) GetUrl() string { return "" } +func (x *StartWorkspaceResponse) GetOwnerToken() string { + if x != nil { + return x.OwnerToken + } + return "" +} + // StopWorkspaceRequest requests that the workspace manager stops a workspace type StopWorkspaceRequest struct { state protoimpl.MessageState @@ -2566,331 +2575,333 @@ var file_core_proto_rawDesc = []byte{ 0x73, 0x70, 0x65, 0x63, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x4a, 0x04, - 0x08, 0x05, 0x10, 0x06, 0x22, 0x2a, 0x0a, 0x16, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, + 0x08, 0x05, 0x10, 0x06, 0x22, 0x4b, 0x0a, 0x16, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, - 0x22, 0x5a, 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, - 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x17, 0x0a, 0x15, - 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x5a, 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, + 0x6e, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x17, 0x0a, + 0x15, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x6f, 0x0a, 0x19, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x22, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x22, 0x48, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x6d, 0x75, 0x73, 0x74, 0x5f, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x09, 0x6d, 0x75, 0x73, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xf9, 0x01, + 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, + 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 0x09, + 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x3b, 0x0a, 0x11, 0x4d, 0x61, 0x72, + 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x11, + 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x22, 0x6f, 0x0a, 0x19, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, - 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x22, 0x48, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x52, 0x09, 0x6d, 0x75, 0x73, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xf9, 0x01, 0x0a, - 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, - 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 0x09, 0x0a, - 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x3b, 0x0a, 0x11, 0x4d, 0x61, 0x72, 0x6b, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, - 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x11, 0x53, - 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x14, 0x0a, 0x12, - 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x61, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x12, 0x23, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, - 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0x15, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, 0x13, - 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x22, 0x28, 0x0a, 0x14, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x56, 0x0a, - 0x17, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, - 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x1a, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x9e, 0x03, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x04, 0x73, - 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, 0x61, - 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, - 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, 0x61, - 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x32, - 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x61, 0x75, - 0x74, 0x68, 0x22, 0xfd, 0x01, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, - 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x65, - 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x68, 0x65, - 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x14, 0x0a, + 0x12, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x61, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, + 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, + 0x6f, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x73, + 0x65, 0x12, 0x23, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x28, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x77, - 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x22, 0x7f, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x76, 0x69, - 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x75, 0x72, 0x6c, 0x22, 0xc6, 0x04, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x44, 0x0a, - 0x0e, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, + 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0x15, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, + 0x13, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x22, 0x28, 0x0a, 0x14, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x56, + 0x0a, 0x17, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, + 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x1a, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x9e, 0x03, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x04, + 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x73, 0x6d, + 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, + 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, + 0x61, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x72, 0x65, 0x70, + 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, + 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, + 0x32, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x61, + 0x75, 0x74, 0x68, 0x22, 0xfd, 0x01, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, + 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x68, + 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x65, 0x78, 0x70, + 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, + 0x63, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, + 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, + 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x22, 0x7f, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, + 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x75, 0x72, 0x6c, 0x22, 0xc6, 0x04, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x44, + 0x0a, 0x0e, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, + 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x51, 0x0a, 0x15, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, + 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x70, 0x75, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, - 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, + 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, + 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x64, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x51, 0x0a, 0x15, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x62, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x6f, 0x6f, 0x6c, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x11, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6e, - 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, - 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0f, 0x6e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x4a, - 0x0a, 0x13, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x09, 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, 0x11, 0x66, 0x69, 0x72, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x65, - 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x66, 0x61, 0x69, 0x6c, - 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x68, 0x65, 0x61, 0x64, 0x6c, 0x65, - 0x73, 0x73, 0x54, 0x61, 0x73, 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x8a, 0x02, 0x0a, - 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x61, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, 0x49, - 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x4b, 0x0a, 0x0b, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x67, 0x0a, 0x14, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, - 0x0a, 0x08, 0x70, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x70, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, - 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, - 0x49, 0x70, 0x22, 0x6f, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, - 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x22, 0x8e, 0x04, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x12, 0x40, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x46, 0x6c, 0x61, 0x67, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, - 0x67, 0x73, 0x12, 0x46, 0x0a, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x52, 0x0b, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x6f, - 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, 0x61, - 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, - 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, - 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, - 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x6f, 0x75, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x03, 0x67, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x03, 0x67, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, - 0x33, 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, 0x0a, 0x07, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, - 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, - 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, - 0x6c, 0x22, 0x3f, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x75, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, - 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x73, - 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x34, 0x0a, 0x13, 0x53, 0x74, 0x6f, - 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x0f, - 0x0a, 0x0b, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x4c, 0x59, 0x10, 0x01, 0x2a, - 0x3a, 0x0a, 0x0e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x44, 0x4d, 0x49, 0x54, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, - 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x44, 0x4d, 0x49, 0x54, - 0x5f, 0x45, 0x56, 0x45, 0x52, 0x59, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x2a, 0x49, 0x0a, 0x0e, 0x50, - 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, - 0x17, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, - 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x4f, - 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x55, - 0x42, 0x4c, 0x49, 0x43, 0x10, 0x01, 0x2a, 0x38, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, - 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54, - 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x02, - 0x2a, 0x83, 0x01, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x68, - 0x61, 0x73, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, 0x0a, - 0x08, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x49, - 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0b, 0x0a, - 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, - 0x54, 0x45, 0x52, 0x52, 0x55, 0x50, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x53, - 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, - 0x50, 0x50, 0x45, 0x44, 0x10, 0x06, 0x2a, 0x68, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, - 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x55, 0x4c, 0x4c, - 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x55, - 0x50, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x10, 0x05, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x22, 0x04, - 0x08, 0x02, 0x10, 0x02, 0x22, 0x04, 0x08, 0x03, 0x10, 0x03, 0x22, 0x04, 0x08, 0x06, 0x10, 0x06, - 0x2a, 0x50, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x00, 0x12, 0x0c, - 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, - 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x48, 0x4f, 0x53, 0x54, - 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x44, - 0x10, 0x04, 0x32, 0x91, 0x06, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, - 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, - 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x6f, - 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, - 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x73, 0x6d, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x11, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, + 0x6e, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0f, + 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, + 0x4a, 0x0a, 0x13, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x09, 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, 0x11, 0x66, 0x69, 0x72, 0x73, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x68, + 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x66, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x68, 0x65, 0x61, 0x64, 0x6c, + 0x65, 0x73, 0x73, 0x54, 0x61, 0x73, 0x6b, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x8a, 0x02, + 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, + 0x61, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, + 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x4b, 0x0a, + 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x67, 0x0a, 0x14, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x70, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, + 0x65, 0x49, 0x70, 0x22, 0x6f, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, + 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8e, 0x04, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x27, 0x0a, 0x0f, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, + 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, + 0x61, 0x67, 0x73, 0x12, 0x46, 0x0a, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x52, 0x0b, + 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x70, + 0x6f, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x77, 0x73, 0x6d, + 0x61, 0x6e, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x70, 0x6f, 0x72, + 0x74, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x6f, 0x75, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x03, 0x67, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, + 0x63, 0x52, 0x03, 0x67, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x12, 0x33, 0x0a, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x64, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, 0x0a, 0x07, 0x47, 0x69, 0x74, 0x53, 0x70, 0x65, 0x63, + 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, + 0x69, 0x6c, 0x22, 0x3f, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, + 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x34, 0x0a, 0x13, 0x53, 0x74, + 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x4c, 0x59, 0x10, 0x00, 0x12, + 0x0f, 0x0a, 0x0b, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x4c, 0x59, 0x10, 0x01, + 0x2a, 0x3a, 0x0a, 0x0e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x44, 0x4d, 0x49, 0x54, 0x5f, 0x4f, 0x57, 0x4e, 0x45, + 0x52, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x44, 0x4d, 0x49, + 0x54, 0x5f, 0x45, 0x56, 0x45, 0x52, 0x59, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x2a, 0x49, 0x0a, 0x0e, + 0x50, 0x6f, 0x72, 0x74, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1b, + 0x0a, 0x17, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, + 0x59, 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, + 0x4f, 0x52, 0x54, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, + 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x01, 0x2a, 0x38, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6f, + 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, + 0x54, 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, + 0x02, 0x2a, 0x83, 0x01, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, + 0x68, 0x61, 0x73, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0c, + 0x0a, 0x08, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, + 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0b, + 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x49, + 0x4e, 0x54, 0x45, 0x52, 0x52, 0x55, 0x50, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, + 0x53, 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, + 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x06, 0x2a, 0x68, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x12, + 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x55, 0x4c, + 0x4c, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, + 0x55, 0x50, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, 0x10, 0x05, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x22, + 0x04, 0x08, 0x02, 0x10, 0x02, 0x22, 0x04, 0x08, 0x03, 0x10, 0x03, 0x22, 0x04, 0x08, 0x06, 0x10, + 0x06, 0x2a, 0x50, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x00, 0x12, + 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, + 0x05, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x48, 0x4f, 0x53, + 0x54, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x42, 0x55, 0x49, 0x4c, + 0x44, 0x10, 0x04, 0x32, 0x91, 0x06, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, + 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x47, + 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x74, + 0x6f, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, - 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x17, 0x2e, 0x77, 0x73, - 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x77, 0x73, 0x6d, - 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x54, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x65, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0b, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x77, 0x73, - 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0c, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, - 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, - 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x55, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x42, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x17, 0x2e, 0x77, + 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x77, 0x73, + 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, + 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x19, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, + 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x77, + 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0c, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, + 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x55, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x77, 0x73, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, + 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/components/ws-manager-api/typescript/src/core_pb.d.ts b/components/ws-manager-api/typescript/src/core_pb.d.ts index 2cb43d98a9a859..a9ce50a4f763ac 100644 --- a/components/ws-manager-api/typescript/src/core_pb.d.ts +++ b/components/ws-manager-api/typescript/src/core_pb.d.ts @@ -128,6 +128,8 @@ export namespace StartWorkspaceRequest { export class StartWorkspaceResponse extends jspb.Message { getUrl(): string; setUrl(value: string): StartWorkspaceResponse; + getOwnerToken(): string; + setOwnerToken(value: string): StartWorkspaceResponse; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): StartWorkspaceResponse.AsObject; @@ -142,6 +144,7 @@ export class StartWorkspaceResponse extends jspb.Message { export namespace StartWorkspaceResponse { export type AsObject = { url: string, + ownerToken: string, } } diff --git a/components/ws-manager-api/typescript/src/core_pb.js b/components/ws-manager-api/typescript/src/core_pb.js index 9c2e1257d62af6..5a083cae4fa8bb 100644 --- a/components/ws-manager-api/typescript/src/core_pb.js +++ b/components/ws-manager-api/typescript/src/core_pb.js @@ -1565,7 +1565,8 @@ proto.wsman.StartWorkspaceResponse.prototype.toObject = function(opt_includeInst */ proto.wsman.StartWorkspaceResponse.toObject = function(includeInstance, msg) { var f, obj = { - url: jspb.Message.getFieldWithDefault(msg, 1, "") + url: jspb.Message.getFieldWithDefault(msg, 1, ""), + ownerToken: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { @@ -1606,6 +1607,10 @@ proto.wsman.StartWorkspaceResponse.deserializeBinaryFromReader = function(msg, r var value = /** @type {string} */ (reader.readString()); msg.setUrl(value); break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setOwnerToken(value); + break; default: reader.skipField(); break; @@ -1642,6 +1647,13 @@ proto.wsman.StartWorkspaceResponse.serializeBinaryToWriter = function(message, w f ); } + f = message.getOwnerToken(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } }; @@ -1663,6 +1675,24 @@ proto.wsman.StartWorkspaceResponse.prototype.setUrl = function(value) { }; +/** + * optional string owner_token = 2; + * @return {string} + */ +proto.wsman.StartWorkspaceResponse.prototype.getOwnerToken = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.wsman.StartWorkspaceResponse} returns this + */ +proto.wsman.StartWorkspaceResponse.prototype.setOwnerToken = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + diff --git a/components/ws-manager/pkg/manager/manager.go b/components/ws-manager/pkg/manager/manager.go index e01165768d2bac..a23d216e4ed5a3 100644 --- a/components/ws-manager/pkg/manager/manager.go +++ b/components/ws-manager/pkg/manager/manager.go @@ -190,7 +190,10 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq span.LogKV("event", "pod created") // all workspaces get a service now - okResponse := &api.StartWorkspaceResponse{Url: startContext.WorkspaceURL} + okResponse := &api.StartWorkspaceResponse{ + Url: startContext.WorkspaceURL, + OwnerToken: startContext.OwnerToken, + } // mandatory Theia service servicePrefix := getServicePrefix(req) diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden index f4d927467c8495..f064f8ce682683 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden @@ -169,7 +169,7 @@ "failureThreshold": 600 }, "terminationMessagePolicy": "File", - "imagePullPolicy": "Always", + "imagePullPolicy": "IfNotPresent", "securityContext": { "capabilities": { "add": [ diff --git a/dev/gpctl/cmd/imagebuilds-build.go b/dev/gpctl/cmd/imagebuilds-build.go index f33c81b60173cf..d55b783f9d873f 100644 --- a/dev/gpctl/cmd/imagebuilds-build.go +++ b/dev/gpctl/cmd/imagebuilds-build.go @@ -64,6 +64,12 @@ var imagebuildsBuildCmd = &cobra.Command{ if err != nil { log.Fatal(err) } + b, _ = marshaler.Marshal(&source) + fmt.Println("actual config:") + fmt.Fprint(os.Stdout, string(b)) + fmt.Println() + + forceRebuild, _ := cmd.Flags().GetBool("force-rebuild") ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -75,7 +81,8 @@ var imagebuildsBuildCmd = &cobra.Command{ defer conn.Close() br, err := client.Build(ctx, &builder.BuildRequest{ - Source: &source, + Source: &source, + ForceRebuild: forceRebuild, }) if err != nil { log.Fatal(err) @@ -105,17 +112,19 @@ var imagebuildsBuildCmd = &cobra.Command{ log.Fatal(err) } log.Info("listening for build logs") - buildMessage, logs := make(chan builder.BuildResponse), make(chan []byte) + buildMessage, logs := make(chan *builder.BuildResponse), make(chan []byte) go func() { r, err := br.Recv() if err != nil { if err != io.EOF { log.Fatal(err) + } else { + log.Info("logs ended") } return } - buildMessage <- *r + buildMessage <- r }() go func() { for { @@ -154,4 +163,5 @@ func init() { imagebuildsCmd.AddCommand(imagebuildsBuildCmd) imagebuildsBuildCmd.Flags().Bool("censor", false, "censor the log output") + imagebuildsBuildCmd.Flags().Bool("force-rebuild", false, "force an image build even if the image exists already") } diff --git a/dev/gpctl/cmd/imagebuilds.go b/dev/gpctl/cmd/imagebuilds.go index d86b2ba80acd69..87971db8918f9e 100644 --- a/dev/gpctl/cmd/imagebuilds.go +++ b/dev/gpctl/cmd/imagebuilds.go @@ -26,6 +26,7 @@ var imagebuildsCmd = &cobra.Command{ func init() { imagebuildsCmd.PersistentFlags().StringP("tls", "t", "", "TLS certificate when connecting to a secured gRPC endpoint") + imagebuildsCmd.PersistentFlags().Bool("mk3", true, "use image-builder mk3") rootCmd.AddCommand(imagebuildsCmd) } @@ -40,8 +41,13 @@ func getImagebuildsClient(ctx context.Context) (*grpc.ClientConn, api.ImageBuild return nil, nil, err } + comp := "image-builder" + if mk3, _ := imagebuildsCmd.PersistentFlags().GetBool("mk3"); mk3 { + comp = "image-builder-mk3" + } + port := "20202:8080" - podName, err := util.FindAnyPodForComponent(clientSet, namespace, "image-builder") + podName, err := util.FindAnyPodForComponent(clientSet, namespace, comp) if err != nil { return nil, nil, err } From 6a7b5422cf3373a318515e62a1d1d199214c93b5 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Mon, 19 Jul 2021 16:05:49 +0000 Subject: [PATCH 10/15] [image-builder-mk3] Handle refs without tag e.g. `gitpod/workspace-full` --- components/image-builder-mk3/go.mod | 3 +- .../image-builder-mk3/pkg/resolve/resolve.go | 38 +++++-- .../pkg/resolve/resolve_test.go | 107 ++++++++++++++++++ 3 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 components/image-builder-mk3/pkg/resolve/resolve_test.go diff --git a/components/image-builder-mk3/go.mod b/components/image-builder-mk3/go.mod index d23c74903d8db9..b27be12a323723 100644 --- a/components/image-builder-mk3/go.mod +++ b/components/image-builder-mk3/go.mod @@ -19,10 +19,11 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/hashicorp/go-retryablehttp v0.7.0 github.com/mattn/go-isatty v0.0.9 + github.com/opencontainers/go-digest v1.0.0 + github.com/opencontainers/image-spec v1.0.1 github.com/opentracing/opentracing-go v1.2.0 github.com/prometheus/client_golang v1.11.0 github.com/spf13/cobra v0.0.5 - golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea // indirect google.golang.org/grpc v1.38.0 diff --git a/components/image-builder-mk3/pkg/resolve/resolve.go b/components/image-builder-mk3/pkg/resolve/resolve.go index 1a599922621ed5..0b6aaf32868db4 100644 --- a/components/image-builder-mk3/pkg/resolve/resolve.go +++ b/components/image-builder-mk3/pkg/resolve/resolve.go @@ -15,6 +15,7 @@ import ( "github.com/gitpod-io/gitpod/common-go/tracing" "github.com/gitpod-io/gitpod/image-builder/pkg/auth" + "github.com/containerd/containerd/remotes" dockerremote "github.com/containerd/containerd/remotes/docker" "github.com/docker/distribution/reference" "github.com/opentracing/opentracing-go" @@ -25,10 +26,12 @@ import ( var ErrNotFound = fmt.Errorf("not found") // StandaloneRefResolver can resolve image references without a Docker daemon -type StandaloneRefResolver struct{} +type StandaloneRefResolver struct { + ResolverFactory func() remotes.Resolver +} // Resolve resolves a mutable Docker tag to its absolute digest form by asking the corresponding Docker registry -func (*StandaloneRefResolver) Resolve(ctx context.Context, ref string, opts ...DockerRefResolverOption) (res string, err error) { +func (sr *StandaloneRefResolver) Resolve(ctx context.Context, ref string, opts ...DockerRefResolverOption) (res string, err error) { span, ctx := opentracing.StartSpanFromContext(ctx, "StandaloneRefResolver.Resolve") defer func() { var rerr error @@ -40,15 +43,20 @@ func (*StandaloneRefResolver) Resolve(ctx context.Context, ref string, opts ...D options := getOptions(opts) - r := dockerremote.NewResolver(dockerremote.ResolverOptions{ - Authorizer: dockerremote.NewDockerAuthorizer(dockerremote.WithAuthCreds(func(host string) (username, password string, err error) { - if options.Auth == nil { - return - } - - return options.Auth.Username, options.Auth.Password, nil - })), - }) + var r remotes.Resolver + if sr.ResolverFactory == nil { + r = dockerremote.NewResolver(dockerremote.ResolverOptions{ + Authorizer: dockerremote.NewDockerAuthorizer(dockerremote.WithAuthCreds(func(host string) (username, password string, err error) { + if options.Auth == nil { + return + } + + return options.Auth.Username, options.Auth.Password, nil + })), + }) + } else { + r = sr.ResolverFactory() + } // The ref may be what Docker calls a "familiar" name, e.g. ubuntu:latest instead of docker.io/library/ubuntu:latest. // To make this a valid digested form we first need to normalize that familiar name. @@ -63,6 +71,14 @@ func (*StandaloneRefResolver) Resolve(ctx context.Context, ref string, opts ...D return ref, nil } + // Some users don't specify a tag, and Docker assumes "latest" - we follow the same convention + if _, ok := pref.(reference.Tagged); !ok { + pref, err = reference.WithTag(pref, "latest") + if err != nil { + return "", err + } + } + nref := pref.String() span.LogKV("normalized-ref", nref) diff --git a/components/image-builder-mk3/pkg/resolve/resolve_test.go b/components/image-builder-mk3/pkg/resolve/resolve_test.go new file mode 100644 index 00000000000000..015bb7eb036c78 --- /dev/null +++ b/components/image-builder-mk3/pkg/resolve/resolve_test.go @@ -0,0 +1,107 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package resolve_test + +import ( + "context" + "fmt" + "testing" + + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/remotes" + "github.com/gitpod-io/gitpod/image-builder/pkg/resolve" + "github.com/google/go-cmp/cmp" + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +func TestStandaloneResolver(t *testing.T) { + defaultRefs := map[string]fakeResolverEntry{ + "docker.io/gitpod-io/workspace-full:latest": { + Name: "docker.io/gitpod-io/workspace-full:latest", + Desc: ocispec.Descriptor{ + Digest: digest.FromBytes([]byte("hello world")), + }, + }, + } + type Expectation struct { + Res string + Err string + } + tests := []struct { + Name string + Refs map[string]fakeResolverEntry + Ref string + Expectation Expectation + }{ + { + Name: "no host", + Refs: defaultRefs, + Ref: "gitpod-io/workspace-full:latest", + Expectation: Expectation{Res: "docker.io/gitpod-io/workspace-full:latest"}, + }, + { + Name: "no tag", + Refs: defaultRefs, + Ref: "docker.io/gitpod-io/workspace-full", + Expectation: Expectation{Res: "docker.io/gitpod-io/workspace-full:latest"}, + }, + { + Name: "with digest", + Refs: defaultRefs, + Ref: "docker.io/gitpod-io/workspace-full:latest@sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", + Expectation: Expectation{Res: "docker.io/gitpod-io/workspace-full:latest@sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"}, + }, + { + Name: "not found", + Refs: defaultRefs, + Ref: "this/does/not/exist", + Expectation: Expectation{Err: "not found"}, + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + sr := resolve.StandaloneRefResolver{ + func() remotes.Resolver { + return &fakeResolver{Refs: test.Refs} + }, + } + res, err := sr.Resolve(context.Background(), test.Ref) + act := Expectation{Res: res} + if err != nil { + act.Err = err.Error() + } + + if diff := cmp.Diff(test.Expectation, act); diff != "" { + t.Errorf("StandaloneRefResolver.Resolve() mismatch (-want +got):\n%s", diff) + } + }) + } +} + +type fakeResolverEntry struct { + Name string + Desc ocispec.Descriptor +} + +type fakeResolver struct { + Refs map[string]fakeResolverEntry +} + +func (f *fakeResolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) { + c, found := f.Refs[ref] + if !found { + return "", desc, errdefs.ErrNotFound + } + + return c.Name, c.Desc, nil +} +func (*fakeResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) { + return nil, fmt.Errorf("not supporter") +} +func (*fakeResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) { + return nil, fmt.Errorf("not supporter") +} From 106733f87a4e3a4856e375f373695ff82054620b Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Tue, 20 Jul 2021 15:52:05 +0000 Subject: [PATCH 11/15] [server] Support configuring image builder service --- components/server/src/container-module.ts | 5 +++-- components/server/src/env.ts | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/components/server/src/container-module.ts b/components/server/src/container-module.ts index ac04e35d7474bc..3942da61184b73 100644 --- a/components/server/src/container-module.ts +++ b/components/server/src/container-module.ts @@ -128,8 +128,9 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo } ).inSingletonScope(); - bind(ImageBuilderClientConfig).toDynamicValue(() => { - return { address: "image-builder-mk3:8080" } + bind(ImageBuilderClientConfig).toDynamicValue(ctx => { + const env = ctx.container.get(Env); + return { address: env.imageBuilderAddress } }); bind(CachingImageBuilderClientProvider).toSelf().inSingletonScope(); bind(ImageBuilderClientProvider).toService(CachingImageBuilderClientProvider); diff --git a/components/server/src/env.ts b/components/server/src/env.ts index d7a366ae002c0e..bf45be5ab126f4 100644 --- a/components/server/src/env.ts +++ b/components/server/src/env.ts @@ -204,5 +204,7 @@ export class Env extends AbstractComponentEnv { readonly runDbDeleter: boolean = getEnvVar('RUN_DB_DELETER', 'false') === 'true'; - readonly oauthServerJWTSecret = getEnvVar("OAUTH_SERVER_JWT_SECRET") + readonly oauthServerJWTSecret = getEnvVar("OAUTH_SERVER_JWT_SECRET"); + + readonly imageBuilderAddress = getEnvVar('IMAGE_BUILDER_SERVICE', "image-builder-mk3:8080"); } From 0a4ae88fae4142c0376529539adf2cd842e1a455 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Tue, 20 Jul 2021 19:48:24 +0000 Subject: [PATCH 12/15] [ws-proxy] Disable compression on supervisor API to avoid "stuttering log output" in image-builder --- .../pkg/orchestrator/monitor.go | 25 ++++++++----------- components/ws-proxy/pkg/proxy/routes.go | 15 ++++++++--- components/ws-proxy/pkg/proxy/routes_test.go | 6 ----- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/components/image-builder-mk3/pkg/orchestrator/monitor.go b/components/image-builder-mk3/pkg/orchestrator/monitor.go index 7f8610a56710f7..faa49a17c323c4 100644 --- a/components/image-builder-mk3/pkg/orchestrator/monitor.go +++ b/components/image-builder-mk3/pkg/orchestrator/monitor.go @@ -5,7 +5,6 @@ package orchestrator import ( - "bufio" "context" "encoding/json" "errors" @@ -325,24 +324,20 @@ func listenToHeadlessLogs(ctx context.Context, url, authToken string, callback l } `json:"result"` } - r := bufio.NewScanner(resp.Body) - for r.Scan() { - err := json.Unmarshal(r.Bytes(), &line) + dec := json.NewDecoder(resp.Body) + for err == nil { + err = dec.Decode(&line) + if errors.Is(err, io.EOF) { + // EOF is not an error in this case + err = nil + break + } if err != nil { - callback(nil, err) - continue + break } + callback(line.Result.Data, nil) } - err = r.Err() - if errors.Is(err, io.EOF) { - // EOF is not an error in this case - err = nil - return - } - if err != nil { - return - } } func findTaskLogURL(ctx context.Context, ideURL, authToken string) (taskLogURL string, err error) { diff --git a/components/ws-proxy/pkg/proxy/routes.go b/components/ws-proxy/pkg/proxy/routes.go index 97c91aa3f7fb0e..9c34d8e1e1d024 100644 --- a/components/ws-proxy/pkg/proxy/routes.go +++ b/components/ws-proxy/pkg/proxy/routes.go @@ -71,7 +71,6 @@ type RouteHandler = func(r *mux.Router, config *RouteHandlerConfig) // installWorkspaceRoutes configures routing of workspace and IDE requests func installWorkspaceRoutes(r *mux.Router, config *RouteHandlerConfig, ip WorkspaceInfoProvider) { r.Use(logHandler) - r.Use(handlers.CompressHandler) // Note: the order of routes defines their priority. // Routes registered first have priority over those that come afterwards. @@ -80,6 +79,7 @@ func installWorkspaceRoutes(r *mux.Router, config *RouteHandlerConfig, ip Worksp // The favicon warants special handling, because we pull that from the supervisor frontend // rather than the IDE. faviconRouter := r.Path("/favicon.ico").Subrouter() + faviconRouter.Use(handlers.CompressHandler) faviconRouter.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { req.URL.Path = "/_supervisor/frontend/favicon.ico" @@ -97,18 +97,25 @@ func installWorkspaceRoutes(r *mux.Router, config *RouteHandlerConfig, ip Worksp routes.HandleDirectIDERoute(r.PathPrefix(pp)) } - routes.HandleSupervisorFrontendRoute(r.PathPrefix("/_supervisor/frontend")) + routes.HandleSupervisorFrontendRoute(enableCompression(r).PathPrefix("/_supervisor/frontend")) + routes.HandleDirectSupervisorRoute(r.PathPrefix("/_supervisor/v1/status/supervisor"), false) routes.HandleDirectSupervisorRoute(r.PathPrefix("/_supervisor/v1/status/ide"), false) routes.HandleDirectSupervisorRoute(r.PathPrefix("/_supervisor/v1"), true) routes.HandleDirectSupervisorRoute(r.PathPrefix("/_supervisor"), true) - routes.HandleDirectIDERoute(r.MatcherFunc(func(req *http.Request, m *mux.RouteMatch) bool { + routes.HandleDirectIDERoute(enableCompression(r).MatcherFunc(func(req *http.Request, m *mux.RouteMatch) bool { // this handles all foreign (none-IDE) content return m.Vars != nil && m.Vars[foreignOriginIdentifier] != "" })) - routes.HandleRoot(r.NewRoute()) + routes.HandleRoot(enableCompression(r).NewRoute()) +} + +func enableCompression(r *mux.Router) *mux.Router { + res := r.NewRoute().Subrouter() + res.Use(handlers.CompressHandler) + return res } func newIDERoutes(config *RouteHandlerConfig, ip WorkspaceInfoProvider) *ideRoutes { diff --git a/components/ws-proxy/pkg/proxy/routes_test.go b/components/ws-proxy/pkg/proxy/routes_test.go index 029470a1e2eae7..3eb0506dda53a5 100644 --- a/components/ws-proxy/pkg/proxy/routes_test.go +++ b/components/ws-proxy/pkg/proxy/routes_test.go @@ -362,7 +362,6 @@ func TestRoutes(t *testing.T) { Header: http.Header{ "Content-Length": {"50"}, "Content-Type": {"text/plain; charset=utf-8"}, - "Vary": {"Accept-Encoding"}, }, Body: "supervisor hit: /_supervisor/v1/status/supervisor\n", }, @@ -377,7 +376,6 @@ func TestRoutes(t *testing.T) { Header: http.Header{ "Content-Length": {"43"}, "Content-Type": {"text/plain; charset=utf-8"}, - "Vary": {"Accept-Encoding"}, }, Body: "supervisor hit: /_supervisor/v1/status/ide\n", }, @@ -389,9 +387,6 @@ func TestRoutes(t *testing.T) { ), Expectation: Expectation{ Status: http.StatusUnauthorized, - Header: http.Header{ - "Vary": {"Accept-Encoding"}, - }, }, }, { @@ -405,7 +400,6 @@ func TestRoutes(t *testing.T) { Header: http.Header{ "Content-Length": {"47"}, "Content-Type": {"text/plain; charset=utf-8"}, - "Vary": {"Accept-Encoding"}, }, Body: "supervisor hit: /_supervisor/v1/status/content\n", }, From 15988767a13d84f10d94dc9b52fa099421ba6cd2 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Tue, 20 Jul 2021 20:03:17 +0000 Subject: [PATCH 13/15] [image-builder-mk3] Improve in-build log output --- components/image-builder-bob/cmd/root.go | 2 +- .../image-builder-bob/pkg/builder/builder.go | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/components/image-builder-bob/cmd/root.go b/components/image-builder-bob/cmd/root.go index 86197463aeefe5..ccf2f7d0c014a6 100644 --- a/components/image-builder-bob/cmd/root.go +++ b/components/image-builder-bob/cmd/root.go @@ -20,7 +20,7 @@ var rootCmd = &cobra.Command{ // Execute runs the root command func Execute() { - log.Init("bob", "", true, true) + log.Init("bob", "", false, false) if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) diff --git a/components/image-builder-bob/pkg/builder/builder.go b/components/image-builder-bob/pkg/builder/builder.go index 76124cae74fc3b..52df20b00f129e 100644 --- a/components/image-builder-bob/pkg/builder/builder.go +++ b/components/image-builder-bob/pkg/builder/builder.go @@ -6,6 +6,7 @@ package builder import ( "context" + "errors" "fmt" "io/ioutil" "os" @@ -21,7 +22,6 @@ import ( "github.com/moby/buildkit/session" "github.com/moby/buildkit/util/progress/progressui" "golang.org/x/sync/errgroup" - "golang.org/x/xerrors" ) const ( @@ -79,7 +79,7 @@ func (b *Builder) buildBaseLayer(ctx context.Context, cl *client.Client) error { return nil } - fmt.Printf("waiting for build context\n") + log.Info("waiting for build context") waitctx, cancel := context.WithTimeout(ctx, 30*time.Minute) defer cancel() err := waitForBuildContext(waitctx) @@ -87,7 +87,7 @@ func (b *Builder) buildBaseLayer(ctx context.Context, cl *client.Client) error { return err } - fmt.Printf("building base image\n") + log.Info("building base image") var sess []session.Attachable if baselayerAuth := b.Config.BaseLayerAuth; baselayerAuth != "" { @@ -120,6 +120,12 @@ func (b *Builder) buildBaseLayer(ctx context.Context, cl *client.Client) error { eg.Go(func() error { _, err := cl.Solve(ectx, nil, solveOpt, ch) if err != nil { + // buildkit errors are wrapped to contain the stack - that does not make for a pretty + // sight when printing it to the user. + if u := errors.Unwrap(err); u != nil { + return u + } + return err } return nil @@ -158,6 +164,12 @@ func (b *Builder) buildBaseLayer(ctx context.Context, cl *client.Client) error { eg.Go(func() error { _, err := cl.Solve(ectx, nil, solveOpt, ch) if err != nil { + // buildkit errors are wrapped to contain the stack - that does not make for a pretty + // sight when printing it to the user. + if u := errors.Unwrap(err); u != nil { + return u + } + return err } return nil @@ -171,7 +183,7 @@ func (b *Builder) buildBaseLayer(ctx context.Context, cl *client.Client) error { return err } - fmt.Printf("base image done\n") + log.Info("base image done") return err } @@ -212,7 +224,7 @@ func (b *Builder) buildGPLayer(ctx context.Context, cl *client.Client) (err erro eg.Go(func() error { _, err := cl.Solve(ctx, nil, solveOpt, ch) if err != nil { - return xerrors.Errorf("cannot build Gitpod layer: %w", err) + return fmt.Errorf("cannot build Gitpod layer: %w", err) } return nil }) From 36cca6729e76faa83a14c7bf229a47d9a52309b0 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Wed, 21 Jul 2021 15:59:19 +0000 Subject: [PATCH 14/15] [image-builder-mk3] Rollback to buildkit v0.8.3 because we don't support mounting proc through procfd --- components/image-builder-bob/leeway.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/image-builder-bob/leeway.Dockerfile b/components/image-builder-bob/leeway.Dockerfile index 7b9c0b301ac26a..4a137b667a6055 100644 --- a/components/image-builder-bob/leeway.Dockerfile +++ b/components/image-builder-bob/leeway.Dockerfile @@ -2,7 +2,7 @@ # Licensed under the GNU Affero General Public License (AGPL). # See License-AGPL.txt in the project root for license information. -FROM moby/buildkit:v0.9.0 +FROM moby/buildkit:v0.8.3 USER root RUN apk --no-cache add sudo bash \ From e520320f09d79730894955a55477b7bca5b9edcb Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Wed, 21 Jul 2021 16:12:11 +0000 Subject: [PATCH 15/15] [ws-manager] Properly stop all headless workspaces not just prebuilds --- components/ws-manager/pkg/manager/status.go | 10 +---- .../status_headless_STOPPING00.golden | 38 +++++++++++++++++++ .../testdata/status_headless_STOPPING00.json | 1 + 3 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.golden create mode 100644 components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.json diff --git a/components/ws-manager/pkg/manager/status.go b/components/ws-manager/pkg/manager/status.go index b5a911a2aaefea..f37af32dfc82dc 100644 --- a/components/ws-manager/pkg/manager/status.go +++ b/components/ws-manager/pkg/manager/status.go @@ -576,12 +576,6 @@ func extractFailure(wso workspaceObjects) (string, *api.WorkspacePhase) { return reason, nil } - tpe, err := wso.WorkspaceType() - if err != nil { - log.WithError(err).Warn("cannot determine workspace type - assuming this is a regular") - tpe = api.WorkspaceType_REGULAR - } - status := pod.Status if status.Phase == corev1.PodFailed && (status.Reason != "" || status.Message != "") { // Don't force the phase to UNKNONWN here to leave a chance that we may detect the actual phase of @@ -621,8 +615,8 @@ func extractFailure(wso workspaceObjects) (string, *api.WorkspacePhase) { return fmt.Sprintf("container %s ran with an error: exit code %d", cs.Name, terminationState.ExitCode), nil } } else if terminationState.Reason == "Completed" { - if tpe == api.WorkspaceType_PREBUILD { - // default way for prebuilds to be done + if wso.IsWorkspaceHeadless() { + // default way for headless workspaces to be done return "", nil } return fmt.Sprintf("container %s completed; containers of a workspace pod are not supposed to do that", cs.Name), nil diff --git a/components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.golden b/components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.golden new file mode 100644 index 00000000000000..1edf61336d03cf --- /dev/null +++ b/components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.golden @@ -0,0 +1,38 @@ +{ + "status": { + "id": "0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b", + "metadata": { + "owner": "image-builder", + "meta_id": "0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b", + "started_at": { + "seconds": 1626883365 + }, + "annotations": { + "baseref": "eu.gcr.io/gitpod-core-dev/registry/base-images:d04c64d5d108632a1768e4af9c3a8a3e6a87c96d2566fb1b0d1aec2fd630e8bd", + "ref": "eu.gcr.io/gitpod-core-dev/registry/workspace-images:a277dab62e839192eb320da283d4e8488a2b2f46fceb4677a7d571431e239aa5" + } + }, + "spec": { + "workspace_image": "eu.gcr.io/gitpod-core-dev/build/image-builder-mk3/bob:2cf747867ff804ee0edc0a2607cb8ca06242083a", + "ide_image": "eu.gcr.io/gitpod-core-dev/build/image-builder-mk3/bob:2cf747867ff804ee0edc0a2607cb8ca06242083a", + "headless": true, + "url": "https://0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.ws-dev.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com", + "type": 4, + "timeout": "1h0m0s" + }, + "phase": 5, + "conditions": { + "service_exists": 1, + "deployed": 1 + }, + "message": "headless workspace is stopping", + "runtime": { + "node_name": "gke-dev-workload-1-49d27f81-8s5c", + "pod_name": "imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b", + "node_ip": "10.132.0.17" + }, + "auth": { + "owner_token": "osZStmqg3TI0NrkLe3edax9bYCknXWtr" + } + } +} \ No newline at end of file diff --git a/components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.json b/components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.json new file mode 100644 index 00000000000000..8d9f6e0d372873 --- /dev/null +++ b/components/ws-manager/pkg/manager/testdata/status_headless_STOPPING00.json @@ -0,0 +1 @@ +{"pod":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/pods/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","uid":"a87d12cb-d5ef-4dad-a1fa-44284e994f07","resourceVersion":"237707407","creationTimestamp":"2021-07-21T16:02:45Z","labels":{"app":"gitpod","component":"workspace","gitpod.io/networkpolicy":"default","gpwsman":"true","headless":"true","metaID":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","owner":"image-builder","workspaceID":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","workspaceType":"imagebuild"},"annotations":{"cluster-autoscaler.kubernetes.io/safe-to-evict":"false","cni.projectcalico.org/podIP":"","cni.projectcalico.org/podIPs":"","container.apparmor.security.beta.kubernetes.io/workspace":"unconfined","gitpod.io/annotation.baseref":"eu.gcr.io/gitpod-core-dev/registry/base-images:d04c64d5d108632a1768e4af9c3a8a3e6a87c96d2566fb1b0d1aec2fd630e8bd","gitpod.io/annotation.ref":"eu.gcr.io/gitpod-core-dev/registry/workspace-images:a277dab62e839192eb320da283d4e8488a2b2f46fceb4677a7d571431e239aa5","gitpod.io/nodeName":"gke-dev-workload-1-49d27f81-8s5c","gitpod.io/requiredNodeServices":"ws-daemon,registry-facade","gitpod/admission":"admit_owner_only","gitpod/contentInitializer":"[redacted]","gitpod/customTimeout":"1h0m0s","gitpod/id":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","gitpod/imageSpec":"Cl5ldS5nY3IuaW8vZ2l0cG9kLWNvcmUtZGV2L2J1aWxkL2ltYWdlLWJ1aWxkZXItbWszL2JvYjoyY2Y3NDc4NjdmZjgwNGVlMGVkYzBhMjYwN2NiOGNhMDYyNDIwODNhEl5ldS5nY3IuaW8vZ2l0cG9kLWNvcmUtZGV2L2J1aWxkL2ltYWdlLWJ1aWxkZXItbWszL2JvYjoyY2Y3NDc4NjdmZjgwNGVlMGVkYzBhMjYwN2NiOGNhMDYyNDIwODNh","gitpod/never-ready":"true","gitpod/ownerToken":"osZStmqg3TI0NrkLe3edax9bYCknXWtr","gitpod/servicePrefix":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","gitpod/url":"https://0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.ws-dev.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com","kubernetes.io/psp":"staging-cw-imgbuilder-mk3-rebase-ns-workspace","prometheus.io/path":"/metrics","prometheus.io/port":"23000","prometheus.io/scrape":"true","seccomp.security.alpha.kubernetes.io/pod":"localhost/workspace_default_cw-imgbuilder-mk3-rebase.100.json"},"finalizers":["gitpod.io/finalizer"],"managedFields":[{"manager":"calico","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:02:46Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{"f:cni.projectcalico.org/podIP":{},"f:cni.projectcalico.org/podIPs":{}}}}},{"manager":"ws-manager","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:03:04Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:cluster-autoscaler.kubernetes.io/safe-to-evict":{},"f:container.apparmor.security.beta.kubernetes.io/workspace":{},"f:gitpod.io/annotation.baseref":{},"f:gitpod.io/annotation.ref":{},"f:gitpod.io/nodeName":{},"f:gitpod.io/requiredNodeServices":{},"f:gitpod/admission":{},"f:gitpod/contentInitializer":{},"f:gitpod/customTimeout":{},"f:gitpod/id":{},"f:gitpod/imageSpec":{},"f:gitpod/never-ready":{},"f:gitpod/ownerToken":{},"f:gitpod/servicePrefix":{},"f:gitpod/url":{},"f:prometheus.io/path":{},"f:prometheus.io/port":{},"f:prometheus.io/scrape":{},"f:seccomp.security.alpha.kubernetes.io/pod":{}},"f:finalizers":{".":{},"v:\"gitpod.io/finalizer\"":{}},"f:labels":{".":{},"f:app":{},"f:component":{},"f:gitpod.io/networkpolicy":{},"f:gpwsman":{},"f:headless":{},"f:metaID":{},"f:owner":{},"f:workspaceID":{},"f:workspaceType":{}}},"f:spec":{"f:automountServiceAccountToken":{},"f:containers":{"k:{\"name\":\"workspace\"}":{".":{},"f:command":{},"f:env":{".":{},"k:{\"name\":\"BOB_AUTH_KEY\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_BASELAYER_AUTH\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_BASE_REF\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_BUILD_BASE\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_CONTEXT_DIR\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_DOCKERFILE_PATH\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_GPLAYER_AUTH\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"BOB_TARGET_REF\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_CLI_APITOKEN\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_HEADLESS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_HOST\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_INSTANCE_ID\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_INTERVAL\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_MEMORY\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_REPO_ROOT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_TASKS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_THEIA_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_WORKSPACE_CLUSTER_HOST\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_WORKSPACE_ID\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"GITPOD_WORKSPACE_URL\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"THEIA_MINI_BROWSER_HOST_PATTERN\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"THEIA_SUPERVISOR_ENDPOINT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"THEIA_WEBVIEW_EXTERNAL_ENDPOINT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"THEIA_WORKSPACE_ROOT\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":23000,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:readinessProbe":{".":{},"f:failureThreshold":{},"f:httpGet":{".":{},"f:path":{},"f:port":{},"f:scheme":{}},"f:periodSeconds":{},"f:successThreshold":{},"f:timeoutSeconds":{}},"f:resources":{".":{},"f:limits":{".":{},"f:cpu":{},"f:memory":{}},"f:requests":{".":{},"f:cpu":{},"f:ephemeral-storage":{},"f:memory":{}}},"f:securityContext":{".":{},"f:allowPrivilegeEscalation":{},"f:capabilities":{".":{},"f:add":{},"f:drop":{}},"f:privileged":{},"f:readOnlyRootFilesystem":{},"f:runAsGroup":{},"f:runAsNonRoot":{},"f:runAsUser":{}},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{},"f:volumeMounts":{".":{},"k:{\"mountPath\":\"/.workspace\"}":{".":{},"f:mountPath":{},"f:mountPropagation":{},"f:name":{}},"k:{\"mountPath\":\"/workspace\"}":{".":{},"f:mountPath":{},"f:mountPropagation":{},"f:name":{}}}}},"f:dnsConfig":{".":{},"f:nameservers":{}},"f:dnsPolicy":{},"f:enableServiceLinks":{},"f:imagePullSecrets":{".":{},"k:{\"name\":\"gcp-sa-registry-auth\"}":{".":{},"f:name":{}}},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{".":{},"f:fsGroup":{},"f:seccompProfile":{"f:localhostProfile":{},"f:type":{}},"f:supplementalGroups":{}},"f:serviceAccount":{},"f:serviceAccountName":{},"f:terminationGracePeriodSeconds":{},"f:tolerations":{},"f:volumes":{".":{},"k:{\"name\":\"daemon-mount\"}":{".":{},"f:hostPath":{".":{},"f:path":{},"f:type":{}},"f:name":{}},"k:{\"name\":\"vol-this-workspace\"}":{".":{},"f:hostPath":{".":{},"f:path":{},"f:type":{}},"f:name":{}}}}}},{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:08:00Z","fieldsType":"FieldsV1","fieldsV1":{"f:status":{"f:conditions":{"k:{\"type\":\"ContainersReady\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Initialized\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:containerStatuses":{},"f:hostIP":{},"f:phase":{},"f:podIP":{},"f:podIPs":{".":{},"k:{\"ip\":\"10.60.22.132\"}":{".":{},"f:ip":{}}},"f:startTime":{}}}}]},"spec":{"volumes":[{"name":"vol-this-workspace","hostPath":{"path":"/mnt/disks/ssd0/workspaces/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","type":"DirectoryOrCreate"}},{"name":"daemon-mount","hostPath":{"path":"/mnt/disks/ssd0/workspaces/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b-daemon","type":"DirectoryOrCreate"}}],"containers":[{"name":"workspace","image":"reg.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com:30815/remote/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","command":["/.supervisor/workspacekit","ring0"],"ports":[{"containerPort":23000,"protocol":"TCP"}],"env":[{"name":"GITPOD_REPO_ROOT","value":"/workspace"},{"name":"GITPOD_CLI_APITOKEN","value":"TUf744QntqioSRIrnIVpic9CpLnKQCbj"},{"name":"GITPOD_WORKSPACE_ID","value":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b"},{"name":"GITPOD_INSTANCE_ID","value":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b"},{"name":"GITPOD_THEIA_PORT","value":"23000"},{"name":"THEIA_WORKSPACE_ROOT","value":"/workspace/workspace"},{"name":"GITPOD_HOST","value":"https://cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com"},{"name":"GITPOD_WORKSPACE_URL","value":"https://0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.ws-dev.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com"},{"name":"GITPOD_WORKSPACE_CLUSTER_HOST","value":"ws-dev.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com"},{"name":"THEIA_SUPERVISOR_ENDPOINT","value":":22999"},{"name":"THEIA_WEBVIEW_EXTERNAL_ENDPOINT","value":"webview-{{hostname}}"},{"name":"THEIA_MINI_BROWSER_HOST_PATTERN","value":"browser-{{hostname}}"},{"name":"BOB_TARGET_REF","value":"eu.gcr.io/gitpod-core-dev/registry/workspace-images:a277dab62e839192eb320da283d4e8488a2b2f46fceb4677a7d571431e239aa5"},{"name":"BOB_BASE_REF","value":"eu.gcr.io/gitpod-core-dev/registry/base-images:d04c64d5d108632a1768e4af9c3a8a3e6a87c96d2566fb1b0d1aec2fd630e8bd"},{"name":"BOB_BUILD_BASE","value":"true"},{"name":"BOB_BASELAYER_AUTH","value":"bI9gBDvDtwGZby8T1Wd3HdjrKz0HH4Kcrdyxtij1"},{"name":"BOB_GPLAYER_AUTH","value":"PetXlerz2kjoa7FPdWuqdaC6o48qmFNCSUlx/DY+VvEh56pB85zB/0xcM2N4haYk3Umoa9OAJvu33AuB9GakbIOxHtF7IqgQUFRD+p2+yM80mWtHcTn13wVrpo2diIH91Ne58Qr+qz8l6q2sXKg/U4YJr0x4kIg1110iKD1r1GklhvlaQuIudUTQdY264ama2FQcrJjpnqaQIYIO4cOhc2lI9y34MGqwSlFfzuqjcKLpt2/XW+CwZxH2h5JKcgmZjcUyClA/GcC1mgJX3b4eqgsravlTloRvMti8IgWK8s4xiOU9qFEFCWcGIXwdj16Abtn5GoWDNFyHFF5Ojss7QzTEx395QnMgLEVxZrkscJc0Afn+ewKXF3oceoIuWe0GmgvbRnzuUv9ftnc7BPWgNq0HXr8J3RBBcnlXSQlcECljq8TW6vtkSDKrOnPeTSLZ12jj+PtmVwDvPCRYevo6TSIluyt6EEpm1aKV9Rt6VuGAFNFZfRLlKx0UivOUzgcUUN0UJ6itBsQKW97o/8sax03PTvcHbP+CtvYYwGXKqF3nO3SQs0eiDhqi0IV4/TvzjvsLm5UFC+VqEzahRMm7fhvoKdmPMBu0kGiFE3bZK4w7s3vWoliWnHS27Mg8GawGySOp1Y8cy15B07Y6tyRcxwJ3dRxYulvEm8w4+9RgGor1w8ScMqZ/GugXhHOUVfDjomTqDhooDLWw7VB3JKqCLlOcZ42cdheHWnEyLtFhDMisESukMfT99cq95L5ZIARTqS2gpcRDro/iiumvwe6Hr+gNtuz/NCA0dKPgst5vLZYzcjJvcHzOSR88iqnottSeuX2NVU5FoqNaMqURcXXvp9oXkrAJ8JILDmE+cMhna+pKK+nbFa7NE8zzvGoxUnZNbPUzu2FT7AXyMPKr5mWOBwQY9Jb7OxQXoqAtCBoAT6pKgan/BkaC02o3kwgt50aYWt0bmdl2/JPoF01+bhbmbIGK6I/B/oOMU5VMXTfHIKg4Q5LJX540JxQB6g4z7wR8eAHLQ3F6GyXcV69xZX64veKXvx3NhZ75lcwjzC9mtUvoXzftM3lsTFwQGlBrzC6wKPGotQJh7dRH8HYKuUdjm/z0xElVKaaNHtMkQ6yNGNQ1lQZpdGDYQwqxMXHd61zolL3JVwovDPax3tNn69mfeAnhnKJ4MQHi+804EO80NrLMJNHxbETdcaE6M/meprmmlsd8Z0ZxSrAcbU4pqNoeSEfC5U2W6DWhP5jiagqml/d7wq2rh8CV1wAct/FLLX/nWC9BejZ2caTTennh3bNpaTfDHDL35+a7+24k74SAw8Py1CsRGqm8LyfwbQEgw4Lihe8k24DA5R3nB+pSFcze4SQhFBWNFK8ZS9MHYWPKEi3ptvCoeTs+fkXuhqDy3pIlkVPJNrP9eCQES7+INgFAUmQ3yuB1YZeev6bjz5mGV+XIV2P12ngz4+y/tTL75+y2QEDC2FWO9rgMC27Q/4WZo+PUIEyf7tLHsOKvvPCJrRIQzBNFCSRg4I6j2A9cK84l6NFKPQhfkzttv8YdsNWClflaDuf5Te3PKPh2pozWmFIeYlufgNFZ7TIEziwFzp9p9emI1O0pVaDlQ0hKeK67GJTNXh5vzYCwBbMSLQECMmClinYHYYS7fMzfmlRwsvKIdeHf2yjCbN8dBhQx7AuLvyiHVNmrBDhPlmB8wbzvAAz8ODz4OiNisXbOJq0+nmok5Jdf1tfuJOnfdKeVwDVRrDkTqUP0W53a34pBdHWctD70o/fVmxxqzJ7R1I6U3YuCYJkTlvvEjCqCbNPKseNBfEAVy/FYpKYj0A7IgILtbVi5SCSPnEAkOnZD1x2yrH0bUhQoBpJ38Je69pkVOnZwpyPvgJFWfKun8WRgdQMzIYA6SrBqRItKOAN7Fd1YHMys8BaJZbwQo7ZuEsnAYwKIS563dc67clKsjbUJ+VkiXeRyUaZiubHweu6vgouSPi8kvZ5aNx98oj+vGUQpoJK1yhZH/siAiPBmf5JIm9qzDM64Y99Biai7Mw4eICCz0qHk4kboS2n1cHePk780o2mpXifVtuc7RK2Rr9UbxQ2PiygFNYZh7mPWc0qCJm/81b/rOP7UQDJuBbNw9U0EslW7uS3Fvl80kvO43SgWxXJTykMJJ3vr94WyAoNagV2e3AB+qCvsCWkn4o7Mwb6EmbobvHBuOHEJVeA4P030B+KCpSLNxwnmZdxJG7NdTjTxXakYV2AEGQLGQuUuYtkMLBBoeQUInNwpJvwslcQCXGn4naVQjCerwip/vMOKaW+vHYhdl8zlg30tjx+oUuyx86LNcv3sNpZapvJvo9UoyfMxmwVv4X/GGkB73v1bRJbH5BJ5+5v+phLvYRMc3rsrSk76Us1hKVyKAfK14m4T+RqAprplf8k1crdaniOnebFRJCWg0QujgS+2EUBpIoAZu184zTirARHs2ip9WikVLXD3gqY2dIbrsCsiNLjTAR/pf8Og9e/VjYfszM56de9q9tNBcNM15oA1w60UwSLlyLNIZR8Uum75UICOEGVimsS73P6rFFsmlvIK8Tr+uVsgt8IKhJsyVArrCVGx3cwaVKMNp2XXNfzEUTy6r86pPXvqQEfKhiDgRkf79HLjx0BxVFgpxjMNHUdgsARTK2ElIAsO/sh/WbsvsHByfQZeTR7iDgxxfJQzA1xpnltctQp95tPWbsj2HlzI9rr95/jAUASJcyMA9cWfN5NZWrgkxP//Prc7pMHsmjCNh0PbSVyPTdRWqdxjZXqMPdm0PNQXWEjtkE5R5830JtqhLLToHBHpbCVbmHTUllkFOYnzob9YkrHYdhez/66VDJGNhms2aVi3bu4X2sjo4f8rbP+1dxdi8n/vRf3zaEAW3vy2fASfwvmPN7yFH9Y4mxiezSNdH16y+c2/NOlM8cgGLA1WJX1liFGvFzDNHsjYRX4sHLlx+zuUf/YBqBTGPzxNZz8GOx/7LZhg3ilcqfDl4fChqEDDvSrsXLX88Hv+1St0FpRikIKimUHUx5X0ClVihAkRamm1M9lR9NsxVV6DEGC6JeWmAls/DD+cEUybS+JwQItLz+lbi5kMTibJale+pl5pFg/eNNZQkTPE1GoEf85JZ6moOp6fwqAhBLLCYzcWTYGHKYdknPkvfopB5HFMQi/biBdvbg7N3cYpH/DpfHs2bNAlI8xTn0lxi6ABuie7o4XPpKt1m2eQw3VGYK5n8b22e2aVjIilOwUQmfrdBX2QuOxLg1OVJGAYJkOjmBaAM14bTMaMGSJo0t60EuFydwaiQ9nYVecjploe8I4RCjYLBskzQICb8XlEeSCIThqKiFaaEis"},{"name":"BOB_DOCKERFILE_PATH","value":"/workspace/.gitpod.dockerfile"},{"name":"BOB_CONTEXT_DIR","value":"/workspace"},{"name":"BOB_AUTH_KEY","value":"GR9u6Y6MnUp4BxDZmSFvwaciqkNOqpQ1"},{"name":"GITPOD_TASKS","value":"[{\"name\": \"build\", \"init\": \"sudo -E /app/bob build\"}]"},{"name":"GITPOD_INTERVAL","value":"30000"},{"name":"GITPOD_MEMORY","value":"2415"},{"name":"GITPOD_HEADLESS","value":"true"}],"resources":{"limits":{"cpu":"5","memory":"12Gi"},"requests":{"cpu":"1m","ephemeral-storage":"5Gi","memory":"2304Mi"}},"volumeMounts":[{"name":"vol-this-workspace","mountPath":"/workspace","mountPropagation":"HostToContainer"},{"name":"daemon-mount","mountPath":"/.workspace","mountPropagation":"HostToContainer"}],"readinessProbe":{"httpGet":{"path":"/_supervisor/v1/status/content/wait/true","port":22999,"scheme":"HTTP"},"timeoutSeconds":1,"periodSeconds":1,"successThreshold":1,"failureThreshold":600},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["AUDIT_WRITE","FSETID","KILL","NET_BIND_SERVICE","SYS_PTRACE"],"drop":["SETPCAP","CHOWN","NET_RAW","DAC_OVERRIDE","FOWNER","SYS_CHROOT","SETFCAP","SETUID","SETGID"]},"privileged":false,"runAsUser":33333,"runAsGroup":33333,"runAsNonRoot":true,"readOnlyRootFilesystem":false,"allowPrivilegeEscalation":true}}],"restartPolicy":"Never","terminationGracePeriodSeconds":30,"dnsPolicy":"None","serviceAccountName":"workspace","serviceAccount":"workspace","automountServiceAccountToken":false,"nodeName":"gke-dev-workload-1-49d27f81-8s5c","securityContext":{"supplementalGroups":[1],"fsGroup":1,"seccompProfile":{"type":"Localhost","localhostProfile":"workspace_default_cw-imgbuilder-mk3-rebase.100.json"}},"imagePullSecrets":[{"name":"gcp-sa-registry-auth"}],"schedulerName":"workspace-scheduler","tolerations":[{"key":"node.kubernetes.io/disk-pressure","operator":"Exists","effect":"NoExecute"},{"key":"node.kubernetes.io/memory-pressure","operator":"Exists","effect":"NoExecute"},{"key":"node.kubernetes.io/network-unavailable","operator":"Exists","effect":"NoExecute","tolerationSeconds":30},{"key":"node.kubernetes.io/not-ready","operator":"Exists","effect":"NoExecute","tolerationSeconds":300},{"key":"node.kubernetes.io/unreachable","operator":"Exists","effect":"NoExecute","tolerationSeconds":300}],"priority":0,"dnsConfig":{"nameservers":["1.1.1.1","8.8.8.8"]},"enableServiceLinks":false,"preemptionPolicy":"PreemptLowerPriority"},"status":{"phase":"Succeeded","conditions":[{"type":"Initialized","status":"True","lastProbeTime":null,"lastTransitionTime":"2021-07-21T16:02:45Z","reason":"PodCompleted"},{"type":"Ready","status":"False","lastProbeTime":null,"lastTransitionTime":"2021-07-21T16:08:00Z","reason":"PodCompleted"},{"type":"ContainersReady","status":"False","lastProbeTime":null,"lastTransitionTime":"2021-07-21T16:08:00Z","reason":"PodCompleted"},{"type":"PodScheduled","status":"True","lastProbeTime":null,"lastTransitionTime":"2021-07-21T16:02:45Z"}],"hostIP":"10.132.0.17","podIP":"10.60.22.132","podIPs":[{"ip":"10.60.22.132"}],"startTime":"2021-07-21T16:02:45Z","containerStatuses":[{"name":"workspace","state":{"terminated":{"exitCode":0,"reason":"Completed","startedAt":"2021-07-21T16:03:04Z","finishedAt":"2021-07-21T16:07:59Z","containerID":"containerd://b1a0fe3f35a826fbf8fee1518f2ccb7c75f818b4ea9cc17bb22586c18aaa1410"}},"lastState":{},"ready":false,"restartCount":0,"image":"reg.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com:30815/remote/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b:latest","imageID":"reg.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com:30815/remote/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b@sha256:d86c7d32f939aa04b1092968a624ffe697c9c35268be230169070a2a52d4bda9","containerID":"containerd://b1a0fe3f35a826fbf8fee1518f2ccb7c75f818b4ea9cc17bb22586c18aaa1410","started":false}],"qosClass":"Burstable"}},"theiaService":{"kind":"Service","apiVersion":"v1","metadata":{"name":"ws-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b-theia","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/services/ws-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b-theia","uid":"cdb765b1-60ee-4bf9-9e5e-c8e635c719df","resourceVersion":"237704855","creationTimestamp":"2021-07-21T16:02:45Z","labels":{"app":"gitpod","component":"workspace","gpwsman":"true","headless":"true","metaID":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","owner":"image-builder","workspaceID":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","workspaceType":"imagebuild"},"managedFields":[{"manager":"ws-manager","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:02:45Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:component":{},"f:gpwsman":{},"f:headless":{},"f:metaID":{},"f:owner":{},"f:workspaceID":{},"f:workspaceType":{}}},"f:spec":{"f:ports":{".":{},"k:{\"port\":22999,\"protocol\":\"TCP\"}":{".":{},"f:name":{},"f:port":{},"f:protocol":{},"f:targetPort":{}},"k:{\"port\":23000,\"protocol\":\"TCP\"}":{".":{},"f:name":{},"f:port":{},"f:protocol":{},"f:targetPort":{}}},"f:selector":{".":{},"f:app":{},"f:component":{},"f:gpwsman":{},"f:headless":{},"f:metaID":{},"f:owner":{},"f:workspaceID":{},"f:workspaceType":{}},"f:sessionAffinity":{},"f:type":{}}}}]},"spec":{"ports":[{"name":"ide","protocol":"TCP","port":23000,"targetPort":23000},{"name":"supervisor","protocol":"TCP","port":22999,"targetPort":22999}],"selector":{"app":"gitpod","component":"workspace","gpwsman":"true","headless":"true","metaID":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","owner":"image-builder","workspaceID":"0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","workspaceType":"imagebuild"},"clusterIP":"10.63.242.92","type":"ClusterIP","sessionAffinity":"None"},"status":{"loadBalancer":{}}},"events":[{"metadata":{"name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b - scrdhnl","generateName":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b - scheduled","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/events/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b%20-%20scrdhnl","uid":"b09f5f40-c5a1-49c4-abb4-c12889a4c151","resourceVersion":"14681306","creationTimestamp":"2021-07-21T16:02:45Z","managedFields":[{"manager":"ws-scheduler","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:02:45Z","fieldsType":"FieldsV1","fieldsV1":{"f:count":{},"f:firstTimestamp":{},"f:involvedObject":{"f:kind":{},"f:name":{},"f:namespace":{},"f:uid":{}},"f:lastTimestamp":{},"f:message":{},"f:metadata":{"f:generateName":{}},"f:reason":{},"f:source":{"f:component":{}},"f:type":{}}}]},"involvedObject":{"kind":"Pod","namespace":"staging-cw-imgbuilder-mk3-rebase","name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","uid":"a87d12cb-d5ef-4dad-a1fa-44284e994f07"},"reason":"Scheduled","message":"Placed pod [staging-cw-imgbuilder-mk3-rebase/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b] on gke-dev-workload-1-49d27f81-8s5c\n","source":{"component":"workspace-scheduler"},"firstTimestamp":"2021-07-21T16:02:45Z","lastTimestamp":"2021-07-21T16:02:45Z","count":1,"type":"Normal","eventTime":null,"reportingComponent":"","reportingInstance":""},{"metadata":{"name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9cd60f7517f","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/events/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9cd60f7517f","uid":"4aadb7e6-0974-4245-bacf-733a3de21487","resourceVersion":"14681307","creationTimestamp":"2021-07-21T16:02:46Z","managedFields":[{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:02:46Z","fieldsType":"FieldsV1","fieldsV1":{"f:count":{},"f:firstTimestamp":{},"f:involvedObject":{"f:apiVersion":{},"f:fieldPath":{},"f:kind":{},"f:name":{},"f:namespace":{},"f:resourceVersion":{},"f:uid":{}},"f:lastTimestamp":{},"f:message":{},"f:reason":{},"f:source":{"f:component":{},"f:host":{}},"f:type":{}}}]},"involvedObject":{"kind":"Pod","namespace":"staging-cw-imgbuilder-mk3-rebase","name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","uid":"a87d12cb-d5ef-4dad-a1fa-44284e994f07","apiVersion":"v1","resourceVersion":"237704853","fieldPath":"spec.containers{workspace}"},"reason":"Pulling","message":"Pulling image \"reg.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com:30815/remote/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b\"","source":{"component":"kubelet","host":"gke-dev-workload-1-49d27f81-8s5c"},"firstTimestamp":"2021-07-21T16:02:46Z","lastTimestamp":"2021-07-21T16:02:46Z","count":1,"type":"Normal","eventTime":null,"reportingComponent":"","reportingInstance":""},{"metadata":{"name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9d0efea9977","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/events/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9d0efea9977","uid":"1914f2c6-0da1-4efc-bcd4-561c33c44f87","resourceVersion":"14681308","creationTimestamp":"2021-07-21T16:03:01Z","managedFields":[{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:03:01Z","fieldsType":"FieldsV1","fieldsV1":{"f:count":{},"f:firstTimestamp":{},"f:involvedObject":{"f:apiVersion":{},"f:fieldPath":{},"f:kind":{},"f:name":{},"f:namespace":{},"f:resourceVersion":{},"f:uid":{}},"f:lastTimestamp":{},"f:message":{},"f:reason":{},"f:source":{"f:component":{},"f:host":{}},"f:type":{}}}]},"involvedObject":{"kind":"Pod","namespace":"staging-cw-imgbuilder-mk3-rebase","name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","uid":"a87d12cb-d5ef-4dad-a1fa-44284e994f07","apiVersion":"v1","resourceVersion":"237704853","fieldPath":"spec.containers{workspace}"},"reason":"Pulled","message":"Successfully pulled image \"reg.cw-imgbuilder-mk3-rebase.staging.gitpod-dev.com:30815/remote/0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b\" in 15.283188815s","source":{"component":"kubelet","host":"gke-dev-workload-1-49d27f81-8s5c"},"firstTimestamp":"2021-07-21T16:03:01Z","lastTimestamp":"2021-07-21T16:03:01Z","count":1,"type":"Normal","eventTime":null,"reportingComponent":"","reportingInstance":""},{"metadata":{"name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9d162cf7143","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/events/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9d162cf7143","uid":"2abb038a-e90b-44f1-85fd-5b4d61a8e307","resourceVersion":"14681309","creationTimestamp":"2021-07-21T16:03:03Z","managedFields":[{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:03:03Z","fieldsType":"FieldsV1","fieldsV1":{"f:count":{},"f:firstTimestamp":{},"f:involvedObject":{"f:apiVersion":{},"f:fieldPath":{},"f:kind":{},"f:name":{},"f:namespace":{},"f:resourceVersion":{},"f:uid":{}},"f:lastTimestamp":{},"f:message":{},"f:reason":{},"f:source":{"f:component":{},"f:host":{}},"f:type":{}}}]},"involvedObject":{"kind":"Pod","namespace":"staging-cw-imgbuilder-mk3-rebase","name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","uid":"a87d12cb-d5ef-4dad-a1fa-44284e994f07","apiVersion":"v1","resourceVersion":"237704853","fieldPath":"spec.containers{workspace}"},"reason":"Created","message":"Created container workspace","source":{"component":"kubelet","host":"gke-dev-workload-1-49d27f81-8s5c"},"firstTimestamp":"2021-07-21T16:03:03Z","lastTimestamp":"2021-07-21T16:03:03Z","count":1,"type":"Normal","eventTime":null,"reportingComponent":"","reportingInstance":""},{"metadata":{"name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9d17488b910","namespace":"staging-cw-imgbuilder-mk3-rebase","selfLink":"/api/v1/namespaces/staging-cw-imgbuilder-mk3-rebase/events/imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b.1693d9d17488b910","uid":"0f2b6737-f1c8-4956-b834-5cd51f342d41","resourceVersion":"14681310","creationTimestamp":"2021-07-21T16:03:04Z","managedFields":[{"manager":"kubelet","operation":"Update","apiVersion":"v1","time":"2021-07-21T16:03:04Z","fieldsType":"FieldsV1","fieldsV1":{"f:count":{},"f:firstTimestamp":{},"f:involvedObject":{"f:apiVersion":{},"f:fieldPath":{},"f:kind":{},"f:name":{},"f:namespace":{},"f:resourceVersion":{},"f:uid":{}},"f:lastTimestamp":{},"f:message":{},"f:reason":{},"f:source":{"f:component":{},"f:host":{}},"f:type":{}}}]},"involvedObject":{"kind":"Pod","namespace":"staging-cw-imgbuilder-mk3-rebase","name":"imagebuild-0dd5700a790e7ca2-95291c91f6e61c2e-e06ba50b","uid":"a87d12cb-d5ef-4dad-a1fa-44284e994f07","apiVersion":"v1","resourceVersion":"237704853","fieldPath":"spec.containers{workspace}"},"reason":"Started","message":"Started container workspace","source":{"component":"kubelet","host":"gke-dev-workload-1-49d27f81-8s5c"},"firstTimestamp":"2021-07-21T16:03:04Z","lastTimestamp":"2021-07-21T16:03:04Z","count":1,"type":"Normal","eventTime":null,"reportingComponent":"","reportingInstance":""}]} \ No newline at end of file