diff --git a/pkg/ctl/namespace/bundles.go b/pkg/ctl/namespace/bundles.go new file mode 100644 index 00000000..b4aa5b8e --- /dev/null +++ b/pkg/ctl/namespace/bundles.go @@ -0,0 +1,88 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "github.com/streamnative/pulsarctl/pkg/cmdutils" +) + +func getBundles(vc *cmdutils.VerbCmd) { + desc := cmdutils.LongDescription{} + desc.CommandUsedFor = "Get the list of bundles for a namespace" + desc.CommandPermission = "This command requires tenant admin permissions." + + var examples []cmdutils.Example + example := cmdutils.Example{ + Desc: "Get the list of bundles for a namespace", + Command: "pulsarctl namespaces bundles (tenant/namespace)", + } + examples = append(examples, example) + desc.CommandExamples = examples + + var out []cmdutils.Output + successOut := cmdutils.Output{ + Desc: "normal output", + Out: "{\n" + + " \"boundaries\": [\n" + + " \"0x00000000\",\n" + + " \"0xffffffff\"\n" + + " ],\n" + + " \"numBundles\": 1\n" + + "}", + } + + noNamespaceName := cmdutils.Output{ + Desc: "you must specify a tenant/namespace name, please check if the tenant/namespace name is provided", + Out: "[✖] the namespace name is not specified or the namespace name is specified more than one", + } + + tenantNotExistError := cmdutils.Output{ + Desc: "the tenant does not exist", + Out: "[✖] code: 404 reason: Tenant does not exist", + } + + nsNotExistError := cmdutils.Output{ + Desc: "the namespace does not exist", + Out: "[✖] code: 404 reason: Namespace (tenant/namespace) does not exist", + } + + out = append(out, successOut, noNamespaceName, tenantNotExistError, nsNotExistError) + desc.CommandOutput = out + + vc.SetDescription( + "bundles", + "Get the list of bundles for a namespace", + desc.ToString(), + desc.ExampleToString()) + + vc.SetRunFuncWithNameArg(func() error { + return doGetBundles(vc) + }, "the namespace name is not specified or the namespace name is specified more than one") + + vc.EnableOutputFlagSet() +} + +func doGetBundles(vc *cmdutils.VerbCmd) error { + admin := cmdutils.NewPulsarClient() + policies, err := admin.Namespaces().GetPolicies(vc.NameArg) + if err == nil { + oc := cmdutils.NewOutputContent().WithObject(policies.Bundles) + err = vc.OutputConfig.WriteOutput(vc.Command.OutOrStdout(), oc) + } + return err +} diff --git a/pkg/ctl/namespace/bundles_test.go b/pkg/ctl/namespace/bundles_test.go new file mode 100644 index 00000000..27320c62 --- /dev/null +++ b/pkg/ctl/namespace/bundles_test.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "encoding/json" + "testing" + + "github.com/apache/pulsar-client-go/pulsaradmin/pkg/utils" + "github.com/stretchr/testify/assert" +) + +func TestBundlesCommandArgsError(t *testing.T) { + args := []string{"bundles"} + _, _, nameErr, _ := TestNamespaceCommands(getBundles, args) + assert.Equal(t, "the namespace name is not specified or the namespace name is specified more than one", + nameErr.Error()) +} + +func TestBundlesCommand(t *testing.T) { + ns := "public/test-bundles-namespace" + + args := []string{"create", ns} + _, execErr, _, _ := TestNamespaceCommands(createNs, args) + assert.Nil(t, execErr) + + args = []string{"bundles", ns} + out, execErr, _, _ := TestNamespaceCommands(getBundles, args) + assert.Nil(t, execErr) + + var bundles utils.BundlesData + err := json.Unmarshal(out.Bytes(), &bundles) + assert.Nil(t, err) + assert.True(t, bundles.NumBundles > 0) + assert.True(t, len(bundles.Boundaries) >= 2) +} diff --git a/pkg/ctl/namespace/get_deduplication.go b/pkg/ctl/namespace/get_deduplication.go new file mode 100644 index 00000000..21ea87b4 --- /dev/null +++ b/pkg/ctl/namespace/get_deduplication.go @@ -0,0 +1,86 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "github.com/streamnative/pulsarctl/pkg/cmdutils" +) + +func getDeduplication(vc *cmdutils.VerbCmd) { + desc := cmdutils.LongDescription{} + desc.CommandUsedFor = "Get deduplication for a namespace" + desc.CommandPermission = "This command requires tenant admin permissions." + + var examples []cmdutils.Example + example := cmdutils.Example{ + Desc: "Get deduplication for a namespace", + Command: "pulsarctl namespaces get-deduplication tenant/namespace", + } + examples = append(examples, example) + desc.CommandExamples = examples + + var out []cmdutils.Output + successOut := cmdutils.Output{ + Desc: "normal output", + Out: "true", + } + + noNamespaceName := cmdutils.Output{ + Desc: "you must specify a tenant/namespace name, please check if the tenant/namespace name is provided", + Out: "[✖] the namespace name is not specified or the namespace name is specified more than one", + } + + tenantNotExistError := cmdutils.Output{ + Desc: "the tenant does not exist", + Out: "[✖] code: 404 reason: Tenant does not exist", + } + + nsNotExistError := cmdutils.Output{ + Desc: "the namespace does not exist", + Out: "[✖] code: 404 reason: Namespace (tenant/namespace) does not exist", + } + + out = append(out, successOut, noNamespaceName, tenantNotExistError, nsNotExistError) + desc.CommandOutput = out + + vc.SetDescription( + "get-deduplication", + "Get deduplication for a namespace", + desc.ToString(), + desc.ExampleToString()) + + vc.SetRunFuncWithNameArg(func() error { + return doGetDeduplication(vc) + }, "the namespace name is not specified or the namespace name is specified more than one") + + vc.EnableOutputFlagSet() +} + +func doGetDeduplication(vc *cmdutils.VerbCmd) error { + admin := cmdutils.NewPulsarClient() + policies, err := admin.Namespaces().GetPolicies(vc.NameArg) + if err == nil { + enabled := false + if policies.DeduplicationEnabled != nil { + enabled = *policies.DeduplicationEnabled + } + oc := cmdutils.NewOutputContent().WithObject(enabled) + err = vc.OutputConfig.WriteOutput(vc.Command.OutOrStdout(), oc) + } + return err +} diff --git a/pkg/ctl/namespace/get_deduplication_test.go b/pkg/ctl/namespace/get_deduplication_test.go new file mode 100644 index 00000000..21ccf8a0 --- /dev/null +++ b/pkg/ctl/namespace/get_deduplication_test.go @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetDeduplicationArgsError(t *testing.T) { + args := []string{"get-deduplication"} + _, _, nameErr, _ := TestNamespaceCommands(getDeduplication, args) + assert.Equal(t, "the namespace name is not specified or the namespace name is specified more than one", + nameErr.Error()) +} + +func TestGetDeduplication(t *testing.T) { + ns := "public/test-get-deduplication-ns" + + args := []string{"create", ns} + _, execErr, _, _ := TestNamespaceCommands(createNs, args) + assert.Nil(t, execErr) + + args = []string{"get-deduplication", ns} + out, execErr, _, _ := TestNamespaceCommands(getDeduplication, args) + assert.Nil(t, execErr) + + var enabled bool + err := json.Unmarshal(out.Bytes(), &enabled) + assert.Nil(t, err) + assert.False(t, enabled) +} diff --git a/pkg/ctl/namespace/get_encryption_required.go b/pkg/ctl/namespace/get_encryption_required.go new file mode 100644 index 00000000..003a1502 --- /dev/null +++ b/pkg/ctl/namespace/get_encryption_required.go @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "github.com/streamnative/pulsarctl/pkg/cmdutils" +) + +func GetEncryptionRequiredCmd(vc *cmdutils.VerbCmd) { + var desc cmdutils.LongDescription + desc.CommandUsedFor = "This command is used for getting whether encryption is required for a namespace." + desc.CommandPermission = "This command requires tenant admin permissions." + + var examples []cmdutils.Example + example := cmdutils.Example{ + Desc: "Get whether encryption is required for the namespace (namespace-name)", + Command: "pulsarctl namespaces get-encryption-required (namespace-name)", + } + examples = append(examples, example) + desc.CommandExamples = examples + + var out []cmdutils.Output + successOut := cmdutils.Output{ + Desc: "normal output", + Out: "true", + } + out = append(out, successOut, ArgError, NsNotExistError) + out = append(out, NsErrors...) + desc.CommandOutput = out + + vc.SetDescription( + "get-encryption-required", + "Get whether encryption is required for a namespace", + desc.ToString(), + desc.ExampleToString()) + + vc.SetRunFuncWithNameArg(func() error { + return doGetEncryptionRequired(vc) + }, "the namespace name is not specified or the namespace name is specified more than one") + + vc.EnableOutputFlagSet() +} + +func doGetEncryptionRequired(vc *cmdutils.VerbCmd) error { + admin := cmdutils.NewPulsarClient() + policies, err := admin.Namespaces().GetPolicies(vc.NameArg) + if err == nil { + oc := cmdutils.NewOutputContent().WithObject(policies.EncryptionRequired) + err = vc.OutputConfig.WriteOutput(vc.Command.OutOrStdout(), oc) + } + return err +} diff --git a/pkg/ctl/namespace/get_encryption_required_test.go b/pkg/ctl/namespace/get_encryption_required_test.go new file mode 100644 index 00000000..8e278d62 --- /dev/null +++ b/pkg/ctl/namespace/get_encryption_required_test.go @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetEncryptionRequiredArgsError(t *testing.T) { + args := []string{"get-encryption-required"} + _, _, nameErr, _ := TestNamespaceCommands(GetEncryptionRequiredCmd, args) + assert.Equal(t, "the namespace name is not specified or the namespace name is specified more than one", + nameErr.Error()) +} + +func TestGetEncryptionRequiredCmd(t *testing.T) { + ns := "public/test-get-encryption-required-ns" + + args := []string{"create", ns} + _, execErr, _, _ := TestNamespaceCommands(createNs, args) + assert.Nil(t, execErr) + + args = []string{"get-encryption-required", ns} + out, execErr, _, _ := TestNamespaceCommands(GetEncryptionRequiredCmd, args) + assert.Nil(t, execErr) + + var enabled bool + err := json.Unmarshal(out.Bytes(), &enabled) + assert.Nil(t, err) + assert.False(t, enabled) +} diff --git a/pkg/ctl/namespace/get_subscription_auth_mode.go b/pkg/ctl/namespace/get_subscription_auth_mode.go new file mode 100644 index 00000000..d0ebd293 --- /dev/null +++ b/pkg/ctl/namespace/get_subscription_auth_mode.go @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "github.com/streamnative/pulsarctl/pkg/cmdutils" +) + +func GetSubscriptionAuthModeCmd(vc *cmdutils.VerbCmd) { + var desc cmdutils.LongDescription + desc.CommandUsedFor = "This command is used for getting the default subscription auth mode of a namespace." + desc.CommandPermission = "This command requires tenant admin permissions." + + var examples []cmdutils.Example + example := cmdutils.Example{ + Desc: "Get the default subscription auth mode of the namespace (namespace-name)", + Command: "pulsarctl namespaces get-subscription-auth-mode (namespace-name)", + } + examples = append(examples, example) + desc.CommandExamples = examples + + var out []cmdutils.Output + successOut := cmdutils.Output{ + Desc: "normal output", + Out: "\"None\"", + } + out = append(out, successOut, ArgError, NsNotExistError) + out = append(out, NsErrors...) + desc.CommandOutput = out + + vc.SetDescription( + "get-subscription-auth-mode", + "Get the default subscription auth mode of a namespace", + desc.ToString(), + desc.ExampleToString()) + + vc.SetRunFuncWithNameArg(func() error { + return doGetSubscriptionAuthMode(vc) + }, "the namespace name is not specified or the namespace name is specified more than one") + + vc.EnableOutputFlagSet() +} + +func doGetSubscriptionAuthMode(vc *cmdutils.VerbCmd) error { + admin := cmdutils.NewPulsarClient() + policies, err := admin.Namespaces().GetPolicies(vc.NameArg) + if err == nil { + oc := cmdutils.NewOutputContent().WithObject(policies.SubscriptionAuthMode.String()) + err = vc.OutputConfig.WriteOutput(vc.Command.OutOrStdout(), oc) + } + return err +} diff --git a/pkg/ctl/namespace/get_subscription_auth_mode_test.go b/pkg/ctl/namespace/get_subscription_auth_mode_test.go new file mode 100644 index 00000000..7f5a77bd --- /dev/null +++ b/pkg/ctl/namespace/get_subscription_auth_mode_test.go @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package namespace + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetSubscriptionAuthModeArgsError(t *testing.T) { + args := []string{"get-subscription-auth-mode"} + _, _, nameErr, _ := TestNamespaceCommands(GetSubscriptionAuthModeCmd, args) + assert.Equal(t, "the namespace name is not specified or the namespace name is specified more than one", + nameErr.Error()) +} + +func TestGetSubscriptionAuthModeCmd(t *testing.T) { + ns := "public/test-get-subscription-auth-mode-ns" + + args := []string{"create", ns} + _, execErr, _, _ := TestNamespaceCommands(createNs, args) + assert.Nil(t, execErr) + + args = []string{"get-subscription-auth-mode", ns} + out, execErr, _, _ := TestNamespaceCommands(GetSubscriptionAuthModeCmd, args) + assert.Nil(t, execErr) + + var mode string + err := json.Unmarshal(out.Bytes(), &mode) + assert.Nil(t, err) + assert.Equal(t, "None", mode) +} diff --git a/pkg/ctl/namespace/namespace.go b/pkg/ctl/namespace/namespace.go index 116f260f..180f4d45 100644 --- a/pkg/ctl/namespace/namespace.go +++ b/pkg/ctl/namespace/namespace.go @@ -33,6 +33,7 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getNamespacesFromTenant) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getTopics) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getBundles) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getPolicies) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, createNs) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, deleteNs) @@ -69,11 +70,13 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getPersistence) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, setPersistence) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, setDeduplication) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getDeduplication) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, setReplicationClusters) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getReplicationClusters) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, unload) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, splitBundle) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetPermissionsCmd) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetSubPermissionsCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GrantPermissionsCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, RevokePermissionsCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GrantSubPermissionsCmd) @@ -82,6 +85,7 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetDispatchRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetDispatchRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetEncryptionRequiredCmd) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetEncryptionRequiredCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetReplicatorDispatchRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetReplicatorDispatchRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetSubscribeRateCmd) @@ -90,6 +94,7 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetSubscriptionDispatchRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, UnsubscribeCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetSubscriptionAuthModeCmd) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetSubscriptionAuthModeCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, GetPublishRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetPublishRateCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, SetIsAllowAutoUpdateSchemaCmd) diff --git a/pkg/ctl/namespace/permissions.go b/pkg/ctl/namespace/permissions.go index b2b74acc..7b1dda0e 100644 --- a/pkg/ctl/namespace/permissions.go +++ b/pkg/ctl/namespace/permissions.go @@ -62,6 +62,45 @@ func GetPermissionsCmd(vc *cmdutils.VerbCmd) { vc.EnableOutputFlagSet() } +func GetSubPermissionsCmd(vc *cmdutils.VerbCmd) { + var desc cmdutils.LongDescription + desc.CommandUsedFor = "This command is used for getting subscription permissions of a namespace." + desc.CommandPermission = "This command requires tenant admin permissions." + + var examples []cmdutils.Example + getNs := cmdutils.Example{ + Desc: "Get subscription permissions of a namespace (tenant)/(namespace)", + Command: "pulsarctl namespaces subscription-permission (tenant)/(namespace)", + } + examples = append(examples, getNs) + desc.CommandExamples = examples + + var out []cmdutils.Output + successOut := cmdutils.Output{ + Desc: "normal output", + Out: "{\n" + + " \"\": [\n" + + " \"\"\n" + + " ]" + + "\n}", + } + out = append(out, successOut, ArgError) + out = append(out, NsErrors...) + desc.CommandOutput = out + + vc.SetDescription( + "subscription-permission", + "Get subscription permissions of a namespace", + desc.ToString(), + desc.ExampleToString()) + + vc.SetRunFuncWithNameArg(func() error { + return doGetSubPermissions(vc) + }, "the namespace name is not specified or the namespace name is specified more than one") + + vc.EnableOutputFlagSet() +} + func doGetPermissions(vc *cmdutils.VerbCmd) error { // for testing if vc.NameError != nil { @@ -82,3 +121,24 @@ func doGetPermissions(vc *cmdutils.VerbCmd) error { return err } + +func doGetSubPermissions(vc *cmdutils.VerbCmd) error { + // for testing + if vc.NameError != nil { + return vc.NameError + } + + ns, err := utils.GetNamespaceName(vc.NameArg) + if err != nil { + return err + } + + admin := cmdutils.NewPulsarClient() + data, err := admin.Namespaces().GetSubPermissions(*ns) + if err == nil { + oc := cmdutils.NewOutputContent().WithObject(data) + err = vc.OutputConfig.WriteOutput(vc.Command.OutOrStdout(), oc) + } + + return err +} diff --git a/pkg/ctl/namespace/permissions_test.go b/pkg/ctl/namespace/permissions_test.go index 239b07c7..3db8c159 100644 --- a/pkg/ctl/namespace/permissions_test.go +++ b/pkg/ctl/namespace/permissions_test.go @@ -54,3 +54,32 @@ func TestGetPermissionsArgsError(t *testing.T) { assert.Equal(t, "the namespace name is not specified or the namespace name is specified more than one", nameErr.Error()) } + +func TestSubPermissionsCmd(t *testing.T) { + ns := "public/test-sub-permissions-ns" + + args := []string{"create", ns} + _, execErr, _, _ := TestNamespaceCommands(createNs, args) + assert.Nil(t, execErr) + + args = []string{"subscription-permission", ns} + out, execErr, _, _ := TestNamespaceCommands(GetSubPermissionsCmd, args) + assert.Nil(t, execErr) + + var permissions map[string][]string + err := json.Unmarshal(out.Bytes(), &permissions) + if err != nil { + t.Fatal(err) + } + + empty := make(map[string][]string) + assert.Equal(t, empty, permissions) +} + +func TestGetSubPermissionsArgsError(t *testing.T) { + args := []string{"subscription-permission"} + _, _, nameErr, _ := TestNamespaceCommands(GetSubPermissionsCmd, args) + assert.NotNil(t, nameErr.Error()) + assert.Equal(t, "the namespace name is not specified or the namespace name is specified more than one", + nameErr.Error()) +} diff --git a/pkg/ctl/namespace/revoke_subscription_permission.go b/pkg/ctl/namespace/revoke_subscription_permission.go index 09dc71e7..c567799c 100644 --- a/pkg/ctl/namespace/revoke_subscription_permission.go +++ b/pkg/ctl/namespace/revoke_subscription_permission.go @@ -62,7 +62,7 @@ func RevokeSubPermissionsCmd(vc *cmdutils.VerbCmd) { "revoke-subscription-permission", "Revoke a client role permissions of accessing a subscription of a namespace", desc.ToString(), - desc.ToString()) + desc.ExampleToString()) var role string diff --git a/pkg/ctl/namespace/revoke_subscription_permission_test.go b/pkg/ctl/namespace/revoke_subscription_permission_test.go index 69583754..81b8e59e 100644 --- a/pkg/ctl/namespace/revoke_subscription_permission_test.go +++ b/pkg/ctl/namespace/revoke_subscription_permission_test.go @@ -23,6 +23,18 @@ import ( "github.com/stretchr/testify/assert" ) +func TestRevokeSubPermissionsCmd(t *testing.T) { + ns := "public/test-revoke-sub-permissions-ns" + + args := []string{"create", ns} + _, execErr, _, _ := TestNamespaceCommands(createNs, args) + assert.Nil(t, execErr) + + args = []string{"revoke-subscription-permission", "--role", "test-role", ns, "test-revoke-sub"} + _, execErr, _, _ = TestNamespaceCommands(RevokeSubPermissionsCmd, args) + assert.Nil(t, execErr) +} + func TestRevokeSubPermissionsArgsError(t *testing.T) { ns := "public/revoke-sub-permissions-args-tests" diff --git a/pkg/ctl/namespace/set_encryption_require.go b/pkg/ctl/namespace/set_encryption_require.go index 223150ed..03491b55 100644 --- a/pkg/ctl/namespace/set_encryption_require.go +++ b/pkg/ctl/namespace/set_encryption_require.go @@ -38,7 +38,7 @@ func SetEncryptionRequiredCmd(vc *cmdutils.VerbCmd) { disable := cmdutils.Example{ Desc: "Disable messages encryption for the namespace (namespace-name)", - Command: "pulsarct. namespaces messages-encryption --disable (namespace-name)", + Command: "pulsarctl namespaces messages-encryption --disable (namespace-name)", } examples = append(examples, enable, disable) desc.CommandExamples = examples @@ -85,8 +85,8 @@ func doSetEncryptionRequired(vc *cmdutils.VerbCmd, disable bool) error { } else { out = "Disable" } - vc.Command.Printf("%s messages encryption of the namespace %s", out, ns.String()) + vc.Command.Printf("%s messages encryption of the namespace %s\n", out, ns.String()) } - return nil + return err } diff --git a/pkg/ctl/namespace/set_subscription_auth_mode.go b/pkg/ctl/namespace/set_subscription_auth_mode.go index 9e5a7ff3..f71f2723 100644 --- a/pkg/ctl/namespace/set_subscription_auth_mode.go +++ b/pkg/ctl/namespace/set_subscription_auth_mode.go @@ -82,7 +82,7 @@ func doSetSubscriptionAuthMode(vc *cmdutils.VerbCmd, mode string) error { admin := cmdutils.NewPulsarClient() err = admin.Namespaces().SetSubscriptionAuthMode(*ns, m) if err == nil { - vc.Command.Printf("Successfully set the default subscription auth mode of namespace %s to %s", + vc.Command.Printf("Successfully set the default subscription auth mode of namespace %s to %s\n", ns.String(), m.String()) }