Skip to content

Commit f3a155d

Browse files
jumbogoanekkanti
andauthored
add a flag to specify codec server for tcld create namespace (#261)
* add a flag to specify codec server for tcld create namespace * init change to use separate cmd flags * cleanup * more cleanup * more validation * fix test * address comments * address comments --------- Co-authored-by: Abhinav Nekkanti <10552725+anekkanti@users.noreply.github.com>
1 parent fd62d89 commit f3a155d

2 files changed

Lines changed: 115 additions & 23 deletions

File tree

app/namespace.go

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const (
2929
caCertificateFingerprintFlagName = "ca-certificate-fingerprint"
3030
searchAttributeFlagName = "search-attribute"
3131
userNamespacePermissionFlagName = "user-namespace-permission"
32+
codecEndpointFlagName = "endpoint"
33+
codecPassAccessTokenFlagName = "pass-access-token"
34+
codecIncludeCredentialsFlagName = "include-credentials"
3235
)
3336

3437
var (
@@ -79,7 +82,6 @@ var (
7982
Name: "kms-arn",
8083
Usage: "Provide the ARN of the KMS key to use for encryption. Note: If the KMS ARN needs to be added or updated, user should create the IAM Role with KMS or modify the created IAM Role accordingly. Provided it as part of the input won't help",
8184
}
82-
8385
pageSizeFlag = &cli.IntFlag{
8486
Name: "page-size",
8587
Usage: "The page size for list operations",
@@ -89,6 +91,21 @@ var (
8991
Name: "page-token",
9092
Usage: "The page token for list operations",
9193
}
94+
codecIncludeCredentialsFlag = &cli.BoolFlag{
95+
Name: codecIncludeCredentialsFlagName,
96+
Usage: "Include cross-origin credentials",
97+
Aliases: []string{"ic"},
98+
}
99+
codecPassAccessTokenFlag = &cli.BoolFlag{
100+
Name: codecPassAccessTokenFlagName,
101+
Usage: "Pass the user access token to the remote endpoint",
102+
Aliases: []string{"pat"},
103+
}
104+
codecEndpointFlag = &cli.StringFlag{
105+
Name: codecEndpointFlagName,
106+
Usage: "The codec server endpoint to decode payloads for all users interacting with this Namespace, must be https",
107+
Aliases: []string{"e"},
108+
}
92109
)
93110

94111
type NamespaceClient struct {
@@ -429,6 +446,9 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
429446
Usage: fmt.Sprintf("Flag can be used multiple times; value must be \"email=permission\"; valid permissions are: %v", getNamespacePermissionTypes()),
430447
Aliases: []string{"p"},
431448
},
449+
codecEndpointFlag,
450+
codecPassAccessTokenFlag,
451+
codecIncludeCredentialsFlag,
432452
},
433453
Action: func(ctx *cli.Context) error {
434454
n := &namespace.Namespace{
@@ -500,6 +520,24 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
500520
}
501521
}
502522

523+
codecEndpoint := ctx.String(codecEndpointFlagName)
524+
// codec server spec is optional, if specified, we need to create the spec and pass along to the API
525+
if codecEndpoint != "" {
526+
err = validateCodecEndpoint(codecEndpoint)
527+
if err != nil {
528+
return err
529+
}
530+
n.Spec.CodecSpec = &namespace.CodecServerPropertySpec{
531+
Endpoint: codecEndpoint,
532+
PassAccessToken: ctx.Bool(codecPassAccessTokenFlagName),
533+
IncludeCredentials: ctx.Bool(codecIncludeCredentialsFlagName),
534+
}
535+
} else {
536+
if ctx.Bool(codecPassAccessTokenFlagName) || ctx.Bool(codecIncludeCredentialsFlagName) {
537+
return errors.New("pass-access-token or include-credentials cannot be specified when codec endpoint is not specified")
538+
}
539+
}
540+
503541
return c.createNamespace(n, unp)
504542
},
505543
},
@@ -936,32 +974,29 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
936974
Flags: []cli.Flag{
937975
NamespaceFlag,
938976
&cli.StringFlag{
939-
Name: "endpoint",
940-
Usage: "The codec server endpoint to decode payloads for all users interacting with this Namespace, must be https",
941-
Aliases: []string{"e"},
977+
Name: codecEndpointFlag.Name,
978+
Usage: codecEndpointFlag.Usage,
979+
Aliases: codecEndpointFlag.Aliases,
942980
Required: true,
943981
},
944-
&cli.BoolFlag{
945-
Name: "pass-access-token",
946-
Usage: "Pass the user access token with the remote endpoint",
947-
Aliases: []string{"pat"},
948-
},
949-
&cli.BoolFlag{
950-
Name: "include-credentials",
951-
Usage: "Include cross-origin credentials",
952-
Aliases: []string{"ic"},
953-
},
982+
codecPassAccessTokenFlag,
983+
codecIncludeCredentialsFlag,
954984
},
955985
Action: func(ctx *cli.Context) error {
956986
n, err := c.getNamespace(ctx.String(NamespaceFlagName))
957987
if err != nil {
958988
return err
959989
}
960990

991+
codecEndpoint := ctx.String(codecEndpointFlagName)
992+
err = validateCodecEndpoint(codecEndpoint)
993+
if err != nil {
994+
return err
995+
}
961996
replacement := &namespace.CodecServerPropertySpec{
962-
Endpoint: ctx.String("endpoint"),
963-
PassAccessToken: ctx.Bool("pass-access-token"),
964-
IncludeCredentials: ctx.Bool("include-credentials"),
997+
Endpoint: codecEndpoint,
998+
PassAccessToken: ctx.Bool(codecPassAccessTokenFlagName),
999+
IncludeCredentials: ctx.Bool(codecIncludeCredentialsFlagName),
9651000
}
9661001

9671002
difference, err := compareCodecSpec(n.Spec.CodecSpec, replacement)
@@ -1395,6 +1430,13 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
13951430
return CommandOut{Command: command}, nil
13961431
}
13971432

1433+
func validateCodecEndpoint(codecEndpoint string) error {
1434+
if !strings.HasPrefix(codecEndpoint, "https://") {
1435+
return errors.New("field Endpoint has to use https")
1436+
}
1437+
return nil
1438+
}
1439+
13981440
func getSearchAttributeTypes() []string {
13991441
validTypes := []string{}
14001442
for i := 1; i < len(namespace.SearchAttributeType_name); i++ {

app/namespace_test.go

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,28 +1095,28 @@ func (s *NamespaceTestSuite) TestUpdateCodecServer() {
10951095
expectErr: true,
10961096
},
10971097
{
1098-
args: []string{"n", "ucs", "-n", ns, "-endpoint", "fakehost:9999"},
1098+
args: []string{"n", "ucs", "-n", ns, "-endpoint", "https://fakehost:9999"},
10991099
expectGet: func(g *namespaceservice.GetNamespaceResponse) {},
11001100
expectUpdate: func(r *namespaceservice.UpdateNamespaceRequest) {
1101-
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{Endpoint: "fakehost:9999"}
1101+
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{Endpoint: "https://fakehost:9999"}
11021102
},
11031103
},
11041104
{
1105-
args: []string{"n", "ucs", "-n", ns, "-e", "fakehost:9999", "--pass-access-token"},
1105+
args: []string{"n", "ucs", "-n", ns, "-e", "https://fakehost:9999", "--pass-access-token"},
11061106
expectGet: func(g *namespaceservice.GetNamespaceResponse) {},
11071107
expectUpdate: func(r *namespaceservice.UpdateNamespaceRequest) {
11081108
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{
1109-
Endpoint: "fakehost:9999",
1109+
Endpoint: "https://fakehost:9999",
11101110
PassAccessToken: true,
11111111
}
11121112
},
11131113
},
11141114
{
1115-
args: []string{"n", "ucs", "-n", ns, "-e", "fakehost:9999", "--pat", "--include-credentials"},
1115+
args: []string{"n", "ucs", "-n", ns, "-e", "https://fakehost:9999", "--pat", "--include-credentials"},
11161116
expectGet: func(g *namespaceservice.GetNamespaceResponse) {},
11171117
expectUpdate: func(r *namespaceservice.UpdateNamespaceRequest) {
11181118
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{
1119-
Endpoint: "fakehost:9999",
1119+
Endpoint: "https://fakehost:9999",
11201120
PassAccessToken: true,
11211121
IncludeCredentials: true,
11221122
}
@@ -1397,6 +1397,56 @@ func (s *NamespaceTestSuite) TestCreate() {
13971397
))
13981398
}
13991399

1400+
func (s *NamespaceTestSuite) TestCreateWithCodec() {
1401+
s.mockService.EXPECT().CreateNamespace(gomock.Any(), gomock.Any()).Return(&namespaceservice.CreateNamespaceResponse{
1402+
RequestStatus: &request.RequestStatus{},
1403+
}, nil).AnyTimes()
1404+
s.mockAuthService.EXPECT().GetUser(gomock.Any(), gomock.Any()).Return(&authservice.GetUserResponse{
1405+
User: &auth.User{
1406+
Id: "test-user-id",
1407+
Spec: &auth.UserSpec{
1408+
Email: "testuser@testcompany.com",
1409+
},
1410+
},
1411+
}, nil).AnyTimes()
1412+
s.NoError(s.RunCmd(
1413+
"namespace", "create",
1414+
"--namespace", "ns1",
1415+
"--region", "us-west-2",
1416+
"--ca-certificate", "cert1",
1417+
"--certificate-filter-input", "{ \"filters\": [ { \"commonName\": \"test1\" } ] }",
1418+
"--search-attribute", "testsearchattribute=Keyword",
1419+
"--user-namespace-permission", "testuser@testcompany.com=Read",
1420+
"--endpoint", "https://test-endpoint.com", "--pass-access-token", "--include-credentials", "false",
1421+
))
1422+
1423+
err := s.RunCmd(
1424+
"namespace", "create",
1425+
"--namespace", "ns1",
1426+
"--region", "us-west-2",
1427+
"--ca-certificate", "cert1",
1428+
"--certificate-filter-input", "{ \"filters\": [ { \"commonName\": \"test1\" } ] }",
1429+
"--search-attribute", "testsearchattribute=Keyword",
1430+
"--user-namespace-permission", "testuser@testcompany.com=Read",
1431+
"--endpoint", "http://test-endpoint.com", "--pass-access-token",
1432+
)
1433+
s.Error(err)
1434+
s.ErrorContains(err, "field Endpoint has to use https")
1435+
1436+
err = s.RunCmd(
1437+
"namespace", "create",
1438+
"--namespace", "ns1",
1439+
"--region", "us-west-2",
1440+
"--ca-certificate", "cert1",
1441+
"--certificate-filter-input", "{ \"filters\": [ { \"commonName\": \"test1\" } ] }",
1442+
"--search-attribute", "testsearchattribute=Keyword",
1443+
"--user-namespace-permission", "testuser@testcompany.com=Read",
1444+
"--pass-access-token",
1445+
)
1446+
s.Error(err)
1447+
s.ErrorContains(err, "pass-access-token or include-credentials cannot be specified when codec endpoint is not specified")
1448+
}
1449+
14001450
func (s *NamespaceTestSuite) TestDelete() {
14011451
s.Error(s.RunCmd("namespace", "delete"))
14021452
s.mockService.EXPECT().GetNamespace(gomock.Any(), gomock.Any()).Return(&namespaceservice.GetNamespaceResponse{

0 commit comments

Comments
 (0)