From c4d3414016edc7d03926ebc7ad2e9c55f6873cfc Mon Sep 17 00:00:00 2001 From: Todd Knight Date: Fri, 21 Aug 2020 10:57:30 -0700 Subject: [PATCH] Add Host Set CUDLR handler and SDK (#290) --- api/hosts/host_catalog_test.go | 6 +- api/hosts/host_set.gen.go | 21 +- api/hosts/host_set_test.go | 184 +++++ api/hosts/host_test.go | 68 ++ internal/gen/controller.swagger.json | 157 +++- .../api/resources/hosts/host_set.pb.go | 241 +++--- .../api/services/host_set_service.pb.go | 560 +++++++------ .../api/services/host_set_service.pb.gw.go | 141 ++-- internal/host/static/testing_test.go | 8 +- .../api/resources/hosts/v1/host_set.proto | 18 +- .../api/services/v1/host_set_service.proto | 72 +- internal/servers/controller/handler.go | 8 + internal/servers/controller/handler_test.go | 5 + .../handlers/host_sets/host_set_service.go | 490 ++++++++++++ .../host_sets/host_set_service_test.go | 747 ++++++++++++++++++ .../handlers/hosts/host_service_test.go | 27 +- 16 files changed, 2307 insertions(+), 446 deletions(-) create mode 100644 api/hosts/host_set_test.go create mode 100644 internal/servers/controller/handlers/host_sets/host_set_service.go create mode 100644 internal/servers/controller/handlers/host_sets/host_set_service_test.go diff --git a/api/hosts/host_catalog_test.go b/api/hosts/host_catalog_test.go index 7ee6e66c6..9c0a36ded 100644 --- a/api/hosts/host_catalog_test.go +++ b/api/hosts/host_catalog_test.go @@ -47,7 +47,7 @@ func TestCatalog_List(t *testing.T) { ul, apiErr, err = catalogClient.List(tc.Context()) assert.NoError(err) assert.Nil(apiErr) - assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ul)) + assert.ElementsMatch(comparableCatalogSlice(expected[:1]), comparableCatalogSlice(ul)) for i := 1; i < 10; i++ { expected[i], apiErr, err = catalogClient.Create(tc.Context(), "static", hosts.WithName(expected[i].Name)) @@ -57,10 +57,10 @@ func TestCatalog_List(t *testing.T) { ul, apiErr, err = catalogClient.List(tc.Context()) require.NoError(err) assert.Nil(apiErr) - assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul)) + assert.ElementsMatch(comparableCatalogSlice(expected), comparableCatalogSlice(ul)) } -func comparableSlice(in []*hosts.HostCatalog) []hosts.HostCatalog { +func comparableCatalogSlice(in []*hosts.HostCatalog) []hosts.HostCatalog { var filtered []hosts.HostCatalog for _, i := range in { p := hosts.HostCatalog{ diff --git a/api/hosts/host_set.gen.go b/api/hosts/host_set.gen.go index 06f25f7bb..fd136ac6b 100644 --- a/api/hosts/host_set.gen.go +++ b/api/hosts/host_set.gen.go @@ -14,16 +14,17 @@ import ( ) type HostSet struct { - Id string `json:"id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` - Size uint32 `json:"size,omitempty"` - Hosts []*Host `json:"hosts,omitempty"` + Id string `json:"id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + HostCatalogId string `json:"host_catalog_id,omitempty"` + HostIds []string `json:"host_ids,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` } type HostSetsClient struct { diff --git a/api/hosts/host_set_test.go b/api/hosts/host_set_test.go new file mode 100644 index 000000000..e98a9fd0d --- /dev/null +++ b/api/hosts/host_set_test.go @@ -0,0 +1,184 @@ +package hosts_test + +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/boundary/api" + "github.com/hashicorp/boundary/api/hosts" + "github.com/hashicorp/boundary/internal/host/static" + "github.com/hashicorp/boundary/internal/iam" + "github.com/hashicorp/boundary/internal/servers/controller" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSet_List(t *testing.T) { + assert, require := assert.New(t), require.New(t) + amId := "paum_1234567890" + tc := controller.NewTestController(t, &controller.TestControllerOpts{ + DisableAuthorizationFailures: true, + DefaultAuthMethodId: amId, + DefaultLoginName: "user", + DefaultPassword: "passpass", + }) + defer tc.Shutdown() + + client := tc.Client() + _, proj := iam.TestScopes(t, tc.IamRepo()) + client.SetScopeId(proj.GetPublicId()) + + hc, apiErr, err := hosts.NewHostCatalogsClient(client).Create(tc.Context(), "static") + require.NoError(err) + require.Nil(apiErr) + require.NotNil(hc) + + hClient := hosts.NewHostSetsClient(client) + + ul, apiErr, err := hClient.List(tc.Context(), hc.Id) + assert.NoError(err) + assert.Nil(apiErr) + assert.Empty(ul) + + var expected []*hosts.HostSet + for i := 0; i < 10; i++ { + expected = append(expected, &hosts.HostSet{Name: fmt.Sprint(i)}) + } + + expected[0], apiErr, err = hClient.Create(tc.Context(), hc.Id, hosts.WithName(expected[0].Name)) + assert.NoError(err) + assert.Nil(apiErr) + + ul, apiErr, err = hClient.List(tc.Context(), hc.Id) + assert.NoError(err) + assert.Nil(apiErr) + assert.ElementsMatch(comparableSetSlice(expected[:1]), comparableSetSlice(ul)) + + for i := 1; i < 10; i++ { + expected[i], apiErr, err = hClient.Create(tc.Context(), hc.Id, hosts.WithName(expected[i].Name)) + assert.NoError(err) + assert.Nil(apiErr) + } + ul, apiErr, err = hClient.List(tc.Context(), hc.Id) + require.NoError(err) + assert.Nil(apiErr) + assert.ElementsMatch(comparableSetSlice(expected), comparableSetSlice(ul)) +} + +func comparableSetSlice(in []*hosts.HostSet) []hosts.HostSet { + var filtered []hosts.HostSet + for _, i := range in { + p := hosts.HostSet{ + Id: i.Id, + Name: i.Name, + Description: i.Description, + CreatedTime: i.CreatedTime, + UpdatedTime: i.UpdatedTime, + } + filtered = append(filtered, p) + } + return filtered +} + +func TestSet_Crud(t *testing.T) { + assert, require := assert.New(t), require.New(t) + amId := "paum_1234567890" + tc := controller.NewTestController(t, &controller.TestControllerOpts{ + DisableAuthorizationFailures: true, + DefaultAuthMethodId: amId, + DefaultLoginName: "user", + DefaultPassword: "passpass", + }) + defer tc.Shutdown() + + client := tc.Client() + org, proj := iam.TestScopes(t, tc.IamRepo()) + client.SetScopeId(org.GetPublicId()) + projClient := client.Clone() + projClient.SetScopeId(proj.GetPublicId()) + + hc, apiErr, err := hosts.NewHostCatalogsClient(projClient).Create(tc.Context(), "static") + require.NoError(err) + require.Nil(apiErr) + require.NotNil(hc) + + checkHost := func(step string, h *hosts.HostSet, apiErr *api.Error, err error, wantedName string, wantVersion uint32) { + require.NoError(err, step) + if !assert.Nil(apiErr, step) && apiErr.Message != "" { + t.Errorf("ApiError message: %q", apiErr.Message) + } + assert.NotNil(h, "returned no resource", step) + gotName := "" + if h.Name != "" { + gotName = h.Name + } + assert.Equal(wantedName, gotName, step) + assert.Equal(wantVersion, h.Version) + } + + hClient := hosts.NewHostSetsClient(projClient) + + h, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithName("foo")) + checkHost("create", h, apiErr, err, "foo", 1) + + h, apiErr, err = hClient.Read(tc.Context(), hc.Id, h.Id) + checkHost("read", h, apiErr, err, "foo", 1) + + h, apiErr, err = hClient.Update(tc.Context(), hc.Id, h.Id, h.Version, hosts.WithName("bar")) + checkHost("update", h, apiErr, err, "bar", 2) + + h, apiErr, err = hClient.Update(tc.Context(), hc.Id, h.Id, h.Version, hosts.DefaultName()) + checkHost("update", h, apiErr, err, "", 3) + + existed, apiErr, err := hClient.Delete(tc.Context(), hc.Id, h.Id) + assert.NoError(err) + assert.True(existed, "Expected existing catalog when deleted, but it wasn't.") + + existed, apiErr, err = hClient.Delete(tc.Context(), hc.Id, h.Id) + assert.NoError(err) + assert.False(existed, "Expected catalog to not exist when deleted, but it did.") +} + +// TODO: Get better coverage for expected errors and error formats. +func TestSet_Errors(t *testing.T) { + assert, require := assert.New(t), require.New(t) + amId := "paum_1234567890" + tc := controller.NewTestController(t, &controller.TestControllerOpts{ + DisableAuthorizationFailures: true, + DefaultAuthMethodId: amId, + DefaultLoginName: "user", + DefaultPassword: "passpass", + }) + defer tc.Shutdown() + + client := tc.Client() + _, proj := iam.TestScopes(t, tc.IamRepo()) + client.SetScopeId(proj.GetPublicId()) + + hc, apiErr, err := hosts.NewHostCatalogsClient(client).Create(tc.Context(), "static") + require.NoError(err) + require.Nil(apiErr) + require.NotNil(hc) + + hClient := hosts.NewHostSetsClient(client) + + h, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithName("foo")) + require.NoError(err) + require.Nil(apiErr) + assert.NotNil(h) + + _, apiErr, err = hClient.Create(tc.Context(), hc.Id, hosts.WithName("foo")) + require.NoError(err) + assert.NotNil(apiErr) + + _, apiErr, err = hClient.Read(tc.Context(), hc.Id, static.HostSetPrefix+"_doesntexis") + require.NoError(err) + assert.NotNil(apiErr) + assert.EqualValues(apiErr.Status, http.StatusNotFound) + + _, apiErr, err = hClient.Read(tc.Context(), hc.Id, "invalid id") + require.NoError(err) + assert.NotNil(apiErr) + assert.EqualValues(http.StatusForbidden, apiErr.Status) +} diff --git a/api/hosts/host_test.go b/api/hosts/host_test.go index ba30adc31..c116c1723 100644 --- a/api/hosts/host_test.go +++ b/api/hosts/host_test.go @@ -1,6 +1,7 @@ package hosts_test import ( + "fmt" "net/http" "testing" @@ -13,6 +14,73 @@ import ( "github.com/stretchr/testify/require" ) +func TestHost_List(t *testing.T) { + assert, require := assert.New(t), require.New(t) + amId := "paum_1234567890" + tc := controller.NewTestController(t, &controller.TestControllerOpts{ + DisableAuthorizationFailures: true, + DefaultAuthMethodId: amId, + DefaultLoginName: "user", + DefaultPassword: "passpass", + }) + defer tc.Shutdown() + + client := tc.Client() + _, proj := iam.TestScopes(t, tc.IamRepo()) + client.SetScopeId(proj.GetPublicId()) + + hc, apiErr, err := hosts.NewHostCatalogsClient(client).Create(tc.Context(), "static") + require.NoError(err) + require.Nil(apiErr) + require.NotNil(hc) + + hClient := hosts.NewHostsClient(client) + + ul, apiErr, err := hClient.List(tc.Context(), hc.Id) + assert.NoError(err) + assert.Nil(apiErr) + assert.Empty(ul) + + var expected []*hosts.Host + for i := 0; i < 10; i++ { + expected = append(expected, &hosts.Host{Name: fmt.Sprint(i)}) + } + + expected[0], apiErr, err = hClient.Create(tc.Context(), hc.Id, hosts.WithName(expected[0].Name), hosts.WithStaticHostAddress("someaddress")) + assert.NoError(err) + assert.Nil(apiErr) + + ul, apiErr, err = hClient.List(tc.Context(), hc.Id) + assert.NoError(err) + assert.Nil(apiErr) + assert.ElementsMatch(comparableHostSlice(expected[:1]), comparableHostSlice(ul)) + + for i := 1; i < 10; i++ { + expected[i], apiErr, err = hClient.Create(tc.Context(), hc.Id, hosts.WithName(expected[i].Name), hosts.WithStaticHostAddress("someaddress")) + assert.NoError(err) + assert.Nil(apiErr) + } + ul, apiErr, err = hClient.List(tc.Context(), hc.Id) + require.NoError(err) + assert.Nil(apiErr) + assert.ElementsMatch(comparableHostSlice(expected), comparableHostSlice(ul)) +} + +func comparableHostSlice(in []*hosts.Host) []hosts.Host { + var filtered []hosts.Host + for _, i := range in { + p := hosts.Host{ + Id: i.Id, + Name: i.Name, + Description: i.Description, + CreatedTime: i.CreatedTime, + UpdatedTime: i.UpdatedTime, + } + filtered = append(filtered, p) + } + return filtered +} + func TestHost_Crud(t *testing.T) { assert, require := assert.New(t), require.New(t) amId := "paum_1234567890" diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index d2b770149..061d902a7 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -1043,13 +1043,6 @@ "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" } }, - { - "name": "version", - "in": "query", - "required": false, - "type": "integer", - "format": "int64" - }, { "name": "update_mask", "in": "query", @@ -1068,14 +1061,13 @@ }, "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}:add-hosts": { "post": { - "summary": "Adds existing Hosts to the Host Set", - "description": "Adds the hosts to this Host Set if possible. All hosts added must be a child of the same host catalog this host set is a child of.", + "summary": "Adds existing Hosts to a Host Set.", "operationId": "HostSetService_AddHostSetHosts", "responses": { "200": { - "description": "A successful response.", + "description": "", "schema": { - "$ref": "#/definitions/controller.api.services.v1.AddHostSetHostsResponse" + "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" } } }, @@ -1091,6 +1083,14 @@ "in": "path", "required": true, "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.AddHostSetHostsRequest" + } } ], "tags": [ @@ -1100,14 +1100,13 @@ }, "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}:remove-hosts": { "post": { - "summary": "Removes Hosts from the Host Set", - "description": "Removes the hosts from this Host Set if present. If it is not present then no action is taken and no error is returned.", + "summary": "Removes Hosts from the Host Set.", "operationId": "HostSetService_RemoveHostSetHosts", "responses": { "200": { - "description": "A successful response.", + "description": "", "schema": { - "$ref": "#/definitions/controller.api.services.v1.RemoveHostSetHostsResponse" + "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" } } }, @@ -1124,6 +1123,14 @@ "in": "path", "required": true, "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.RemoveHostSetHostsRequest" + } } ], "tags": [ @@ -1134,13 +1141,12 @@ "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}:set-hosts": { "post": { "summary": "Sets the Hosts on the Host Set.", - "description": "Sets the Hosts on the Host Set, removing any hosts that are not specified in the request.", "operationId": "HostSetService_SetHostSetHosts", "responses": { "200": { - "description": "A successful response.", + "description": "", "schema": { - "$ref": "#/definitions/controller.api.services.v1.SetHostSetHostsResponse" + "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" } } }, @@ -1156,6 +1162,14 @@ "in": "path", "required": true, "type": "string" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/controller.api.services.v1.SetHostSetHostsRequest" + } } ], "tags": [ @@ -2395,26 +2409,27 @@ "version": { "type": "integer", "format": "int64", - "description": "The version can be used in subsequent write requests to ensure this resource\nhas not changed and to fail the write if it has.\nOutput only.", - "readOnly": true + "description": "The version can be used in subsequent write requests to ensure this resource\nhas not changed and to fail the write if it has." }, "type": { "type": "string", "title": "The type of the resource, to help differentiate schemas" }, - "size": { - "type": "integer", - "format": "int64", - "description": "The total count of hosts in this host set\nOutput only.", - "readOnly": true + "host_catalog_id": { + "type": "string", + "title": "The host catalog this host set is a part of\nOutput only" }, - "hosts": { + "host_ids": { "type": "array", "items": { - "$ref": "#/definitions/controller.api.resources.hosts.v1.Host" + "type": "string" }, "description": "A list of hosts in this host set\nTODO: Figure out if this should be in the basic HostSet view and what\nview to use on the Hosts.\nOutput only.", "readOnly": true + }, + "attributes": { + "type": "object", + "description": "The attributes that are applied for the specific host set type." } }, "title": "HostSet is a collection of Hosts created and managed by a HostCatalog" @@ -2699,8 +2714,35 @@ } } }, + "controller.api.services.v1.AddHostSetHostsRequest": { + "type": "object", + "properties": { + "host_catalog_id": { + "type": "string" + }, + "id": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int64" + }, + "host_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of host IDs which will be added to this host set. Each host\nreferenced here must be a child of the same host catalog that this host\nset is a child of." + } + } + }, "controller.api.services.v1.AddHostSetHostsResponse": { - "type": "object" + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" + } + } }, "controller.api.services.v1.AddRoleGrantsRequest": { "type": "object", @@ -3216,8 +3258,36 @@ } } }, + "controller.api.services.v1.RemoveHostSetHostsRequest": { + "type": "object", + "properties": { + "host_catalog_id": { + "type": "string" + }, + "id": { + "type": "string", + "description": "This host set's id." + }, + "version": { + "type": "integer", + "format": "int64" + }, + "host_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of host IDs which should not be in the host set when this request\nreturns." + } + } + }, "controller.api.services.v1.RemoveHostSetHostsResponse": { - "type": "object" + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" + } + } }, "controller.api.services.v1.RemoveRoleGrantsRequest": { "type": "object", @@ -3300,8 +3370,35 @@ } } }, + "controller.api.services.v1.SetHostSetHostsRequest": { + "type": "object", + "properties": { + "host_catalog_id": { + "type": "string" + }, + "id": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int64" + }, + "host_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of host IDs which will be set on this host set. Each host\nreferenced here must be a child of the same host catalog that this host\nset is a child of." + } + } + }, "controller.api.services.v1.SetHostSetHostsResponse": { - "type": "object" + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.hosts.v1.HostSet" + } + } }, "controller.api.services.v1.SetPasswordRequest": { "type": "object", diff --git a/internal/gen/controller/api/resources/hosts/host_set.pb.go b/internal/gen/controller/api/resources/hosts/host_set.pb.go index c586572b9..8130e03ef 100644 --- a/internal/gen/controller/api/resources/hosts/host_set.pb.go +++ b/internal/gen/controller/api/resources/hosts/host_set.pb.go @@ -8,6 +8,7 @@ package hosts import ( proto "github.com/golang/protobuf/proto" + _struct "github.com/golang/protobuf/ptypes/struct" timestamp "github.com/golang/protobuf/ptypes/timestamp" wrappers "github.com/golang/protobuf/ptypes/wrappers" scopes "github.com/hashicorp/boundary/internal/gen/controller/api/resources/scopes" @@ -53,18 +54,19 @@ type HostSet struct { UpdatedTime *timestamp.Timestamp `protobuf:"bytes,60,opt,name=updated_time,proto3" json:"updated_time,omitempty"` // The version can be used in subsequent write requests to ensure this resource // has not changed and to fail the write if it has. - // Output only. Version uint32 `protobuf:"varint,70,opt,name=version,proto3" json:"version,omitempty"` // The type of the resource, to help differentiate schemas - Type *wrappers.StringValue `protobuf:"bytes,80,opt,name=type,proto3" json:"type,omitempty"` - // The total count of hosts in this host set - // Output only. - Size uint32 `protobuf:"varint,90,opt,name=size,proto3" json:"size,omitempty"` + Type string `protobuf:"bytes,80,opt,name=type,proto3" json:"type,omitempty"` + // The host catalog this host set is a part of + // Output only + HostCatalogId string `protobuf:"bytes,90,opt,name=host_catalog_id,proto3" json:"host_catalog_id,omitempty"` // A list of hosts in this host set // TODO: Figure out if this should be in the basic HostSet view and what // view to use on the Hosts. // Output only. - Hosts []*Host `protobuf:"bytes,100,rep,name=hosts,proto3" json:"hosts,omitempty"` + HostIds []string `protobuf:"bytes,100,rep,name=host_ids,json=hostIds,proto3" json:"host_ids,omitempty"` + // The attributes that are applied for the specific host set type. + Attributes *_struct.Struct `protobuf:"bytes,110,opt,name=attributes,proto3" json:"attributes,omitempty"` } func (x *HostSet) Reset() { @@ -148,27 +150,72 @@ func (x *HostSet) GetVersion() uint32 { return 0 } -func (x *HostSet) GetType() *wrappers.StringValue { +func (x *HostSet) GetType() string { if x != nil { return x.Type } + return "" +} + +func (x *HostSet) GetHostCatalogId() string { + if x != nil { + return x.HostCatalogId + } + return "" +} + +func (x *HostSet) GetHostIds() []string { + if x != nil { + return x.HostIds + } return nil } -func (x *HostSet) GetSize() uint32 { +func (x *HostSet) GetAttributes() *_struct.Struct { if x != nil { - return x.Size - } - return 0 -} - -func (x *HostSet) GetHosts() []*Host { - if x != nil { - return x.Hosts + return x.Attributes } return nil } +type StaticHostSetAttributes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *StaticHostSetAttributes) Reset() { + *x = StaticHostSetAttributes{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_resources_hosts_v1_host_set_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StaticHostSetAttributes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StaticHostSetAttributes) ProtoMessage() {} + +func (x *StaticHostSetAttributes) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_resources_hosts_v1_host_set_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StaticHostSetAttributes.ProtoReflect.Descriptor instead. +func (*StaticHostSetAttributes) Descriptor() ([]byte, []int) { + return file_controller_api_resources_hosts_v1_host_set_proto_rawDescGZIP(), []int{1} +} + var File_controller_api_resources_hosts_v1_host_set_proto protoreflect.FileDescriptor var file_controller_api_resources_hosts_v1_host_set_proto_rawDesc = []byte{ @@ -177,60 +224,64 @@ var file_controller_api_resources_hosts_v1_host_set_proto_rawDesc = []byte{ 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, - 0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, - 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, - 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0xa9, 0x04, 0x0a, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0x12, 0x46, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, - 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, - 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, - 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x32, 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, - 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, - 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 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, - 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x50, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, - 0x65, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x3d, 0x0a, - 0x05, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x05, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x42, 0x51, 0x5a, 0x4f, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3b, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x68, + 0x6f, 0x73, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, + 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, + 0x04, 0x0a, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, + 0x6f, 0x70, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, + 0x46, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, + 0x01, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, + 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x32, 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, 0x0c, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 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, 0x0c, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x50, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, + 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x5a, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x5f, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x64, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x73, 0x12, 0x37, + 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x6e, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3b, + 0x68, 0x6f, 0x73, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -245,27 +296,27 @@ func file_controller_api_resources_hosts_v1_host_set_proto_rawDescGZIP() []byte return file_controller_api_resources_hosts_v1_host_set_proto_rawDescData } -var file_controller_api_resources_hosts_v1_host_set_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_controller_api_resources_hosts_v1_host_set_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_controller_api_resources_hosts_v1_host_set_proto_goTypes = []interface{}{ - (*HostSet)(nil), // 0: controller.api.resources.hosts.v1.HostSet - (*scopes.ScopeInfo)(nil), // 1: controller.api.resources.scopes.v1.ScopeInfo - (*wrappers.StringValue)(nil), // 2: google.protobuf.StringValue - (*timestamp.Timestamp)(nil), // 3: google.protobuf.Timestamp - (*Host)(nil), // 4: controller.api.resources.hosts.v1.Host + (*HostSet)(nil), // 0: controller.api.resources.hosts.v1.HostSet + (*StaticHostSetAttributes)(nil), // 1: controller.api.resources.hosts.v1.StaticHostSetAttributes + (*scopes.ScopeInfo)(nil), // 2: controller.api.resources.scopes.v1.ScopeInfo + (*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue + (*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp + (*_struct.Struct)(nil), // 5: google.protobuf.Struct } var file_controller_api_resources_hosts_v1_host_set_proto_depIdxs = []int32{ - 1, // 0: controller.api.resources.hosts.v1.HostSet.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 2, // 1: controller.api.resources.hosts.v1.HostSet.name:type_name -> google.protobuf.StringValue - 2, // 2: controller.api.resources.hosts.v1.HostSet.description:type_name -> google.protobuf.StringValue - 3, // 3: controller.api.resources.hosts.v1.HostSet.created_time:type_name -> google.protobuf.Timestamp - 3, // 4: controller.api.resources.hosts.v1.HostSet.updated_time:type_name -> google.protobuf.Timestamp - 2, // 5: controller.api.resources.hosts.v1.HostSet.type:type_name -> google.protobuf.StringValue - 4, // 6: controller.api.resources.hosts.v1.HostSet.hosts:type_name -> controller.api.resources.hosts.v1.Host - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 2, // 0: controller.api.resources.hosts.v1.HostSet.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 3, // 1: controller.api.resources.hosts.v1.HostSet.name:type_name -> google.protobuf.StringValue + 3, // 2: controller.api.resources.hosts.v1.HostSet.description:type_name -> google.protobuf.StringValue + 4, // 3: controller.api.resources.hosts.v1.HostSet.created_time:type_name -> google.protobuf.Timestamp + 4, // 4: controller.api.resources.hosts.v1.HostSet.updated_time:type_name -> google.protobuf.Timestamp + 5, // 5: controller.api.resources.hosts.v1.HostSet.attributes:type_name -> google.protobuf.Struct + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_controller_api_resources_hosts_v1_host_set_proto_init() } @@ -287,6 +338,18 @@ func file_controller_api_resources_hosts_v1_host_set_proto_init() { return nil } } + file_controller_api_resources_hosts_v1_host_set_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StaticHostSetAttributes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -294,7 +357,7 @@ func file_controller_api_resources_hosts_v1_host_set_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_resources_hosts_v1_host_set_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/gen/controller/api/services/host_set_service.pb.go b/internal/gen/controller/api/services/host_set_service.pb.go index 5c3616f0d..656f4b21b 100644 --- a/internal/gen/controller/api/services/host_set_service.pb.go +++ b/internal/gen/controller/api/services/host_set_service.pb.go @@ -362,9 +362,8 @@ type UpdateHostSetRequest struct { HostCatalogId string `protobuf:"bytes,1,opt,name=host_catalog_id,proto3" json:"host_catalog_id,omitempty"` Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` - Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` - Item *hosts.HostSet `protobuf:"bytes,4,opt,name=item,proto3" json:"item,omitempty"` - UpdateMask *field_mask.FieldMask `protobuf:"bytes,5,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` + Item *hosts.HostSet `protobuf:"bytes,3,opt,name=item,proto3" json:"item,omitempty"` + UpdateMask *field_mask.FieldMask `protobuf:"bytes,4,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` } func (x *UpdateHostSetRequest) Reset() { @@ -413,13 +412,6 @@ func (x *UpdateHostSetRequest) GetId() string { return "" } -func (x *UpdateHostSetRequest) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 -} - func (x *UpdateHostSetRequest) GetItem() *hosts.HostSet { if x != nil { return x.Item @@ -661,6 +653,8 @@ type AddHostSetHostsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Item *hosts.HostSet `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` } func (x *AddHostSetHostsResponse) Reset() { @@ -695,6 +689,13 @@ func (*AddHostSetHostsResponse) Descriptor() ([]byte, []int) { return file_controller_api_services_v1_host_set_service_proto_rawDescGZIP(), []int{11} } +func (x *AddHostSetHostsResponse) GetItem() *hosts.HostSet { + if x != nil { + return x.Item + } + return nil +} + type SetHostSetHostsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -773,6 +774,8 @@ type SetHostSetHostsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Item *hosts.HostSet `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` } func (x *SetHostSetHostsResponse) Reset() { @@ -807,6 +810,13 @@ func (*SetHostSetHostsResponse) Descriptor() ([]byte, []int) { return file_controller_api_services_v1_host_set_service_proto_rawDescGZIP(), []int{13} } +func (x *SetHostSetHostsResponse) GetItem() *hosts.HostSet { + if x != nil { + return x.Item + } + return nil +} + type RemoveHostSetHostsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -885,6 +895,8 @@ type RemoveHostSetHostsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Item *hosts.HostSet `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` } func (x *RemoveHostSetHostsResponse) Reset() { @@ -919,6 +931,13 @@ func (*RemoveHostSetHostsResponse) Descriptor() ([]byte, []int) { return file_controller_api_services_v1_host_set_service_proto_rawDescGZIP(), []int{15} } +func (x *RemoveHostSetHostsResponse) GetItem() *hosts.HostSet { + if x != nil { + return x.Item + } + return nil +} + var File_controller_api_services_v1_host_set_service_proto protoreflect.FileDescriptor var file_controller_api_services_v1_host_set_service_proto_rawDesc = []byte{ @@ -974,215 +993,205 @@ var file_controller_api_services_v1_host_set_service_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, - 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xe7, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xcd, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3e, 0x0a, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, + 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x57, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3e, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x22, 0x50, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, + 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, + 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x31, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, + 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, + 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x78, + 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, 0x87, 0x01, 0x0a, 0x16, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, + 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, + 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, - 0x73, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, - 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, - 0x6b, 0x22, 0x57, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x69, 0x74, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x73, 0x22, + 0x59, 0x0a, 0x17, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, - 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x50, 0x0a, 0x14, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, - 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x31, 0x0a, 0x15, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x22, - 0x87, 0x01, 0x0a, 0x16, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, - 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 0x5f, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, - 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x41, 0x64, 0x64, - 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, - 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x73, 0x22, 0x19, - 0x0a, 0x17, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8a, 0x01, 0x0a, 0x19, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, - 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, - 0x6f, 0x73, 0x74, 0x49, 0x64, 0x73, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8d, 0x11, 0x0a, 0x0e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xcf, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x12, 0x3b, 0x2f, - 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, - 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, - 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, - 0x92, 0x41, 0x16, 0x12, 0x14, 0x47, 0x65, 0x74, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0xe2, 0x01, 0x0a, 0x0c, 0x4c, 0x69, - 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73, - 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6f, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, - 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x92, 0x41, 0x2e, - 0x12, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x65, 0x74, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, - 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0xd5, - 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, - 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x22, 0x36, 0x2f, - 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, - 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, - 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x92, 0x41, 0x12, 0x12, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x48, - 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0xda, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x49, 0x32, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, - 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, - 0x12, 0x12, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, - 0x53, 0x65, 0x74, 0x12, 0xce, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x58, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x3d, 0x2a, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, - 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, - 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, - 0x41, 0x12, 0x12, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, - 0x74, 0x53, 0x65, 0x74, 0x12, 0xf9, 0x02, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, 0x74, - 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, + 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x87, 0x01, 0x0a, 0x16, 0x53, + 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, + 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73, + 0x74, 0x49, 0x64, 0x73, 0x22, 0x59, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, + 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3e, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, + 0x8a, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, + 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, + 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x73, 0x22, 0x5c, 0x0a, 0x1a, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, + 0x74, 0x53, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xc8, 0x0e, 0x0a, 0x0e, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xcf, 0x01, + 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, - 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0xfc, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x45, 0x2f, 0x76, 0x31, 0x2f, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, - 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x68, 0x6f, 0x73, 0x74, - 0x73, 0x92, 0x41, 0xab, 0x01, 0x12, 0x23, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, - 0x74, 0x69, 0x6e, 0x67, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x1a, 0x83, 0x01, 0x41, 0x64, 0x64, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x68, 0x69, 0x73, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x20, 0x69, 0x66, 0x20, - 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x2e, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x68, - 0x6f, 0x73, 0x74, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, - 0x62, 0x65, 0x20, 0x61, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x73, 0x65, - 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x2e, - 0x12, 0xc9, 0x02, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x73, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xcc, 0x01, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x22, 0x45, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x92, 0x41, 0x7c, - 0x12, 0x1f, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x73, - 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, - 0x2e, 0x1a, 0x59, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, - 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, - 0x74, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, - 0x68, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x12, 0xf5, 0x02, 0x0a, - 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xef, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4a, 0x22, 0x48, 0x2f, 0x76, 0x31, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, + 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, + 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x43, 0x12, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, + 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, + 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x16, 0x12, 0x14, 0x47, 0x65, 0x74, 0x20, 0x61, + 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, + 0xe2, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, + 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x6f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, - 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, - 0x68, 0x6f, 0x73, 0x74, 0x73, 0x92, 0x41, 0x9b, 0x01, 0x12, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x73, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x1a, 0x78, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x66, 0x72, - 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, - 0x20, 0x69, 0x66, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x20, 0x49, 0x66, - 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, - 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, - 0x6f, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x65, 0x64, 0x2e, 0x42, 0xa6, 0x01, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x92, 0x41, 0x56, 0x12, 0x50, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x12, 0x37, 0x41, 0x50, 0x49, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x73, 0x2e, 0x32, 0x05, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2a, 0x02, 0x02, 0x01, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x74, 0x73, 0x92, 0x41, 0x2e, 0x12, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x6c, 0x6c, + 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x63, 0x61, 0x74, + 0x61, 0x6c, 0x6f, 0x67, 0x12, 0xd5, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, + 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x44, 0x22, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, + 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, + 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, + 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x12, 0x12, 0x10, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0xda, 0x01, 0x0a, + 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x30, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x49, 0x32, 0x3b, 0x2f, 0x76, 0x31, + 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, + 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, + 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, + 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x12, 0x12, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, + 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0xce, 0x01, 0x0a, 0x0d, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x58, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x2a, 0x3b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, + 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, + 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, + 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, + 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x12, 0x12, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0xf9, 0x01, 0x0a, 0x0f, 0x41, + 0x64, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x32, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x64, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x22, + 0x45, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, + 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, + 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, + 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, + 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, + 0x41, 0x24, 0x12, 0x22, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, + 0x74, 0x20, 0x53, 0x65, 0x74, 0x2e, 0x12, 0xf6, 0x01, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, + 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x7a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x22, 0x45, 0x2f, 0x76, 0x31, + 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, + 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, + 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, + 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f, 0x73, + 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x21, 0x12, 0x1f, + 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x20, 0x6f, + 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x2e, 0x12, + 0x83, 0x02, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x53, 0x22, 0x48, 0x2f, + 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x68, 0x6f, 0x73, 0x74, + 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x68, 0x6f, 0x73, 0x74, 0x5f, + 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x68, 0x6f, 0x73, 0x74, + 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x92, 0x41, 0x22, 0x12, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x48, 0x6f, 0x73, + 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, + 0x20, 0x53, 0x65, 0x74, 0x2e, 0x42, 0xa6, 0x01, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x92, 0x41, 0x56, 0x12, 0x50, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x12, 0x37, 0x41, 0x50, 0x49, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, + 0x72, 0x73, 0x2e, 0x32, 0x05, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2a, 0x02, 0x02, 0x01, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1226,27 +1235,30 @@ var file_controller_api_services_v1_host_set_service_proto_depIdxs = []int32{ 16, // 4: controller.api.services.v1.UpdateHostSetRequest.item:type_name -> controller.api.resources.hosts.v1.HostSet 17, // 5: controller.api.services.v1.UpdateHostSetRequest.update_mask:type_name -> google.protobuf.FieldMask 16, // 6: controller.api.services.v1.UpdateHostSetResponse.item:type_name -> controller.api.resources.hosts.v1.HostSet - 0, // 7: controller.api.services.v1.HostSetService.GetHostSet:input_type -> controller.api.services.v1.GetHostSetRequest - 2, // 8: controller.api.services.v1.HostSetService.ListHostSets:input_type -> controller.api.services.v1.ListHostSetsRequest - 4, // 9: controller.api.services.v1.HostSetService.CreateHostSet:input_type -> controller.api.services.v1.CreateHostSetRequest - 6, // 10: controller.api.services.v1.HostSetService.UpdateHostSet:input_type -> controller.api.services.v1.UpdateHostSetRequest - 8, // 11: controller.api.services.v1.HostSetService.DeleteHostSet:input_type -> controller.api.services.v1.DeleteHostSetRequest - 10, // 12: controller.api.services.v1.HostSetService.AddHostSetHosts:input_type -> controller.api.services.v1.AddHostSetHostsRequest - 12, // 13: controller.api.services.v1.HostSetService.SetHostSetHosts:input_type -> controller.api.services.v1.SetHostSetHostsRequest - 14, // 14: controller.api.services.v1.HostSetService.RemoveHostSetHosts:input_type -> controller.api.services.v1.RemoveHostSetHostsRequest - 1, // 15: controller.api.services.v1.HostSetService.GetHostSet:output_type -> controller.api.services.v1.GetHostSetResponse - 3, // 16: controller.api.services.v1.HostSetService.ListHostSets:output_type -> controller.api.services.v1.ListHostSetsResponse - 5, // 17: controller.api.services.v1.HostSetService.CreateHostSet:output_type -> controller.api.services.v1.CreateHostSetResponse - 7, // 18: controller.api.services.v1.HostSetService.UpdateHostSet:output_type -> controller.api.services.v1.UpdateHostSetResponse - 9, // 19: controller.api.services.v1.HostSetService.DeleteHostSet:output_type -> controller.api.services.v1.DeleteHostSetResponse - 11, // 20: controller.api.services.v1.HostSetService.AddHostSetHosts:output_type -> controller.api.services.v1.AddHostSetHostsResponse - 13, // 21: controller.api.services.v1.HostSetService.SetHostSetHosts:output_type -> controller.api.services.v1.SetHostSetHostsResponse - 15, // 22: controller.api.services.v1.HostSetService.RemoveHostSetHosts:output_type -> controller.api.services.v1.RemoveHostSetHostsResponse - 15, // [15:23] is the sub-list for method output_type - 7, // [7:15] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 16, // 7: controller.api.services.v1.AddHostSetHostsResponse.item:type_name -> controller.api.resources.hosts.v1.HostSet + 16, // 8: controller.api.services.v1.SetHostSetHostsResponse.item:type_name -> controller.api.resources.hosts.v1.HostSet + 16, // 9: controller.api.services.v1.RemoveHostSetHostsResponse.item:type_name -> controller.api.resources.hosts.v1.HostSet + 0, // 10: controller.api.services.v1.HostSetService.GetHostSet:input_type -> controller.api.services.v1.GetHostSetRequest + 2, // 11: controller.api.services.v1.HostSetService.ListHostSets:input_type -> controller.api.services.v1.ListHostSetsRequest + 4, // 12: controller.api.services.v1.HostSetService.CreateHostSet:input_type -> controller.api.services.v1.CreateHostSetRequest + 6, // 13: controller.api.services.v1.HostSetService.UpdateHostSet:input_type -> controller.api.services.v1.UpdateHostSetRequest + 8, // 14: controller.api.services.v1.HostSetService.DeleteHostSet:input_type -> controller.api.services.v1.DeleteHostSetRequest + 10, // 15: controller.api.services.v1.HostSetService.AddHostSetHosts:input_type -> controller.api.services.v1.AddHostSetHostsRequest + 12, // 16: controller.api.services.v1.HostSetService.SetHostSetHosts:input_type -> controller.api.services.v1.SetHostSetHostsRequest + 14, // 17: controller.api.services.v1.HostSetService.RemoveHostSetHosts:input_type -> controller.api.services.v1.RemoveHostSetHostsRequest + 1, // 18: controller.api.services.v1.HostSetService.GetHostSet:output_type -> controller.api.services.v1.GetHostSetResponse + 3, // 19: controller.api.services.v1.HostSetService.ListHostSets:output_type -> controller.api.services.v1.ListHostSetsResponse + 5, // 20: controller.api.services.v1.HostSetService.CreateHostSet:output_type -> controller.api.services.v1.CreateHostSetResponse + 7, // 21: controller.api.services.v1.HostSetService.UpdateHostSet:output_type -> controller.api.services.v1.UpdateHostSetResponse + 9, // 22: controller.api.services.v1.HostSetService.DeleteHostSet:output_type -> controller.api.services.v1.DeleteHostSetResponse + 11, // 23: controller.api.services.v1.HostSetService.AddHostSetHosts:output_type -> controller.api.services.v1.AddHostSetHostsResponse + 13, // 24: controller.api.services.v1.HostSetService.SetHostSetHosts:output_type -> controller.api.services.v1.SetHostSetHostsResponse + 15, // 25: controller.api.services.v1.HostSetService.RemoveHostSetHosts:output_type -> controller.api.services.v1.RemoveHostSetHostsResponse + 18, // [18:26] is the sub-list for method output_type + 10, // [10:18] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_controller_api_services_v1_host_set_service_proto_init() } @@ -1480,14 +1492,59 @@ const _ = grpc.SupportPackageIsVersion6 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type HostSetServiceClient interface { - // This retrieves the host set specified in the request using the basic view. + // GetHostSet returns a stored Host Set if present. The provided request + // must include the host catalog and host set ID for the resource being + // retrieved. If any of those IDs are missing, malformed or reference a + // non existing resource an error is returned. GetHostSet(ctx context.Context, in *GetHostSetRequest, opts ...grpc.CallOption) (*GetHostSetResponse, error) + // ListHostSets returns a list of stored host sets which exist inside the scope + // referenced inside the request. The request must include the scope ID and + // the host catalog id for the host sets being retrieved. If the any of those + // are missing, malformed, or reference a non existing scope, an error is + // returned. ListHostSets(ctx context.Context, in *ListHostSetsRequest, opts ...grpc.CallOption) (*ListHostSetsResponse, error) + // CreateHostSet creates and stores a host set in boundary. The provided + // request must include the scope and host catalog ids in which the host set + // will be created. If the scope or catalog id are missing, malformed or + // references a non existing resource, an error is returned. If a name is + // provided that is in use by another host set in the same host catalog, an + // error is returned. CreateHostSet(ctx context.Context, in *CreateHostSetRequest, opts ...grpc.CallOption) (*CreateHostSetResponse, error) + // UpdateHostSet updates an existing host set in boundary. The provided + // host set must not have any read only fields set. The update mask must be + // included in the request and contain at least 1 mutable field. To unset + // a field's value, include the field in the update mask and don't set it + // in the provided host set. An error is returned if either the scope + // or host catalog or host set ids are missing or reference a non existing + // resource. An error is also returned if the request attempts to update the + // name to one that is already in use in this host catalog. UpdateHostSet(ctx context.Context, in *UpdateHostSetRequest, opts ...grpc.CallOption) (*UpdateHostSetResponse, error) + // DeleteHostSet removes a host set from Boundary. If the provided scope, + // host catalog, or host set ids are malformed or not provided an error is + // returned. No error is returned if any of the ids reference resources that + // do not exist since the response itself specifies if the resource existed + // before the DeleteHostSet request was received. DeleteHostSet(ctx context.Context, in *DeleteHostSetRequest, opts ...grpc.CallOption) (*DeleteHostSetResponse, error) + // AddHostSetHosts adds a host to a host set. The provided request must + // include the scope ID and the host set ID to which the host will be added. + // All hosts added to the provided host set must be a child of the same + // catalog that this host set is a child of. If the scope or host set IDs are + // missing, malformed, or reference non-existing resources, an error is + // returned. AddHostSetHosts(ctx context.Context, in *AddHostSetHostsRequest, opts ...grpc.CallOption) (*AddHostSetHostsResponse, error) + // SetHostSetHosts sets the host set's hosts. Any existing hosts on the + // host set are deleted if they are not included in this request. The + // provided request must include the scope, host catalog, and the host set + // ID on which the hosts will be set. All hosts in the request must be a + // child of the same catalog that the provided host set is. If any of those + // IDs are missing, malformed, or references a non-existing resource, an + // error is returned. SetHostSetHosts(ctx context.Context, in *SetHostSetHostsRequest, opts ...grpc.CallOption) (*SetHostSetHostsResponse, error) + // RemoveHostSetHosts removes the hosts from the specified host set. The + // provided request must include the scope, host catalog, and the host set + // IDs for the host set from which the host will be removed. If any of the + // IDs are missing, malformed, or references a non-existing scope or catalog, + // an error is returned. RemoveHostSetHosts(ctx context.Context, in *RemoveHostSetHostsRequest, opts ...grpc.CallOption) (*RemoveHostSetHostsResponse, error) } @@ -1573,14 +1630,59 @@ func (c *hostSetServiceClient) RemoveHostSetHosts(ctx context.Context, in *Remov // HostSetServiceServer is the server API for HostSetService service. type HostSetServiceServer interface { - // This retrieves the host set specified in the request using the basic view. + // GetHostSet returns a stored Host Set if present. The provided request + // must include the host catalog and host set ID for the resource being + // retrieved. If any of those IDs are missing, malformed or reference a + // non existing resource an error is returned. GetHostSet(context.Context, *GetHostSetRequest) (*GetHostSetResponse, error) + // ListHostSets returns a list of stored host sets which exist inside the scope + // referenced inside the request. The request must include the scope ID and + // the host catalog id for the host sets being retrieved. If the any of those + // are missing, malformed, or reference a non existing scope, an error is + // returned. ListHostSets(context.Context, *ListHostSetsRequest) (*ListHostSetsResponse, error) + // CreateHostSet creates and stores a host set in boundary. The provided + // request must include the scope and host catalog ids in which the host set + // will be created. If the scope or catalog id are missing, malformed or + // references a non existing resource, an error is returned. If a name is + // provided that is in use by another host set in the same host catalog, an + // error is returned. CreateHostSet(context.Context, *CreateHostSetRequest) (*CreateHostSetResponse, error) + // UpdateHostSet updates an existing host set in boundary. The provided + // host set must not have any read only fields set. The update mask must be + // included in the request and contain at least 1 mutable field. To unset + // a field's value, include the field in the update mask and don't set it + // in the provided host set. An error is returned if either the scope + // or host catalog or host set ids are missing or reference a non existing + // resource. An error is also returned if the request attempts to update the + // name to one that is already in use in this host catalog. UpdateHostSet(context.Context, *UpdateHostSetRequest) (*UpdateHostSetResponse, error) + // DeleteHostSet removes a host set from Boundary. If the provided scope, + // host catalog, or host set ids are malformed or not provided an error is + // returned. No error is returned if any of the ids reference resources that + // do not exist since the response itself specifies if the resource existed + // before the DeleteHostSet request was received. DeleteHostSet(context.Context, *DeleteHostSetRequest) (*DeleteHostSetResponse, error) + // AddHostSetHosts adds a host to a host set. The provided request must + // include the scope ID and the host set ID to which the host will be added. + // All hosts added to the provided host set must be a child of the same + // catalog that this host set is a child of. If the scope or host set IDs are + // missing, malformed, or reference non-existing resources, an error is + // returned. AddHostSetHosts(context.Context, *AddHostSetHostsRequest) (*AddHostSetHostsResponse, error) + // SetHostSetHosts sets the host set's hosts. Any existing hosts on the + // host set are deleted if they are not included in this request. The + // provided request must include the scope, host catalog, and the host set + // ID on which the hosts will be set. All hosts in the request must be a + // child of the same catalog that the provided host set is. If any of those + // IDs are missing, malformed, or references a non-existing resource, an + // error is returned. SetHostSetHosts(context.Context, *SetHostSetHostsRequest) (*SetHostSetHostsResponse, error) + // RemoveHostSetHosts removes the hosts from the specified host set. The + // provided request must include the scope, host catalog, and the host set + // IDs for the host set from which the host will be removed. If any of the + // IDs are missing, malformed, or references a non-existing scope or catalog, + // an error is returned. RemoveHostSetHosts(context.Context, *RemoveHostSetHostsRequest) (*RemoveHostSetHostsResponse, error) } diff --git a/internal/gen/controller/api/services/host_set_service.pb.gw.go b/internal/gen/controller/api/services/host_set_service.pb.gw.go index c3d491357..694a2f5ef 100644 --- a/internal/gen/controller/api/services/host_set_service.pb.gw.go +++ b/internal/gen/controller/api/services/host_set_service.pb.gw.go @@ -449,14 +449,18 @@ func local_request_HostSetService_DeleteHostSet_0(ctx context.Context, marshaler } -var ( - filter_HostSetService_AddHostSetHosts_0 = &utilities.DoubleArray{Encoding: map[string]int{"host_catalog_id": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - func request_HostSetService_AddHostSetHosts_0(ctx context.Context, marshaler runtime.Marshaler, client HostSetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq AddHostSetHostsRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -484,13 +488,6 @@ func request_HostSetService_AddHostSetHosts_0(ctx context.Context, marshaler run return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_AddHostSetHosts_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.AddHostSetHosts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -500,6 +497,14 @@ func local_request_HostSetService_AddHostSetHosts_0(ctx context.Context, marshal var protoReq AddHostSetHostsRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -527,26 +532,23 @@ func local_request_HostSetService_AddHostSetHosts_0(ctx context.Context, marshal return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_AddHostSetHosts_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.AddHostSetHosts(ctx, &protoReq) return msg, metadata, err } -var ( - filter_HostSetService_SetHostSetHosts_0 = &utilities.DoubleArray{Encoding: map[string]int{"host_catalog_id": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - func request_HostSetService_SetHostSetHosts_0(ctx context.Context, marshaler runtime.Marshaler, client HostSetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq SetHostSetHostsRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -574,13 +576,6 @@ func request_HostSetService_SetHostSetHosts_0(ctx context.Context, marshaler run return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_SetHostSetHosts_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.SetHostSetHosts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -590,6 +585,14 @@ func local_request_HostSetService_SetHostSetHosts_0(ctx context.Context, marshal var protoReq SetHostSetHostsRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -617,26 +620,23 @@ func local_request_HostSetService_SetHostSetHosts_0(ctx context.Context, marshal return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_SetHostSetHosts_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.SetHostSetHosts(ctx, &protoReq) return msg, metadata, err } -var ( - filter_HostSetService_RemoveHostSetHosts_0 = &utilities.DoubleArray{Encoding: map[string]int{"host_catalog_id": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - func request_HostSetService_RemoveHostSetHosts_0(ctx context.Context, marshaler runtime.Marshaler, client HostSetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq RemoveHostSetHostsRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -664,13 +664,6 @@ func request_HostSetService_RemoveHostSetHosts_0(ctx context.Context, marshaler return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_RemoveHostSetHosts_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.RemoveHostSetHosts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -680,6 +673,14 @@ func local_request_HostSetService_RemoveHostSetHosts_0(ctx context.Context, mars var protoReq RemoveHostSetHostsRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -707,13 +708,6 @@ func local_request_HostSetService_RemoveHostSetHosts_0(ctx context.Context, mars return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HostSetService_RemoveHostSetHosts_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.RemoveHostSetHosts(ctx, &protoReq) return msg, metadata, err @@ -841,7 +835,7 @@ func RegisterHostSetServiceHandlerServer(ctx context.Context, mux *runtime.Serve return } - forward_HostSetService_AddHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_HostSetService_AddHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, response_HostSetService_AddHostSetHosts_0{resp}, mux.GetForwardResponseOptions()...) }) @@ -861,7 +855,7 @@ func RegisterHostSetServiceHandlerServer(ctx context.Context, mux *runtime.Serve return } - forward_HostSetService_SetHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_HostSetService_SetHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, response_HostSetService_SetHostSetHosts_0{resp}, mux.GetForwardResponseOptions()...) }) @@ -881,7 +875,7 @@ func RegisterHostSetServiceHandlerServer(ctx context.Context, mux *runtime.Serve return } - forward_HostSetService_RemoveHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_HostSetService_RemoveHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, response_HostSetService_RemoveHostSetHosts_0{resp}, mux.GetForwardResponseOptions()...) }) @@ -1042,7 +1036,7 @@ func RegisterHostSetServiceHandlerClient(ctx context.Context, mux *runtime.Serve return } - forward_HostSetService_AddHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_HostSetService_AddHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, response_HostSetService_AddHostSetHosts_0{resp}, mux.GetForwardResponseOptions()...) }) @@ -1062,7 +1056,7 @@ func RegisterHostSetServiceHandlerClient(ctx context.Context, mux *runtime.Serve return } - forward_HostSetService_SetHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_HostSetService_SetHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, response_HostSetService_SetHostSetHosts_0{resp}, mux.GetForwardResponseOptions()...) }) @@ -1082,7 +1076,7 @@ func RegisterHostSetServiceHandlerClient(ctx context.Context, mux *runtime.Serve return } - forward_HostSetService_RemoveHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_HostSetService_RemoveHostSetHosts_0(ctx, mux, outboundMarshaler, w, req, response_HostSetService_RemoveHostSetHosts_0{resp}, mux.GetForwardResponseOptions()...) }) @@ -1116,6 +1110,33 @@ func (m response_HostSetService_UpdateHostSet_0) XXX_ResponseBody() interface{} return response.Item } +type response_HostSetService_AddHostSetHosts_0 struct { + proto.Message +} + +func (m response_HostSetService_AddHostSetHosts_0) XXX_ResponseBody() interface{} { + response := m.Message.(*AddHostSetHostsResponse) + return response.Item +} + +type response_HostSetService_SetHostSetHosts_0 struct { + proto.Message +} + +func (m response_HostSetService_SetHostSetHosts_0) XXX_ResponseBody() interface{} { + response := m.Message.(*SetHostSetHostsResponse) + return response.Item +} + +type response_HostSetService_RemoveHostSetHosts_0 struct { + proto.Message +} + +func (m response_HostSetService_RemoveHostSetHosts_0) XXX_ResponseBody() interface{} { + response := m.Message.(*RemoveHostSetHostsResponse) + return response.Item +} + var ( pattern_HostSetService_GetHostSet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "scopes", "host-catalogs", "host_catalog_id", "host-sets", "id"}, "")) diff --git a/internal/host/static/testing_test.go b/internal/host/static/testing_test.go index 23e736d46..36a4786b8 100644 --- a/internal/host/static/testing_test.go +++ b/internal/host/static/testing_test.go @@ -38,10 +38,10 @@ func Test_TestHosts(t *testing.T) { c := TestCatalogs(t, conn, org.GetPublicId(), 1)[0] count := 4 - accounts := TestHosts(t, conn, c.GetPublicId(), count) - assert.Len(accounts, count) - for _, a := range accounts { - assert.NotEmpty(a.GetPublicId()) + hosts := TestHosts(t, conn, c.GetPublicId(), count) + assert.Len(hosts, count) + for _, h := range hosts { + assert.NotEmpty(h.GetPublicId()) } } diff --git a/internal/proto/local/controller/api/resources/hosts/v1/host_set.proto b/internal/proto/local/controller/api/resources/hosts/v1/host_set.proto index df49e45f2..4616fe519 100644 --- a/internal/proto/local/controller/api/resources/hosts/v1/host_set.proto +++ b/internal/proto/local/controller/api/resources/hosts/v1/host_set.proto @@ -4,6 +4,7 @@ package controller.api.resources.hosts.v1; option go_package = "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts;hosts"; +import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; import "controller/api/resources/hosts/v1/host.proto"; @@ -36,19 +37,24 @@ message HostSet { // The version can be used in subsequent write requests to ensure this resource // has not changed and to fail the write if it has. - // Output only. uint32 version = 70; // The type of the resource, to help differentiate schemas - google.protobuf.StringValue type = 80; + string type = 80; - // The total count of hosts in this host set - // Output only. - uint32 size = 90; + // The host catalog this host set is a part of + // Output only + string host_catalog_id = 90 [json_name="host_catalog_id"]; // A list of hosts in this host set // TODO: Figure out if this should be in the basic HostSet view and what // view to use on the Hosts. // Output only. - repeated Host hosts = 100; + repeated string host_ids = 100; + + // The attributes that are applied for the specific host set type. + google.protobuf.Struct attributes = 110; } + +message StaticHostSetAttributes { +} \ No newline at end of file diff --git a/internal/proto/local/controller/api/services/v1/host_set_service.proto b/internal/proto/local/controller/api/services/v1/host_set_service.proto index 8a1b0313c..2d368cc34 100644 --- a/internal/proto/local/controller/api/services/v1/host_set_service.proto +++ b/internal/proto/local/controller/api/services/v1/host_set_service.proto @@ -20,7 +20,10 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { }; service HostSetService { - // This retrieves the host set specified in the request using the basic view. + // GetHostSet returns a stored Host Set if present. The provided request + // must include the host catalog and host set ID for the resource being + // retrieved. If any of those IDs are missing, malformed or reference a + // non existing resource an error is returned. rpc GetHostSet(GetHostSetRequest) returns (GetHostSetResponse) { option (google.api.http) = { get: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}" @@ -30,6 +33,12 @@ service HostSetService { summary: "Get a single HostSet" }; } + + // ListHostSets returns a list of stored host sets which exist inside the scope + // referenced inside the request. The request must include the scope ID and + // the host catalog id for the host sets being retrieved. If the any of those + // are missing, malformed, or reference a non existing scope, an error is + // returned. rpc ListHostSets(ListHostSetsRequest) returns (ListHostSetsResponse) { option (google.api.http) = { get: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets" @@ -38,6 +47,13 @@ service HostSetService { summary: "List all HostSets under the specific catalog" }; } + + // CreateHostSet creates and stores a host set in boundary. The provided + // request must include the scope and host catalog ids in which the host set + // will be created. If the scope or catalog id are missing, malformed or + // references a non existing resource, an error is returned. If a name is + // provided that is in use by another host set in the same host catalog, an + // error is returned. rpc CreateHostSet(CreateHostSetRequest) returns (CreateHostSetResponse) { option (google.api.http) = { post: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets" @@ -48,6 +64,15 @@ service HostSetService { summary: "Create a HostSet" }; } + + // UpdateHostSet updates an existing host set in boundary. The provided + // host set must not have any read only fields set. The update mask must be + // included in the request and contain at least 1 mutable field. To unset + // a field's value, include the field in the update mask and don't set it + // in the provided host set. An error is returned if either the scope + // or host catalog or host set ids are missing or reference a non existing + // resource. An error is also returned if the request attempts to update the + // name to one that is already in use in this host catalog. rpc UpdateHostSet(UpdateHostSetRequest) returns (UpdateHostSetResponse) { option (google.api.http) = { patch: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}" @@ -58,6 +83,12 @@ service HostSetService { summary: "Update a HostSet" }; } + + // DeleteHostSet removes a host set from Boundary. If the provided scope, + // host catalog, or host set ids are malformed or not provided an error is + // returned. No error is returned if any of the ids reference resources that + // do not exist since the response itself specifies if the resource existed + // before the DeleteHostSet request was received. rpc DeleteHostSet(DeleteHostSetRequest) returns (DeleteHostSetResponse) { option (google.api.http) = { delete: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}" @@ -67,33 +98,54 @@ service HostSetService { }; } + // AddHostSetHosts adds a host to a host set. The provided request must + // include the scope ID and the host set ID to which the host will be added. + // All hosts added to the provided host set must be a child of the same + // catalog that this host set is a child of. If the scope or host set IDs are + // missing, malformed, or reference non-existing resources, an error is + // returned. rpc AddHostSetHosts(AddHostSetHostsRequest) returns (AddHostSetHostsResponse) { option (google.api.http) = { post: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}:add-hosts" + body: "*" + response_body: "item" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { - summary: "Adds existing Hosts to the Host Set" - description: "Adds the hosts to this Host Set if possible. All hosts added must be a child of the same host catalog this host set is a child of." + summary: "Adds existing Hosts to a Host Set." }; } + // SetHostSetHosts sets the host set's hosts. Any existing hosts on the + // host set are deleted if they are not included in this request. The + // provided request must include the scope, host catalog, and the host set + // ID on which the hosts will be set. All hosts in the request must be a + // child of the same catalog that the provided host set is. If any of those + // IDs are missing, malformed, or references a non-existing resource, an + // error is returned. rpc SetHostSetHosts(SetHostSetHostsRequest) returns (SetHostSetHostsResponse) { option (google.api.http) = { post: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}:set-hosts" + body: "*" + response_body: "item" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { summary: "Sets the Hosts on the Host Set." - description: "Sets the Hosts on the Host Set, removing any hosts that are not specified in the request." }; } + // RemoveHostSetHosts removes the hosts from the specified host set. The + // provided request must include the scope, host catalog, and the host set + // IDs for the host set from which the host will be removed. If any of the + // IDs are missing, malformed, or references a non-existing scope or catalog, + // an error is returned. rpc RemoveHostSetHosts(RemoveHostSetHostsRequest) returns (RemoveHostSetHostsResponse) { option (google.api.http) = { post: "/v1/scopes/*/host-catalogs/{host_catalog_id}/host-sets/{id}:remove-hosts" + body: "*" + response_body: "item" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { - summary: "Removes Hosts from the Host Set" - description: "Removes the hosts from this Host Set if present. If it is not present then no action is taken and no error is returned." + summary: "Removes Hosts from the Host Set." }; } } @@ -130,9 +182,8 @@ message CreateHostSetResponse { message UpdateHostSetRequest { string host_catalog_id = 1 [json_name="host_catalog_id"]; string id = 2; - uint32 version = 3; - api.resources.hosts.v1.HostSet item = 4; - google.protobuf.FieldMask update_mask = 5; + api.resources.hosts.v1.HostSet item = 3; + google.protobuf.FieldMask update_mask = 4; } message UpdateHostSetResponse { @@ -160,6 +211,7 @@ message AddHostSetHostsRequest { } message AddHostSetHostsResponse { + api.resources.hosts.v1.HostSet item = 1; } message SetHostSetHostsRequest { @@ -174,6 +226,7 @@ message SetHostSetHostsRequest { } message SetHostSetHostsResponse { + api.resources.hosts.v1.HostSet item = 1; } message RemoveHostSetHostsRequest { @@ -188,4 +241,5 @@ message RemoveHostSetHostsRequest { } message RemoveHostSetHostsResponse { + api.resources.hosts.v1.HostSet item = 1; } diff --git a/internal/servers/controller/handler.go b/internal/servers/controller/handler.go index 42536976f..a2e317db4 100644 --- a/internal/servers/controller/handler.go +++ b/internal/servers/controller/handler.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/servers/controller/handlers/accounts" "github.com/hashicorp/boundary/internal/servers/controller/handlers/authmethods" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/host_sets" "github.com/hashicorp/shared-secure-libs/configutil" "github.com/hashicorp/vault/sdk/helper/strutil" @@ -84,6 +85,13 @@ func handleGrpcGateway(c *Controller, props HandlerProperties) (http.Handler, er if err := services.RegisterHostCatalogServiceHandlerServer(ctx, mux, hcs); err != nil { return nil, fmt.Errorf("failed to register host catalog service handler: %w", err) } + hss, err := host_sets.NewService(c.StaticHostRepoFn) + if err != nil { + return nil, fmt.Errorf("failed to create host set handler service: %w", err) + } + if err := services.RegisterHostSetServiceHandlerServer(ctx, mux, hss); err != nil { + return nil, fmt.Errorf("failed to register host set service handler: %w", err) + } hs, err := hosts.NewService(c.StaticHostRepoFn) if err != nil { return nil, fmt.Errorf("failed to create host handler service: %w", err) diff --git a/internal/servers/controller/handler_test.go b/internal/servers/controller/handler_test.go index b94e654b5..1290d96ec 100644 --- a/internal/servers/controller/handler_test.go +++ b/internal/servers/controller/handler_test.go @@ -59,6 +59,8 @@ func TestHandleImplementedPaths(t *testing.T) { "v1/scopes/someid/groups/someid", "v1/scopes/someid/host-catalogs", "v1/scopes/someid/host-catalogs/someid", + "v1/scopes/someid/host-catalogs/someid/host-sets", + "v1/scopes/someid/host-catalogs/someid/host-sets/someid", "v1/scopes/someid/host-catalogs/someid/hosts", "v1/scopes/someid/host-catalogs/someid/hosts/someid", "v1/scopes/someid/roles", @@ -75,6 +77,7 @@ func TestHandleImplementedPaths(t *testing.T) { "v1/scopes/someid/auth-methods", "v1/scopes/someid/auth-methods/someid/accounts", "v1/scopes/someid/host-catalogs", + "v1/scopes/someid/host-catalogs/someid/host-sets", "v1/scopes/someid/host-catalogs/someid/hosts", // custom methods @@ -100,6 +103,7 @@ func TestHandleImplementedPaths(t *testing.T) { "v1/scopes/someid/auth-methods/someid", "v1/scopes/someid/auth-methods/someid/accounts/someid", "v1/scopes/someid/host-catalogs/someid", + "v1/scopes/someid/host-catalogs/someid/host-sets/someid", "v1/scopes/someid/host-catalogs/someid/hosts/someid", }, "PATCH": { @@ -109,6 +113,7 @@ func TestHandleImplementedPaths(t *testing.T) { "v1/scopes/someid/groups/someid", "v1/scopes/someid/auth-methods/someid", "v1/scopes/someid/host-catalogs/someid", + "v1/scopes/someid/host-catalogs/someid/host-sets/someid", "v1/scopes/someid/host-catalogs/someid/hosts/someid", }, } { diff --git a/internal/servers/controller/handlers/host_sets/host_set_service.go b/internal/servers/controller/handlers/host_sets/host_set_service.go new file mode 100644 index 000000000..bc73a0568 --- /dev/null +++ b/internal/servers/controller/handlers/host_sets/host_set_service.go @@ -0,0 +1,490 @@ +package host_sets + +import ( + "context" + "fmt" + + "github.com/hashicorp/boundary/internal/auth" + pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts" + pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" + "github.com/hashicorp/boundary/internal/host" + "github.com/hashicorp/boundary/internal/host/static" + "github.com/hashicorp/boundary/internal/host/static/store" + "github.com/hashicorp/boundary/internal/servers/controller/common" + "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/wrapperspb" +) + +var ( + maskManager handlers.MaskManager +) + +func init() { + var err error + if maskManager, err = handlers.NewMaskManager(&pb.HostSet{}, &store.HostSet{}); err != nil { + panic(err) + } +} + +type Service struct { + staticRepoFn common.StaticRepoFactory +} + +var _ pbs.HostSetServiceServer = Service{} + +// NewService returns a host catalog Service which handles host catalog related requests to boundary and uses the provided +// repositories for storage and retrieval. +func NewService(repoFn common.StaticRepoFactory) (Service, error) { + if repoFn == nil { + return Service{}, fmt.Errorf("nil static repository provided") + } + return Service{staticRepoFn: repoFn}, nil +} + +func (s Service) ListHostSets(ctx context.Context, req *pbs.ListHostSetsRequest) (*pbs.ListHostSetsResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateListRequest(req); err != nil { + return nil, err + } + hl, err := s.listFromRepo(ctx, req.GetHostCatalogId()) + if err != nil { + return nil, err + } + for _, item := range hl { + item.Scope = authResults.Scope + } + return &pbs.ListHostSetsResponse{Items: hl}, nil +} + +// GetHostSet implements the interface pbs.HostSetServiceServer. +func (s Service) GetHostSet(ctx context.Context, req *pbs.GetHostSetRequest) (*pbs.GetHostSetResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateGetRequest(req); err != nil { + return nil, err + } + hc, err := s.getFromRepo(ctx, req.GetId()) + if err != nil { + return nil, err + } + hc.Scope = authResults.Scope + return &pbs.GetHostSetResponse{Item: hc}, nil +} + +// CreateHostSet implements the interface pbs.HostSetServiceServer. +func (s Service) CreateHostSet(ctx context.Context, req *pbs.CreateHostSetRequest) (*pbs.CreateHostSetResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateCreateRequest(req); err != nil { + return nil, err + } + h, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetHostCatalogId(), req.GetItem()) + if err != nil { + return nil, err + } + h.Scope = authResults.Scope + return &pbs.CreateHostSetResponse{ + Item: h, + Uri: fmt.Sprintf("scopes/%s/host-catalogs/%s/host-sets/%s", authResults.Scope.GetId(), req.GetHostCatalogId(), h.GetId()), + }, nil +} + +// UpdateHostSet implements the interface pbs.HostSetServiceServer. +func (s Service) UpdateHostSet(ctx context.Context, req *pbs.UpdateHostSetRequest) (*pbs.UpdateHostSetResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateUpdateRequest(req); err != nil { + return nil, err + } + hc, err := s.updateInRepo(ctx, authResults.Scope.GetId(), req.GetHostCatalogId(), req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem()) + if err != nil { + return nil, err + } + hc.Scope = authResults.Scope + return &pbs.UpdateHostSetResponse{Item: hc}, nil +} + +// DeleteHostSet implements the interface pbs.HostSetServiceServer. +func (s Service) DeleteHostSet(ctx context.Context, req *pbs.DeleteHostSetRequest) (*pbs.DeleteHostSetResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateDeleteRequest(req); err != nil { + return nil, err + } + existed, err := s.deleteFromRepo(ctx, authResults.Scope.GetId(), req.GetId()) + if err != nil { + return nil, err + } + return &pbs.DeleteHostSetResponse{Existed: existed}, nil +} + +// AddHostSetHosts implements the interface pbs.HostSetServiceServer. +func (s Service) AddHostSetHosts(ctx context.Context, req *pbs.AddHostSetHostsRequest) (*pbs.AddHostSetHostsResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateAddRequest(req); err != nil { + return nil, err + } + g, err := s.addInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetHostIds(), req.GetVersion()) + if err != nil { + return nil, err + } + return &pbs.AddHostSetHostsResponse{Item: g}, nil +} + +// SetHostSetHosts implements the interface pbs.HostSetServiceServer. +func (s Service) SetHostSetHosts(ctx context.Context, req *pbs.SetHostSetHostsRequest) (*pbs.SetHostSetHostsResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateSetRequest(req); err != nil { + return nil, err + } + g, err := s.setInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetHostIds(), req.GetVersion()) + if err != nil { + return nil, err + } + return &pbs.SetHostSetHostsResponse{Item: g}, nil +} + +// RemoveHostSetHosts implements the interface pbs.HostSetServiceServer. +func (s Service) RemoveHostSetHosts(ctx context.Context, req *pbs.RemoveHostSetHostsRequest) (*pbs.RemoveHostSetHostsResponse, error) { + authResults := auth.Verify(ctx) + if authResults.Error != nil { + return nil, authResults.Error + } + if err := validateRemoveRequest(req); err != nil { + return nil, err + } + g, err := s.removeInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetHostIds(), req.GetVersion()) + if err != nil { + return nil, err + } + return &pbs.RemoveHostSetHostsResponse{Item: g}, nil +} + +func (s Service) getFromRepo(ctx context.Context, id string) (*pb.HostSet, error) { + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + h, err := repo.LookupSet(ctx, id) + if err != nil { + return nil, err + } + if h == nil { + return nil, handlers.NotFoundErrorf("Host set %q doesn't exist.", id) + } + return toProto(h, nil), nil +} + +func (s Service) createInRepo(ctx context.Context, scopeId, catalogId string, item *pb.HostSet) (*pb.HostSet, error) { + var opts []static.Option + if item.GetName() != nil { + opts = append(opts, static.WithName(item.GetName().GetValue())) + } + if item.GetDescription() != nil { + opts = append(opts, static.WithDescription(item.GetDescription().GetValue())) + } + h, err := static.NewHostSet(catalogId, opts...) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to build host set for creation: %v.", err) + } + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + out, err := repo.CreateSet(ctx, scopeId, h) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to create host set: %v.", err) + } + if out == nil { + return nil, status.Error(codes.Internal, "Unable to create host set but no error returned from repository.") + } + return toProto(out, nil), nil +} + +func (s Service) updateInRepo(ctx context.Context, scopeId, catalogId, id string, mask []string, item *pb.HostSet) (*pb.HostSet, error) { + var opts []static.Option + if desc := item.GetDescription(); desc != nil { + opts = append(opts, static.WithDescription(desc.GetValue())) + } + if name := item.GetName(); name != nil { + opts = append(opts, static.WithName(name.GetValue())) + } + h, err := static.NewHostSet(catalogId, opts...) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to build host set for update: %v.", err) + } + h.PublicId = id + dbMask := maskManager.Translate(mask) + if len(dbMask) == 0 { + return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid paths provided in the update mask."}) + } + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + out, rowsUpdated, err := repo.UpdateSet(ctx, scopeId, h, item.GetVersion(), dbMask) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to update host set: %v.", err) + } + if rowsUpdated == 0 { + return nil, handlers.NotFoundErrorf("Host set %q doesn't exist.", id) + } + return toProto(out, nil), nil +} + +func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, error) { + repo, err := s.staticRepoFn() + if err != nil { + return false, err + } + rows, err := repo.DeleteSet(ctx, scopeId, id) + if err != nil { + return false, status.Errorf(codes.Internal, "Unable to delete host: %v.", err) + } + return rows > 0, nil +} + +func (s Service) listFromRepo(ctx context.Context, catalogId string) ([]*pb.HostSet, error) { + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + hl, err := repo.ListSets(ctx, catalogId) + if err != nil { + return nil, err + } + var outH []*pb.HostSet + for _, h := range hl { + outH = append(outH, toProto(h, nil)) + } + return outH, nil +} + +func (s Service) addInRepo(ctx context.Context, scopeId, setId string, hostIds []string, version uint32) (*pb.HostSet, error) { + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + // _, err = repo.AddHostSetMembers(ctx, setId, version, hostIds) + // if err != nil { + // return nil, status.Errorf(codes.Internal, "Unable to add members to group: %v.", err) + // } + out, err := repo.LookupSet(ctx, setId) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to look up group: %v.", err) + } + if out == nil { + return nil, status.Error(codes.Internal, "Unable to lookup group after adding member to it.") + } + return toProto(out, nil), nil +} + +func (s Service) setInRepo(ctx context.Context, scopeId, setId string, hostIds []string, version uint32) (*pb.HostSet, error) { + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + // _, _, err = repo.SetHostSetMembers(ctx, groupId, version, userIds) + // if err != nil { + // return nil, status.Errorf(codes.Internal, "Unable to set members on group: %v.", err) + // } + + out, err := repo.LookupSet(ctx, setId) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to look up group: %v.", err) + } + if out == nil { + return nil, status.Error(codes.Internal, "Unable to lookup group after setting members for it.") + } + return toProto(out, nil), nil +} + +func (s Service) removeInRepo(ctx context.Context, scopeId, setId string, hostIds []string, version uint32) (*pb.HostSet, error) { + repo, err := s.staticRepoFn() + if err != nil { + return nil, err + } + // _, err = repo.RemoveHostSetMembers(ctx, hostSetId, version, userIds) + // if err != nil { + // return nil, status.Errorf(codes.Internal, "Unable to remove members from group: %v.", err) + // } + out, err := repo.LookupSet(ctx, setId) + if err != nil { + return nil, status.Errorf(codes.Internal, "Unable to look up group: %v.", err) + } + if out == nil { + return nil, status.Error(codes.Internal, "Unable to lookup group after removing members from it.") + } + return toProto(out, nil), nil +} + +func toProto(in *static.HostSet, members []*static.HostSetMember) *pb.HostSet { + out := pb.HostSet{ + Id: in.GetPublicId(), + HostCatalogId: in.GetCatalogId(), + Type: host.StaticSubtype.String(), + CreatedTime: in.GetCreateTime().GetTimestamp(), + UpdatedTime: in.GetUpdateTime().GetTimestamp(), + Version: in.GetVersion(), + } + if in.GetDescription() != "" { + out.Description = wrapperspb.String(in.GetDescription()) + } + if in.GetName() != "" { + out.Name = wrapperspb.String(in.GetName()) + } + for _, m := range members { + out.HostIds = append(out.HostIds, m.GetHostId()) + } + return &out +} + +// A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce +// requirements on the structure of the request. They verify that: +// * The path passed in is correctly formatted +// * All required parameters are set +// * There are no conflicting parameters provided +// * The type asserted by the ID and/or field is known +// * If relevant, the type derived from the id prefix matches what is claimed by the type field +func validateGetRequest(req *pbs.GetHostSetRequest) error { + return handlers.ValidateGetRequest(static.HostSetPrefix, req, func() map[string]string { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + return badFields + }) +} + +func validateCreateRequest(req *pbs.CreateHostSetRequest) error { + return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + + if req.GetItem().GetHostCatalogId() != "" { + badFields["host_catalog_id"] = "This field is read only." + } + switch host.SubtypeFromId(req.GetHostCatalogId()) { + case host.StaticSubtype: + if req.GetItem().GetType() != "" && req.GetItem().GetType() != host.StaticSubtype.String() { + badFields["type"] = "Doesn't match the parent resource's type." + } + } + return badFields + }) +} + +func validateUpdateRequest(req *pbs.UpdateHostSetRequest) error { + return handlers.ValidateUpdateRequest(static.HostSetPrefix, req, req.GetItem(), func() map[string]string { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + if req.GetItem().GetHostCatalogId() != "" { + badFields["host_catalog_id"] = "This is a read only field and cannot be specified in an update request." + } + if req.GetItem().GetType() != "" { + badFields["type"] = "This is a read only field and cannot be specified in an update request." + } + return badFields + }) +} + +func validateDeleteRequest(req *pbs.DeleteHostSetRequest) error { + return handlers.ValidateDeleteRequest(static.HostSetPrefix, req, func() map[string]string { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + return badFields + }) +} + +func validateListRequest(req *pbs.ListHostSetsRequest) error { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields) + } + return nil +} + +func validateAddRequest(req *pbs.AddHostSetHostsRequest) error { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + if !handlers.ValidId(static.HostSetPrefix, req.GetId()) { + badFields["id"] = "Incorrectly formatted identifier." + } + if req.GetVersion() == 0 { + badFields["version"] = "Required field." + } + if len(req.GetHostIds()) == 0 { + badFields["host_ids"] = "Must be non-empty." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields) + } + return nil +} + +func validateSetRequest(req *pbs.SetHostSetHostsRequest) error { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + if !handlers.ValidId(static.HostSetPrefix, req.GetId()) { + badFields["id"] = "Incorrectly formatted identifier." + } + if req.GetVersion() == 0 { + badFields["version"] = "Required field." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields) + } + return nil +} + +func validateRemoveRequest(req *pbs.RemoveHostSetHostsRequest) error { + badFields := map[string]string{} + if !handlers.ValidId(static.HostCatalogPrefix, req.GetHostCatalogId()) { + badFields["host_catalog_id"] = "The field is incorrectly formatted." + } + if !handlers.ValidId(static.HostSetPrefix, req.GetId()) { + badFields["id"] = "Incorrectly formatted identifier." + } + if req.GetVersion() == 0 { + badFields["version"] = "Required field." + } + if len(req.GetHostIds()) == 0 { + badFields["host_ids"] = "Must be non-empty." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields) + } + return nil +} diff --git a/internal/servers/controller/handlers/host_sets/host_set_service_test.go b/internal/servers/controller/handlers/host_sets/host_set_service_test.go new file mode 100644 index 000000000..36b0a7b45 --- /dev/null +++ b/internal/servers/controller/handlers/host_sets/host_set_service_test.go @@ -0,0 +1,747 @@ +package host_sets_test + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/wrappers" + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/boundary/internal/auth" + "github.com/hashicorp/boundary/internal/db" + pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts" + "github.com/hashicorp/boundary/internal/gen/controller/api/resources/scopes" + pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" + "github.com/hashicorp/boundary/internal/host" + "github.com/hashicorp/boundary/internal/host/static" + "github.com/hashicorp/boundary/internal/iam" + "github.com/hashicorp/boundary/internal/kms" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/host_sets" + "github.com/hashicorp/boundary/internal/types/scope" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/genproto/protobuf/field_mask" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" +) + +func TestGet(t *testing.T) { + t.Parallel() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + + _, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) + + rw := db.New(conn) + repoFn := func() (*static.Repository, error) { + return static.NewRepository(rw, rw, kms) + } + hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] + h := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] + + toMerge := &pbs.GetHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + } + + pHost := &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + CreatedTime: h.CreateTime.GetTimestamp(), + UpdatedTime: h.UpdateTime.GetTimestamp(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Type: "static", + } + + cases := []struct { + name string + req *pbs.GetHostSetRequest + res *pbs.GetHostSetResponse + errCode codes.Code + }{ + { + name: "Get an Existing Host", + req: &pbs.GetHostSetRequest{Id: h.GetPublicId()}, + res: &pbs.GetHostSetResponse{Item: pHost}, + errCode: codes.OK, + }, + { + name: "Get a non existing Host Set", + req: &pbs.GetHostSetRequest{Id: static.HostSetPrefix + "_DoesntExis"}, + res: nil, + errCode: codes.NotFound, + }, + { + name: "Wrong id prefix", + req: &pbs.GetHostSetRequest{Id: "j_1234567890"}, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "space in id", + req: &pbs.GetHostSetRequest{Id: static.HostPrefix + "_1 23456789"}, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert := assert.New(t) + req := proto.Clone(toMerge).(*pbs.GetHostSetRequest) + proto.Merge(req, tc.req) + + s, err := host_sets.NewService(repoFn) + require.NoError(t, err, "Couldn't create a new host set service.") + + got, gErr := s.GetHostSet(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req) + assert.Equal(tc.errCode, status.Code(gErr), "GetHostSet(%+v) got error %v, wanted %v", req, gErr, tc.errCode) + + if tc.res != nil { + tc.res.Item.Version = 1 + } + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetHostSet(%q) got response %q, wanted %q", req, got, tc.res) + }) + } +} + +func TestList(t *testing.T) { + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + + _, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) + + rw := db.New(conn) + repoFn := func() (*static.Repository, error) { + return static.NewRepository(rw, rw, kms) + } + hcs := static.TestCatalogs(t, conn, proj.GetPublicId(), 2) + hc, hcNoHosts := hcs[0], hcs[1] + + var wantHs []*pb.HostSet + for _, h := range static.TestSets(t, conn, hc.GetPublicId(), 10) { + wantHs = append(wantHs, &pb.HostSet{ + Id: h.GetPublicId(), + HostCatalogId: h.GetCatalogId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + UpdatedTime: h.GetUpdateTime().GetTimestamp(), + Version: h.GetVersion(), + Type: host.StaticSubtype.String(), + }) + } + + cases := []struct { + name string + hostCatalogId string + res *pbs.ListHostSetsResponse + errCode codes.Code + }{ + { + name: "List Many Host Sets", + hostCatalogId: hc.GetPublicId(), + res: &pbs.ListHostSetsResponse{Items: wantHs}, + errCode: codes.OK, + }, + { + name: "List No Host Sets", + hostCatalogId: hcNoHosts.GetPublicId(), + res: &pbs.ListHostSetsResponse{}, + errCode: codes.OK, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + s, err := host_sets.NewService(repoFn) + require.NoError(err, "Couldn't create new host set service.") + + got, gErr := s.ListHostSets(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), &pbs.ListHostSetsRequest{HostCatalogId: tc.hostCatalogId}) + assert.Equal(tc.errCode, status.Code(gErr), "ListHostSets(%q) got error %v, wanted %v", tc.hostCatalogId, gErr, tc.errCode) + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListHostSets(%q) got response %q, wanted %q", tc.hostCatalogId, got, tc.res) + }) + } +} + +func TestDelete(t *testing.T) { + t.Parallel() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + + _, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) + + rw := db.New(conn) + repoFn := func() (*static.Repository, error) { + return static.NewRepository(rw, rw, kms) + } + hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] + h := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] + + s, err := host_sets.NewService(repoFn) + require.NoError(t, err, "Couldn't create a new host set service.") + + cases := []struct { + name string + scopeId string + req *pbs.DeleteHostSetRequest + res *pbs.DeleteHostSetResponse + errCode codes.Code + }{ + { + name: "Delete an Existing Host", + scopeId: proj.GetPublicId(), + req: &pbs.DeleteHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + }, + res: &pbs.DeleteHostSetResponse{ + Existed: true, + }, + errCode: codes.OK, + }, + { + name: "Delete bad id Host", + scopeId: proj.GetPublicId(), + req: &pbs.DeleteHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + Id: static.HostSetPrefix + "_doesntexis", + }, + res: &pbs.DeleteHostSetResponse{ + Existed: false, + }, + errCode: codes.OK, + }, + { + name: "Delete bad host catalog id in Host", + scopeId: proj.GetPublicId(), + req: &pbs.DeleteHostSetRequest{ + HostCatalogId: static.HostCatalogPrefix + "_doesntexis", + Id: h.GetPublicId(), + }, + res: &pbs.DeleteHostSetResponse{ + Existed: false, + }, + errCode: codes.OK, + }, + { + name: "Bad Host Id formatting", + scopeId: proj.GetPublicId(), + req: &pbs.DeleteHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + Id: static.HostSetPrefix + "_bad_format", + }, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert := assert.New(t) + got, gErr := s.DeleteHostSet(auth.DisabledAuthTestContext(auth.WithScopeId(tc.scopeId)), tc.req) + assert.Equal(tc.errCode, status.Code(gErr), "DeleteHostSet(%+v) got error %v, wanted %v", tc.req, gErr, tc.errCode) + assert.Empty(cmp.Diff(tc.res, got, protocmp.Transform()), "DeleteHostSet(%q) got response %q, wanted %q", tc.req, got, tc.res) + }) + } +} + +func TestDelete_twice(t *testing.T) { + t.Parallel() + assert := assert.New(t) + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + + _, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) + + rw := db.New(conn) + repoFn := func() (*static.Repository, error) { + return static.NewRepository(rw, rw, kms) + } + hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] + h := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] + + s, err := host_sets.NewService(repoFn) + require.NoError(t, err, "Couldn't create a new host set service.") + req := &pbs.DeleteHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + } + ctx := auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())) + got, gErr := s.DeleteHostSet(ctx, req) + assert.NoError(gErr, "First attempt") + assert.True(got.GetExisted(), "Expected existed to be true for the first delete.") + got, gErr = s.DeleteHostSet(ctx, req) + assert.NoError(gErr, "Second attempt") + assert.False(got.GetExisted(), "Expected existed to be false for the second delete.") +} + +func TestCreate(t *testing.T) { + t.Parallel() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + + _, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) + + rw := db.New(conn) + repoFn := func() (*static.Repository, error) { + return static.NewRepository(rw, rw, kms) + } + hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] + + toMerge := &pbs.CreateHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + } + + defaultHcCreated, err := ptypes.Timestamp(hc.GetCreateTime().GetTimestamp()) + require.NoError(t, err) + + cases := []struct { + name string + req *pbs.CreateHostSetRequest + res *pbs.CreateHostSetResponse + errCode codes.Code + }{ + { + name: "Create a valid Host", + req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "name"}, + Description: &wrappers.StringValue{Value: "desc"}, + Type: "static", + }}, + res: &pbs.CreateHostSetResponse{ + Uri: fmt.Sprintf("scopes/%s/host-catalogs/%s/host-sets/%s_", proj.GetPublicId(), hc.GetPublicId(), static.HostSetPrefix), + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "name"}, + Description: &wrappers.StringValue{Value: "desc"}, + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Create with unknown type", + req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "name"}, + Description: &wrappers.StringValue{Value: "desc"}, + Type: "ThisIsMadeUp", + }}, + errCode: codes.InvalidArgument, + }, + { + name: "Create with no type", + req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "no type name"}, + Description: &wrappers.StringValue{Value: "no type desc"}, + }}, + res: &pbs.CreateHostSetResponse{ + Uri: fmt.Sprintf("scopes/%s/host-catalogs/%s/host-sets/%s_", proj.GetPublicId(), hc.GetPublicId(), static.HostSetPrefix), + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "no type name"}, + Description: &wrappers.StringValue{Value: "no type desc"}, + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Can't specify Id", + req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ + Id: "not allowed to be set", + }}, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Can't specify Created Time", + req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ + CreatedTime: ptypes.TimestampNow(), + }}, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Can't specify Update Time", + req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ + UpdatedTime: ptypes.TimestampNow(), + }}, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + req := proto.Clone(toMerge).(*pbs.CreateHostSetRequest) + proto.Merge(req, tc.req) + + s, err := host_sets.NewService(repoFn) + require.NoError(err, "Failed to create a new host set service.") + + got, gErr := s.CreateHostSet(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req) + assert.Equal(tc.errCode, status.Code(gErr), "CreateHostSet(%+v) got error %v, wanted %v", req, gErr, tc.errCode) + if got != nil { + assert.Contains(got.GetUri(), tc.res.GetUri()) + assert.True(strings.HasPrefix(got.GetItem().GetId(), static.HostPrefix)) + gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime()) + require.NoError(err, "Error converting proto to timestamp.") + gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) + require.NoError(err, "Error converting proto to timestamp") + // Verify it is a set created after the test setup's default set + assert.True(gotCreateTime.After(defaultHcCreated), "New set should have been created after default set. Was created %v, which is after %v", gotCreateTime, defaultHcCreated) + assert.True(gotUpdateTime.After(defaultHcCreated), "New set should have been updated after default set. Was updated %v, which is after %v", gotUpdateTime, defaultHcCreated) + + // Clear all values which are hard to compare against. + got.Uri, tc.res.Uri = "", "" + got.Item.Id, tc.res.Item.Id = "", "" + got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil + } + if tc.res != nil { + tc.res.Item.Version = 1 + } + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "CreateHostSet(%q) got response %q, wanted %q", req, got, tc.res) + }) + } +} + +func TestUpdate(t *testing.T) { + t.Parallel() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + + _, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) + + rw := db.New(conn) + repoFn := func() (*static.Repository, error) { + return static.NewRepository(rw, rw, kms) + } + repo, err := repoFn() + require.NoError(t, err, "Couldn't create new static repo.") + + hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] + + h, err := static.NewHostSet(hc.GetPublicId(), static.WithName("default"), static.WithDescription("default")) + require.NoError(t, err) + h, err = repo.CreateSet(context.Background(), proj.GetPublicId(), h) + require.NoError(t, err) + + var version uint32 = 1 + + resetHostSet := func() { + version++ + _, _, err = repo.UpdateSet(context.Background(), proj.GetPublicId(), h, version, []string{"Name", "Description"}) + require.NoError(t, err, "Failed to reset host.") + version++ + } + + hCreated, err := ptypes.Timestamp(h.GetCreateTime().GetTimestamp()) + require.NoError(t, err, "Failed to convert proto to timestamp") + toMerge := &pbs.UpdateHostSetRequest{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + } + + tested, err := host_sets.NewService(repoFn) + require.NoError(t, err, "Failed to create a new host set service.") + + cases := []struct { + name string + req *pbs.UpdateHostSetRequest + res *pbs.UpdateHostSetResponse + errCode codes.Code + }{ + { + name: "Update an Existing Host", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name", "description"}, + }, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + }, + }, + res: &pbs.UpdateHostSetResponse{ + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Multiple Paths in single string", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name,description"}, + }, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + }, + }, + res: &pbs.UpdateHostSetResponse{ + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "No Update Mask", + req: &pbs.UpdateHostSetRequest{ + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "updated name"}, + Description: &wrappers.StringValue{Value: "updated desc"}, + }, + }, + errCode: codes.InvalidArgument, + }, + { + name: "Empty Path", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{Paths: []string{}}, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "updated name"}, + Description: &wrappers.StringValue{Value: "updated desc"}, + }, + }, + errCode: codes.InvalidArgument, + }, + { + name: "Only non-existant paths in Mask", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{Paths: []string{"nonexistant_field"}}, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "updated name"}, + Description: &wrappers.StringValue{Value: "updated desc"}, + }, + }, + errCode: codes.InvalidArgument, + }, + { + name: "Unset Name", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name"}, + }, + Item: &pb.HostSet{ + Description: &wrappers.StringValue{Value: "ignored"}, + }, + }, + res: &pbs.UpdateHostSetResponse{ + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Description: &wrappers.StringValue{Value: "default"}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Unset Description", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"description"}, + }, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "ignored"}, + }, + }, + res: &pbs.UpdateHostSetResponse{ + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "default"}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Update Only Name", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name"}, + }, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "updated"}, + Description: &wrappers.StringValue{Value: "ignored"}, + }, + }, + res: &pbs.UpdateHostSetResponse{ + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "updated"}, + Description: &wrappers.StringValue{Value: "default"}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Update Only Description", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"description"}, + }, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "ignored"}, + Description: &wrappers.StringValue{Value: "notignored"}, + }, + }, + res: &pbs.UpdateHostSetResponse{ + Item: &pb.HostSet{ + HostCatalogId: hc.GetPublicId(), + Id: h.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "default"}, + Description: &wrappers.StringValue{Value: "notignored"}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + Type: "static", + }, + }, + errCode: codes.OK, + }, + { + name: "Update a Non Existing Host Set", + req: &pbs.UpdateHostSetRequest{ + Id: static.HostSetPrefix + "_DoesntExis", + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"description"}, + }, + Item: &pb.HostSet{ + Name: &wrappers.StringValue{Value: "new"}, + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Description: &wrappers.StringValue{Value: "desc"}, + }, + }, + errCode: codes.Internal, + }, + { + name: "Cant change Id", + req: &pbs.UpdateHostSetRequest{ + Id: hc.GetPublicId(), + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"id"}, + }, + Item: &pb.HostSet{ + Id: "p_somethinge", + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "new desc"}, + }}, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Cant specify Created Time", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"created_time"}, + }, + Item: &pb.HostSet{ + CreatedTime: ptypes.TimestampNow(), + }, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Cant specify Updated Time", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"updated_time"}, + }, + Item: &pb.HostSet{ + UpdatedTime: ptypes.TimestampNow(), + }, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + { + name: "Valid mask, cant specify type", + req: &pbs.UpdateHostSetRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name"}, + }, + Item: &pb.HostSet{ + Type: "Unknown", + }, + }, + res: nil, + errCode: codes.InvalidArgument, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + tc.req.Item.Version = version + + req := proto.Clone(toMerge).(*pbs.UpdateHostSetRequest) + proto.Merge(req, tc.req) + + // Test some bad versions + req.Item.Version = version + 2 + _, gErr := tested.UpdateHostSet(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req) + require.Error(gErr) + req.Item.Version = version - 1 + _, gErr = tested.UpdateHostSet(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req) + require.Error(gErr) + req.Item.Version = version + + got, gErr := tested.UpdateHostSet(auth.DisabledAuthTestContext(auth.WithScopeId(proj.GetPublicId())), req) + assert.Equal(tc.errCode, status.Code(gErr), "UpdateHostSet(%+v) got error %v, wanted %v", req, gErr, tc.errCode) + + if tc.errCode == codes.OK { + defer resetHostSet() + } + + if got != nil { + assert.NotNilf(tc.res, "Expected UpdateHost response to be nil, but was %v", got) + gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) + require.NoError(err, "Failed to convert proto to timestamp") + // Verify it is a set updated after it was created + // TODO: This is currently failing. + assert.True(gotUpdateTime.After(hCreated), "Updated set should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, hCreated) + + // Clear all values which are hard to compare against. + got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil + } + if tc.res != nil { + tc.res.Item.Version = version + 1 + } + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "UpdateHostSet(%q) got response %q, wanted %q", req, got, tc.res) + }) + } +} diff --git a/internal/servers/controller/handlers/hosts/host_service_test.go b/internal/servers/controller/handlers/hosts/host_service_test.go index 11bdf906c..181539c65 100644 --- a/internal/servers/controller/handlers/hosts/host_service_test.go +++ b/internal/servers/controller/handlers/hosts/host_service_test.go @@ -30,7 +30,6 @@ import ( "google.golang.org/protobuf/types/known/structpb" ) -// TODO: Uncomment all the valid test cases. func TestGet(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") @@ -361,10 +360,26 @@ func TestCreate(t *testing.T) { { name: "Create with no type", req: &pbs.CreateHostRequest{Item: &pb.Host{ - Name: &wrappers.StringValue{Value: "name"}, - Description: &wrappers.StringValue{Value: "desc"}, + Name: &wrappers.StringValue{Value: "no type name"}, + Description: &wrappers.StringValue{Value: "no type desc"}, + Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ + "address": structpb.NewStringValue("123.456.789"), + }}, }}, - errCode: codes.InvalidArgument, + res: &pbs.CreateHostResponse{ + Uri: fmt.Sprintf("scopes/%s/host-catalogs/%s/hosts/%s_", proj.GetPublicId(), hc.GetPublicId(), static.HostPrefix), + Item: &pb.Host{ + HostCatalogId: hc.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "no type name"}, + Description: &wrappers.StringValue{Value: "no type desc"}, + Type: "static", + Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ + "address": structpb.NewStringValue("123.456.789"), + }}, + }, + }, + errCode: codes.OK, }, { name: "Can't specify Id", @@ -410,8 +425,8 @@ func TestCreate(t *testing.T) { gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) require.NoError(err, "Error converting proto to timestamp") // Verify it is a set created after the test setup's default set - assert.True(gotCreateTime.After(defaultHcCreated), "New set should have been created after default set. Was created %v, which is after %v", gotCreateTime, defaultHcCreated) - assert.True(gotUpdateTime.After(defaultHcCreated), "New set should have been updated after default set. Was updated %v, which is after %v", gotUpdateTime, defaultHcCreated) + assert.True(gotCreateTime.After(defaultHcCreated), "New host should have been created after default host. Was created %v, which is after %v", gotCreateTime, defaultHcCreated) + assert.True(gotUpdateTime.After(defaultHcCreated), "New host should have been updated after default host. Was updated %v, which is after %v", gotUpdateTime, defaultHcCreated) // Clear all values which are hard to compare against. got.Uri, tc.res.Uri = "", ""