Skip to content

Commit

Permalink
Add resource-quotas commands for pulsarctl (#90)
Browse files Browse the repository at this point in the history
* Add resource-quotas commands for pulsarctl

Signed-off-by: xiaolong.ran <ranxiaolong716@gmail.com>
  • Loading branch information
wolfstudy committed Oct 24, 2019
1 parent 065b4c1 commit 48e1cac
Show file tree
Hide file tree
Showing 14 changed files with 697 additions and 2 deletions.
113 changes: 113 additions & 0 deletions pkg/ctl/resourcequotas/get.go
@@ -0,0 +1,113 @@
// 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 resourcequotas

import (
"github.com/streamnative/pulsarctl/pkg/cmdutils"
"github.com/streamnative/pulsarctl/pkg/pulsar"

"github.com/pkg/errors"
)

func getResourceQuota(vc *cmdutils.VerbCmd) {
var desc pulsar.LongDescription
desc.CommandUsedFor = "Get the resource quota for a specified namespace bundle, " +
"or default quota if no namespace/bundle is specified."
desc.CommandPermission = "This command requires super-user permissions."

var examples []pulsar.Example
get := pulsar.Example{
Desc: "Get the resource quota use default namespace/bundle",
Command: "pulsarctl resource-quotas get",
}
getWithArgs := pulsar.Example{
Desc: "Get the resource quota for a specified namespace bundle",
Command: "pulsarctl resource-quotas get (namespace name) (bundle range)",
}
examples = append(examples, get, getWithArgs)
desc.CommandExamples = examples

var out []pulsar.Output
successOut := pulsar.Output{
Desc: "normal output",
Out: "{\n" +
" \"msgRateIn\" : 40.0,\n" +
" \"msgRateOut\" : 120.0,\n" +
" \"bandwidthIn\" : 100000.0,\n" +
" \"bandwidthOut\" : 300000.0,\n" +
" \"memory\" : 80.0,\n" +
" \"dynamic\" : true\n" +
"}",
}
out = append(out, successOut)
desc.CommandOutput = out

vc.SetDescription(
"get",
"Get the resource quota for a specified namespace bundle, "+
"or default quota if no namespace/bundle is specified.",
desc.ToString(),
desc.ExampleToString(),
"get")

vc.SetRunFuncWithMultiNameArgs(func() error {
return doGetResourceQuota(vc)
}, func(args []string) error {
if len(args) > 2 && len(args) == 1 {
return errors.New("need two arguments or zero arguments apply to the command")
}
return nil
})
}

func doGetResourceQuota(vc *cmdutils.VerbCmd) error {
var namespace, bundle string
if len(vc.NameArgs) > 0 {
namespace = vc.NameArgs[0]
bundle = vc.NameArgs[1]
}
admin := cmdutils.NewPulsarClient()

var err error

switch {
case bundle == "" && namespace == "":
resourceQuotaData, err := admin.ResourceQuotas().GetDefaultResourceQuota()
if err != nil {
cmdutils.PrintError(vc.Command.OutOrStderr(), err)
} else {
cmdutils.PrintJSON(vc.Command.OutOrStdout(), resourceQuotaData)
}
case bundle != "" && namespace != "":
nsName, err := pulsar.GetNamespaceName(namespace)
if err != nil {
return err
}
resourceQuotaData, err := admin.ResourceQuotas().GetNamespaceBundleResourceQuota(
nsName.String(), bundle)
if err != nil {
cmdutils.PrintError(vc.Command.OutOrStderr(), err)
} else {
cmdutils.PrintJSON(vc.Command.OutOrStdout(), resourceQuotaData)
}
default:
return errors.New("Namespace and bundle must be provided together")
}

return err
}
83 changes: 83 additions & 0 deletions pkg/ctl/resourcequotas/reset.go
@@ -0,0 +1,83 @@
// 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 resourcequotas

import (
"errors"

"github.com/streamnative/pulsarctl/pkg/cmdutils"
"github.com/streamnative/pulsarctl/pkg/pulsar"
)

func resetNamespaceBundleResourceQuota(vc *cmdutils.VerbCmd) {
var desc pulsar.LongDescription
desc.CommandUsedFor = "Reset the specified namespace bundle's resource quota to default value."
desc.CommandPermission = "This command requires super-user permissions."

var examples []pulsar.Example
reset := pulsar.Example{
Desc: "Reset the specified namespace bundle's resource quota to default value",
Command: "pulsarctl resource-quotas reset (namespace name) (bundle range)",
}

examples = append(examples, reset)
desc.CommandExamples = examples

var out []pulsar.Output
successOut := pulsar.Output{
Desc: "normal output",
Out: "Reset resource quota successful",
}
out = append(out, successOut)
desc.CommandOutput = out

vc.SetDescription(
"reset",
"Reset the specified namespace bundle's resource quota to default value.",
desc.ToString(),
desc.ExampleToString(),
"clear")

vc.SetRunFuncWithMultiNameArgs(func() error {
return doResetNamespaceBundleResourceQuota(vc)
}, func(args []string) error {
if len(args) != 2 {
return errors.New("need two arguments apply to the command")
}
return nil
})
}

func doResetNamespaceBundleResourceQuota(vc *cmdutils.VerbCmd) error {
namespace := vc.NameArgs[0]
bundle := vc.NameArgs[1]
admin := cmdutils.NewPulsarClient()

nsName, err := pulsar.GetNamespaceName(namespace)
if err != nil {
return err
}
err = admin.ResourceQuotas().ResetNamespaceBundleResourceQuota(nsName.String(), bundle)
if err != nil {
cmdutils.PrintError(vc.Command.OutOrStderr(), err)
} else {
vc.Command.Println("Reset resource quota successful")
}

return err
}
86 changes: 86 additions & 0 deletions pkg/ctl/resourcequotas/resource_quota_test.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 resourcequotas

import (
"encoding/json"
"testing"

"github.com/streamnative/pulsarctl/pkg/pulsar"
"github.com/stretchr/testify/assert"
)

func TestResourceQuota(t *testing.T) {
getDefaultArgs := []string{"get"}
getDefaultOut, execErr, _, _ := TestResourceQuotaCommands(getResourceQuota, getDefaultArgs)
assert.Nil(t, execErr)
var quota pulsar.ResourceQuota
err := json.Unmarshal(getDefaultOut.Bytes(), &quota)
assert.Nil(t, err)

assert.Equal(t, float64(40), quota.MsgRateIn)
assert.Equal(t, float64(120), quota.MsgRateOut)
assert.Equal(t, float64(100000), quota.BandwidthIn)
assert.Equal(t, float64(300000), quota.BandwidthOut)
assert.Equal(t, float64(80), quota.Memory)
assert.Equal(t, true, quota.Dynamic)

setDefaultArgs := []string{"set", "--bandwidthIn", "10", "--bandwidthOut", "20",
"--memory", "30", "--msgRateIn", "40", "--msgRateOut", "50"}
setDefaultOut, execErr, _, _ := TestResourceQuotaCommands(setResourceQuota, setDefaultArgs)
assert.Nil(t, execErr)
assert.Equal(t, "Set default resource quota successful\n", setDefaultOut.String())

getDefaultAgainArgs := []string{"get"}
getDefaultOut, execErr, _, _ = TestResourceQuotaCommands(getResourceQuota, getDefaultAgainArgs)
assert.Nil(t, execErr)
err = json.Unmarshal(getDefaultOut.Bytes(), &quota)
assert.Nil(t, err)

assert.Equal(t, float64(10), quota.BandwidthIn)
assert.Equal(t, float64(20), quota.BandwidthOut)
assert.Equal(t, float64(30), quota.Memory)
assert.Equal(t, float64(40), quota.MsgRateIn)
assert.Equal(t, float64(50), quota.MsgRateOut)

setArgs := []string{"set", "--bandwidthIn", "100", "--bandwidthOut", "200", "--memory", "300",
"--msgRateIn", "400", "--msgRateOut", "500", "--namespace", "public/default",
"--bundle", "0x80000000_0xc0000000"}
setOut, execErr, _, _ := TestResourceQuotaCommands(setResourceQuota, setArgs)
assert.Nil(t, execErr)
assert.Equal(t, "Set resource quota successful\n", setOut.String())

getArgs := []string{"get", "public/default", "0x80000000_0xc0000000"}
getOut, execErr, _, _ := TestResourceQuotaCommands(getResourceQuota, getArgs)
assert.Nil(t, execErr)
err = json.Unmarshal(getOut.Bytes(), &quota)
assert.Nil(t, err)

assert.Equal(t, float64(100), quota.BandwidthIn)
assert.Equal(t, float64(200), quota.BandwidthOut)
assert.Equal(t, float64(300), quota.Memory)
assert.Equal(t, float64(400), quota.MsgRateIn)
assert.Equal(t, float64(500), quota.MsgRateOut)

resetArgs := []string{"reset",
"public/default",
"0x80000000_0xc0000000"}
resetOut, execErr, _, _ := TestResourceQuotaCommands(resetNamespaceBundleResourceQuota, resetArgs)
assert.Nil(t, execErr)
assert.Equal(t, "Reset resource quota successful\n", resetOut.String())
}
37 changes: 37 additions & 0 deletions pkg/ctl/resourcequotas/resource_quotas.go
@@ -0,0 +1,37 @@
// 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 resourcequotas

import (
"github.com/spf13/cobra"
"github.com/streamnative/pulsarctl/pkg/cmdutils"
)

func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command {
resourceCmd := cmdutils.NewResourceCmd(
"resource-quotas",
"Operations about resource quotas",
"",
"resource-quotas")

cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getResourceQuota)
cmdutils.AddVerbCmd(flagGrouping, resourceCmd, setResourceQuota)
cmdutils.AddVerbCmd(flagGrouping, resourceCmd, resetNamespaceBundleResourceQuota)

return resourceCmd
}

0 comments on commit 48e1cac

Please sign in to comment.