Move default port to a TCP target attribute (#361)

This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-09-15 15:20:49 -04:00
1 parent b56e5b6766
commit f4ad22b247
15 files changed
+358 -114

No files matched your search

+5
View File
@@ -342,4 +342,9 @@ var inputStructs = []*structInfo{
typeOnCreate: true,
createResponseTypes: true,
},
{
inProto: &targets.TcpTargetAttributes{},
outFile: "targets/tcp_target_attributes.gen.go",
subtypeName: "TcpTarget",
},
}
+28 -4
View File
@@ -45,15 +45,39 @@ func WithAutomaticVersioning(enable bool) Option {
}
}
func WithDefaultPort(inDefaultPort uint32) Option {
func WithAttributes(inAttributes map[string]interface{}) Option {
return func(o *options) {
o.postMap["default_port"] = inDefaultPort
o.postMap["attributes"] = inAttributes
}
}
func DefaultDefaultPort() Option {
func DefaultAttributes() Option {
return func(o *options) {
o.postMap["default_port"] = nil
o.postMap["attributes"] = nil
}
}
func WithTcpTargetDefaultPort(inDefaultPort uint32) Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = interface{}(map[string]interface{}{})
}
val := raw.(map[string]interface{})
val["default_port"] = inDefaultPort
o.postMap["attributes"] = val
}
}
func DefaultTcpTargetDefaultPort() Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = interface{}(map[string]interface{}{})
}
val := raw.(map[string]interface{})
val["default_port"] = nil
o.postMap["attributes"] = val
}
}
+12 -12
View File
@@ -16,18 +16,18 @@ import (
)
type Target struct {
Id string `json:"id,omitempty"`
ScopeId string `json:"scope_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"`
HostSetIds []string `json:"host_set_ids,omitempty"`
HostSets []*HostSet `json:"host_sets,omitempty"`
DefaultPort uint32 `json:"default_port,omitempty"`
Id string `json:"id,omitempty"`
ScopeId string `json:"scope_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"`
HostSetIds []string `json:"host_set_ids,omitempty"`
HostSets []*HostSet `json:"host_sets,omitempty"`
Attributes map[string]interface{} `json:"attributes,omitempty"`
responseBody *bytes.Buffer
responseMap map[string]interface{}
+6
View File
@@ -0,0 +1,6 @@
// Code generated by "make api"; DO NOT EDIT.
package targets
type TcpTargetAttributes struct {
DefaultPort uint32 `json:"default_port,omitempty"`
}
+31 -2
View File
@@ -19,7 +19,6 @@ func generateTargetTableOutput(in *targets.Target) string {
"Type": in.Type,
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
"Default Port": in.DefaultPort,
}
if in.Name != "" {
@@ -35,6 +34,19 @@ func generateTargetTableOutput(in *targets.Target) string {
maxLength = len(k)
}
}
if len(in.Attributes) > 0 {
for k, v := range in.Attributes {
if attributeMap[k] != "" {
in.Attributes[attributeMap[k]] = v
delete(in.Attributes, k)
}
}
for k := range in.Attributes {
if len(k) > maxLength {
maxLength = len(k)
}
}
}
var hostSetMaps []map[string]interface{}
if len(in.HostSets) > 0 {
@@ -68,9 +80,24 @@ func generateTargetTableOutput(in *targets.Target) string {
}
}
if len(in.Attributes) > 0 {
if true {
ret = append(ret,
fmt.Sprintf(" Attributes: %s", ""),
)
}
ret = append(ret,
base.WrapMap(4, maxLength, in.Attributes),
)
}
return base.WrapForHelpText(ret)
}
var attributeMap = map[string]string{
"default_port": "Default Port",
}
func exampleOutput() string {
in := &targets.Target{
Id: "ttcp_1234567890",
@@ -95,7 +122,9 @@ func exampleOutput() string {
HostCatalogId: "hcst_1234567890",
},
},
DefaultPort: 22,
Attributes: map[string]interface{}{
"default_port": 22,
},
}
return generateTargetTableOutput(in)
}
+2 -2
View File
@@ -138,14 +138,14 @@ func (c *TcpCommand) Run(args []string) int {
switch c.flagDefaultPort {
case "":
case "null":
opts = append(opts, targets.DefaultDefaultPort())
opts = append(opts, targets.DefaultTcpTargetDefaultPort())
default:
port, err := strconv.ParseUint(c.flagDefaultPort, 10, 32)
if err != nil {
c.UI.Error(fmt.Sprintf("Error parsing %q: %s", c.flagDefaultPort, err))
return 1
}
opts = append(opts, targets.WithDefaultPort(uint32(port)))
opts = append(opts, targets.WithTcpTargetDefaultPort(uint32(port)))
}
targetClient := targets.NewClient(client)
+3 -4
View File
@@ -2931,10 +2931,9 @@
"description": "The host sets that make up this target.\nOutput only.",
"readOnly": true
},
"default_port": {
"type": "integer",
"format": "int64",
"description": "The default port a target should use if present."
"attributes": {
"type": "object",
"description": "The attributes that are applied for the specific Target type."
}
},
"title": "Target contains all fields related to a Target resource"
@@ -8,7 +8,7 @@ package targets
import (
proto "github.com/golang/protobuf/proto"
_ "github.com/golang/protobuf/ptypes/struct"
_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"
@@ -119,8 +119,8 @@ type Target struct {
// The host sets that make up this target.
// Output only.
HostSets []*HostSet `protobuf:"bytes,110,rep,name=host_sets,json=hostSets,proto3" json:"host_sets,omitempty"`
// The default port a target should use if present.
DefaultPort *wrappers.UInt32Value `protobuf:"bytes,120,opt,name=default_port,json=defaultPort,proto3" json:"default_port,omitempty"`
// The attributes that are applied for the specific Target type.
Attributes *_struct.Struct `protobuf:"bytes,120,opt,name=attributes,proto3" json:"attributes,omitempty"`
}
func (x *Target) Reset() {
@@ -232,7 +232,54 @@ func (x *Target) GetHostSets() []*HostSet {
return nil
}
func (x *Target) GetDefaultPort() *wrappers.UInt32Value {
func (x *Target) GetAttributes() *_struct.Struct {
if x != nil {
return x.Attributes
}
return nil
}
type TcpTargetAttributes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DefaultPort *wrappers.UInt32Value `protobuf:"bytes,10,opt,name=default_port,json=defaultPort,proto3" json:"default_port,omitempty"`
}
func (x *TcpTargetAttributes) Reset() {
*x = TcpTargetAttributes{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_api_resources_targets_v1_target_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TcpTargetAttributes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TcpTargetAttributes) ProtoMessage() {}
func (x *TcpTargetAttributes) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_resources_targets_v1_target_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TcpTargetAttributes.ProtoReflect.Descriptor instead.
func (*TcpTargetAttributes) Descriptor() ([]byte, []int) {
return file_controller_api_resources_targets_v1_target_proto_rawDescGZIP(), []int{2}
}
func (x *TcpTargetAttributes) GetDefaultPort() *wrappers.UInt32Value {
if x != nil {
return x.DefaultPort
}
@@ -263,7 +310,7 @@ var file_controller_api_resources_targets_v1_target_proto_rawDesc = []byte{
0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a,
0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64,
0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61,
0x6c, 0x6f, 0x67, 0x49, 0x64, 0x22, 0xa6, 0x05, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x6c, 0x6f, 0x67, 0x49, 0x64, 0x22, 0xff, 0x04, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05,
@@ -299,19 +346,25 @@ var file_controller_api_resources_targets_v1_target_proto_rawDesc = []byte{
0x32, 0x2c, 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, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x52, 0x08,
0x68, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x78, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x23, 0xa0, 0xda,
0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1b, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f,
0x70, 0x6f, 0x72, 0x74, 0x12, 0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72,
0x74, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x42, 0x55,
0x5a, 0x53, 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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x3b, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x68, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 0x3d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x78, 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, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x13, 0x54, 0x63, 0x70, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12,
0x6f, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x42, 0x2e, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x26, 0x0a, 0x17, 0x61,
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50,
0x6f, 0x72, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74,
0x42, 0x55, 0x5a, 0x53, 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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x3b,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -326,28 +379,31 @@ func file_controller_api_resources_targets_v1_target_proto_rawDescGZIP() []byte
return file_controller_api_resources_targets_v1_target_proto_rawDescData
}
var file_controller_api_resources_targets_v1_target_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_controller_api_resources_targets_v1_target_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_controller_api_resources_targets_v1_target_proto_goTypes = []interface{}{
(*HostSet)(nil), // 0: controller.api.resources.targets.v1.HostSet
(*Target)(nil), // 1: controller.api.resources.targets.v1.Target
(*scopes.ScopeInfo)(nil), // 2: controller.api.resources.scopes.v1.ScopeInfo
(*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue
(*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp
(*wrappers.UInt32Value)(nil), // 5: google.protobuf.UInt32Value
(*TcpTargetAttributes)(nil), // 2: controller.api.resources.targets.v1.TcpTargetAttributes
(*scopes.ScopeInfo)(nil), // 3: controller.api.resources.scopes.v1.ScopeInfo
(*wrappers.StringValue)(nil), // 4: google.protobuf.StringValue
(*timestamp.Timestamp)(nil), // 5: google.protobuf.Timestamp
(*_struct.Struct)(nil), // 6: google.protobuf.Struct
(*wrappers.UInt32Value)(nil), // 7: google.protobuf.UInt32Value
}
var file_controller_api_resources_targets_v1_target_proto_depIdxs = []int32{
2, // 0: controller.api.resources.targets.v1.Target.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
3, // 1: controller.api.resources.targets.v1.Target.name:type_name -> google.protobuf.StringValue
3, // 2: controller.api.resources.targets.v1.Target.description:type_name -> google.protobuf.StringValue
4, // 3: controller.api.resources.targets.v1.Target.created_time:type_name -> google.protobuf.Timestamp
4, // 4: controller.api.resources.targets.v1.Target.updated_time:type_name -> google.protobuf.Timestamp
3, // 0: controller.api.resources.targets.v1.Target.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
4, // 1: controller.api.resources.targets.v1.Target.name:type_name -> google.protobuf.StringValue
4, // 2: controller.api.resources.targets.v1.Target.description:type_name -> google.protobuf.StringValue
5, // 3: controller.api.resources.targets.v1.Target.created_time:type_name -> google.protobuf.Timestamp
5, // 4: controller.api.resources.targets.v1.Target.updated_time:type_name -> google.protobuf.Timestamp
0, // 5: controller.api.resources.targets.v1.Target.host_sets:type_name -> controller.api.resources.targets.v1.HostSet
5, // 6: controller.api.resources.targets.v1.Target.default_port:type_name -> google.protobuf.UInt32Value
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
6, // 6: controller.api.resources.targets.v1.Target.attributes:type_name -> google.protobuf.Struct
7, // 7: controller.api.resources.targets.v1.TcpTargetAttributes.default_port:type_name -> google.protobuf.UInt32Value
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_controller_api_resources_targets_v1_target_proto_init() }
@@ -380,6 +436,18 @@ func file_controller_api_resources_targets_v1_target_proto_init() {
return nil
}
}
file_controller_api_resources_targets_v1_target_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TcpTargetAttributes); 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{
@@ -387,7 +455,7 @@ func file_controller_api_resources_targets_v1_target_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_api_resources_targets_v1_target_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
@@ -56,6 +56,10 @@ message Target {
// Output only.
repeated HostSet host_sets = 110;
// The default port a target should use if present.
google.protobuf.UInt32Value default_port = 120 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this:"default_port" that: "DefaultPort"}];
// The attributes that are applied for the specific Target type.
google.protobuf.Struct attributes = 120 [(custom_options.v1.generate_sdk_option) = true];
}
message TcpTargetAttributes {
google.protobuf.UInt32Value default_port = 10 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this:"attributes.default_port" that: "DefaultPort"}];
}
@@ -100,6 +100,6 @@ message TcpTarget {
// @inject_tag: `gorm:"default:null"`
uint32 default_port = 80 [(custom_options.v1.mask_mapping) = {
this: "DefaultPort"
that: "default_port"
that: "attributes.default_port"
}];
}
@@ -6,6 +6,8 @@ import (
structpb "github.com/golang/protobuf/ptypes/struct"
"github.com/google/go-cmp/cmp"
accountspb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/accounts"
hostspb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts"
targetspb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/targets"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protojson"
@@ -25,6 +27,16 @@ func TestStructToProtoToStruct(t *testing.T) {
pb: &accountspb.PasswordAccountAttributes{LoginName: "testun", Password: &wrapperspb.StringValue{Value: "testpw"}},
wantJson: `{"login_name": "testun", "password": "testpw"}`,
},
{
name: "tcp",
pb: &targetspb.TcpTargetAttributes{DefaultPort: &wrapperspb.UInt32Value{Value: 22}},
wantJson: `{"default_port": 22}`,
},
{
name: "host",
pb: &hostspb.StaticHostAttributes{Address: &wrapperspb.StringValue{Value: "::1"}},
wantJson: `{"address": "::1"}`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
@@ -35,9 +47,9 @@ func TestStructToProtoToStruct(t *testing.T) {
require.NoError(t, protojson.Unmarshal([]byte(tc.wantJson), wantStruct))
assert.Empty(t, cmp.Diff(wantStruct, st, protocmp.Transform()))
newPwAttr := tc.pb.ProtoReflect().New().Interface()
StructToProto(st, newPwAttr)
assert.Equal(t, tc.pb, newPwAttr)
newAttr := tc.pb.ProtoReflect().New().Interface()
StructToProto(st, newAttr)
assert.Equal(t, tc.pb, newAttr)
})
}
}
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/golang/protobuf/ptypes/wrappers"
"github.com/hashicorp/boundary/internal/auth"
"github.com/hashicorp/boundary/internal/db"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/targets"
@@ -27,7 +28,7 @@ var (
func init() {
var err error
if maskManager, err = handlers.NewMaskManager(&store.TcpTarget{}, &pb.Target{}); err != nil {
if maskManager, err = handlers.NewMaskManager(&store.TcpTarget{}, &pb.Target{}, &pb.TcpTargetAttributes{}); err != nil {
panic(err)
}
}
@@ -203,7 +204,7 @@ func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Target, error)
if u == nil {
return nil, handlers.NotFoundErrorf("Target %q doesn't exist.", id)
}
return toProto(u, m), nil
return toProto(u, m)
}
func (s Service) createInRepo(ctx context.Context, item *pb.Target) (*pb.Target, error) {
@@ -211,8 +212,12 @@ func (s Service) createInRepo(ctx context.Context, item *pb.Target) (*pb.Target,
if item.GetDescription() != nil {
opts = append(opts, target.WithDescription(item.GetDescription().GetValue()))
}
if item.GetDefaultPort().GetValue() != 0 {
opts = append(opts, target.WithDefaultPort(item.GetDefaultPort().GetValue()))
tcpAttrs := &pb.TcpTargetAttributes{}
if err := handlers.StructToProto(item.GetAttributes(), tcpAttrs); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Provided attributes don't match expected format.")
}
if tcpAttrs.GetDefaultPort().GetValue() != 0 {
opts = append(opts, target.WithDefaultPort(tcpAttrs.GetDefaultPort().GetValue()))
}
u, err := target.NewTcpTarget(item.GetScopeId(), opts...)
if err != nil {
@@ -229,7 +234,7 @@ func (s Service) createInRepo(ctx context.Context, item *pb.Target) (*pb.Target,
if out == nil {
return nil, status.Error(codes.Internal, "Unable to create target but no error returned from repository.")
}
return toProto(out, m), nil
return toProto(out, m)
}
func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []string, item *pb.Target) (*pb.Target, error) {
@@ -240,8 +245,13 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st
if name := item.GetName(); name != nil {
opts = append(opts, target.WithName(name.GetValue()))
}
if item.GetDefaultPort().GetValue() != 0 {
opts = append(opts, target.WithDefaultPort(item.GetDefaultPort().GetValue()))
tcpAttrs := &pb.TcpTargetAttributes{}
if err := handlers.StructToProto(item.GetAttributes(), tcpAttrs); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Provided attributes don't match expected format.")
}
if tcpAttrs.GetDefaultPort().GetValue() != 0 {
opts = append(opts, target.WithDefaultPort(tcpAttrs.GetDefaultPort().GetValue()))
}
version := item.GetVersion()
u, err := target.NewTcpTarget(scopeId, opts...)
@@ -264,7 +274,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st
if rowsUpdated == 0 {
return nil, handlers.NotFoundErrorf("Target %q doesn't exist.", id)
}
return toProto(out, m), nil
return toProto(out, m)
}
func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) {
@@ -293,7 +303,11 @@ func (s Service) listFromRepo(ctx context.Context, scopeId string) ([]*pb.Target
}
var outUl []*pb.Target
for _, u := range ul {
outUl = append(outUl, toProto(u, nil))
o, err := toProto(u, nil)
if err != nil {
return nil, status.Errorf(codes.Internal, "Unable to convert value to proto: %v.", err)
}
outUl = append(outUl, o)
}
return outUl, nil
}
@@ -310,7 +324,7 @@ func (s Service) addInRepo(ctx context.Context, targetId string, hostSetId []str
if out == nil {
return nil, status.Error(codes.Internal, "Unable to lookup target after adding host sets to it.")
}
return toProto(out, m), nil
return toProto(out, m)
}
func (s Service) setInRepo(ctx context.Context, targetId string, hostSetIds []string, version uint32) (*pb.Target, error) {
@@ -330,7 +344,7 @@ func (s Service) setInRepo(ctx context.Context, targetId string, hostSetIds []st
if out == nil {
return nil, status.Error(codes.Internal, "Unable to lookup target after setting host sets for it.")
}
return toProto(out, m), nil
return toProto(out, m)
}
func (s Service) removeInRepo(ctx context.Context, targetId string, hostSetIds []string, version uint32) (*pb.Target, error) {
@@ -349,7 +363,7 @@ func (s Service) removeInRepo(ctx context.Context, targetId string, hostSetIds [
if out == nil {
return nil, status.Error(codes.Internal, "Unable to lookup target after removing host sets from it.")
}
return toProto(out, m), nil
return toProto(out, m)
}
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
@@ -396,7 +410,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.
return auth.Verify(ctx, opts...)
}
func toProto(in target.Target, m []*target.TargetSet) *pb.Target {
func toProto(in target.Target, m []*target.TargetSet) (*pb.Target, error) {
out := pb.Target{
Id: in.GetPublicId(),
ScopeId: in.GetScopeId(),
@@ -411,9 +425,15 @@ func toProto(in target.Target, m []*target.TargetSet) *pb.Target {
if in.GetName() != "" {
out.Name = wrapperspb.String(in.GetName())
}
if in.GetDefaultPort() != 0 {
out.DefaultPort = wrapperspb.UInt32(in.GetDefaultPort())
attrs := &pb.TcpTargetAttributes{}
if in.GetDefaultPort() > 0 {
attrs.DefaultPort = &wrappers.UInt32Value{Value: in.GetDefaultPort()}
}
st, err := handlers.ProtoToStruct(attrs)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed building password attribute struct: %v", err)
}
out.Attributes = st
for _, hs := range m {
out.HostSetIds = append(out.HostSetIds, hs.GetPublicId())
out.HostSets = append(out.HostSets, &pb.HostSet{
@@ -421,7 +441,7 @@ func toProto(in target.Target, m []*target.TargetSet) *pb.Target {
HostCatalogId: hs.GetCatalogId(),
})
}
return &out
return &out, nil
}
// A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce
@@ -442,8 +462,15 @@ func validateCreateRequest(req *pbs.CreateTargetRequest) error {
if req.GetItem().GetName() == nil || req.GetItem().GetName().GetValue() == "" {
badFields["name"] = "This field is required."
}
if req.GetItem().GetDefaultPort() != nil && req.GetItem().GetDefaultPort().GetValue() == 0 {
badFields["default_port"] = "This optional field cannot be set to 0."
switch target.SubtypeFromType(req.GetItem().GetType()) {
case target.TcpSubType:
tcpAttrs := &pb.TcpTargetAttributes{}
if err := handlers.StructToProto(req.GetItem().GetAttributes(), tcpAttrs); err != nil {
badFields["attributes"] = "Attribute fields do not match the expected format."
}
if tcpAttrs.GetDefaultPort() != nil && tcpAttrs.GetDefaultPort().GetValue() == 0 {
badFields["attributes.default_port"] = "This optional field cannot be set to 0."
}
}
switch req.GetItem().GetType() {
case target.TcpTargetType.String():
@@ -462,8 +489,16 @@ func validateUpdateRequest(req *pbs.UpdateTargetRequest) error {
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), "name") && req.GetItem().GetName().GetValue() == "" {
badFields["name"] = "This field cannot be set to empty."
}
if req.GetItem().GetDefaultPort() != nil && req.GetItem().GetDefaultPort().GetValue() == 0 {
badFields["default_port"] = "This optional field cannot be set to 0."
switch target.SubtypeFromType(req.GetItem().GetType()) {
case target.TcpSubType:
tcpAttrs := &pb.TcpTargetAttributes{}
if err := handlers.StructToProto(req.GetItem().GetAttributes(), tcpAttrs); err != nil {
badFields["attributes"] = "Attribute fields do not match the expected format."
}
if tcpAttrs.GetDefaultPort() != nil && tcpAttrs.GetDefaultPort().GetValue() == 0 {
badFields["attributes.default_port"] = "This optional field cannot be set to 0."
}
}
if req.GetItem().GetType() != "" {
badFields["type"] = "This field cannot be updated."
@@ -26,6 +26,7 @@ import (
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
@@ -58,6 +59,7 @@ func TestGet(t *testing.T) {
Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()},
Type: target.TcpTargetType.String(),
HostSetIds: []string{hs[0].GetPublicId(), hs[1].GetPublicId()},
Attributes: new(structpb.Struct),
}
for _, ihs := range hs {
pTar.HostSets = append(pTar.HostSets, &pb.HostSet{Id: ihs.GetPublicId(), HostCatalogId: ihs.GetCatalogId()})
@@ -142,6 +144,7 @@ func TestList(t *testing.T) {
UpdatedTime: tar.GetUpdateTime().GetTimestamp(),
Version: tar.GetVersion(),
Type: target.TcpTargetType.String(),
Attributes: new(structpb.Struct),
})
}
@@ -299,7 +302,9 @@ func TestCreate(t *testing.T) {
Name: wrapperspb.String("name"),
Description: wrapperspb.String("desc"),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(2),
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
}},
res: &pbs.CreateTargetResponse{
Uri: fmt.Sprintf("targets/%s_", target.TcpTargetPrefix),
@@ -309,7 +314,9 @@ func TestCreate(t *testing.T) {
Name: wrapperspb.String("name"),
Description: wrapperspb.String("desc"),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(2),
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
},
},
errCode: codes.OK,
@@ -320,7 +327,9 @@ func TestCreate(t *testing.T) {
Name: wrapperspb.String("name"),
Description: wrapperspb.String("desc"),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(0),
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(0),
}},
}},
errCode: codes.InvalidArgument,
},
@@ -468,7 +477,9 @@ func TestUpdate(t *testing.T) {
Name: wrapperspb.String("name"),
Description: wrapperspb.String("desc"),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(2),
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
CreatedTime: tar.GetCreateTime().GetTimestamp(),
HostSetIds: hsIds,
HostSets: hostSets,
@@ -496,9 +507,11 @@ func TestUpdate(t *testing.T) {
Description: wrapperspb.String("desc"),
CreatedTime: tar.GetCreateTime().GetTimestamp(),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(2),
HostSetIds: hsIds,
HostSets: hostSets,
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
HostSetIds: hsIds,
HostSets: hostSets,
},
},
errCode: codes.OK,
@@ -529,7 +542,9 @@ func TestUpdate(t *testing.T) {
req: &pbs.UpdateTargetRequest{
UpdateMask: &field_mask.FieldMask{Paths: []string{"default_port"}},
Item: &pb.Target{
DefaultPort: wrapperspb.UInt32(0),
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(0),
}},
},
},
errCode: codes.InvalidArgument,
@@ -575,9 +590,11 @@ func TestUpdate(t *testing.T) {
Name: wrapperspb.String("default"),
CreatedTime: tar.GetCreateTime().GetTimestamp(),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(2),
HostSetIds: hsIds,
HostSets: hostSets,
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
HostSetIds: hsIds,
HostSets: hostSets,
},
},
errCode: codes.OK,
@@ -602,9 +619,11 @@ func TestUpdate(t *testing.T) {
Description: wrapperspb.String("default"),
CreatedTime: tar.GetCreateTime().GetTimestamp(),
Type: target.TcpTargetType.String(),
DefaultPort: wrapperspb.UInt32(2),
HostSetIds: hsIds,
HostSets: hostSets,
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
HostSetIds: hsIds,
HostSets: hostSets,
},
},
errCode: codes.OK,
@@ -628,10 +647,12 @@ func TestUpdate(t *testing.T) {
Name: wrapperspb.String("default"),
Description: wrapperspb.String("notignored"),
CreatedTime: tar.GetCreateTime().GetTimestamp(),
DefaultPort: wrapperspb.UInt32(2),
Type: target.TcpTargetType.String(),
HostSetIds: hsIds,
HostSets: hostSets,
Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{
"default_port": structpb.NewNumberValue(2),
}},
Type: target.TcpTargetType.String(),
HostSetIds: hsIds,
HostSets: hostSets,
},
},
errCode: codes.OK,
+11 -11
View File
@@ -395,7 +395,7 @@ var file_controller_storage_target_store_v1_target_proto_rawDesc = []byte{
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72,
0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xa3, 0x03, 0x0a, 0x09, 0x54, 0x63, 0x70, 0x54, 0x61,
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xae, 0x03, 0x0a, 0x09, 0x54, 0x63, 0x70, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69,
0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49,
0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20,
@@ -417,16 +417,16 @@ var file_controller_storage_target_store_v1_target_proto_rawDesc = []byte{
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 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, 0x42, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x1f,
0xc2, 0xdd, 0x29, 0x1b, 0x0a, 0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72,
0x74, 0x12, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x52,
0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x42, 0x3b, 0x5a, 0x39,
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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2f, 0x73, 0x74,
0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x2a,
0xc2, 0xdd, 0x29, 0x26, 0x0a, 0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72,
0x74, 0x12, 0x17, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x64, 0x65,
0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x42, 0x3b, 0x5a, 0x39, 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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
+41
View File
@@ -0,0 +1,41 @@
package target
import (
"strings"
)
type SubType int
const (
UnknownSubtype SubType = iota
TcpSubType
)
func (t SubType) String() string {
switch t {
case TcpSubType:
return "tcp"
}
return "unknown"
}
// SubtypeFromType converts a string to a SubType.
// returns UnknownSubtype if no SubType with that name is found.
func SubtypeFromType(t string) SubType {
switch {
case strings.EqualFold(strings.TrimSpace(t), TcpSubType.String()):
return TcpSubType
}
return UnknownSubtype
}
// SubtypeFromId takes any public id in the target subsystem and uses the prefix to determine
// what subtype the id is for.
// Returns UnknownSubtype if no SubType with this id's prefix is found.
func SubtypeFromId(id string) SubType {
switch {
case strings.HasPrefix(strings.TrimSpace(id), TcpTargetPrefix):
return TcpSubType
}
return UnknownSubtype
}