Skip to content

Commit

Permalink
Merge pull request #33 from kubecost/mmd/more-ergonomic-namespace
Browse files Browse the repository at this point in the history
--namespace behaves as expected, applying to Kubecost request instead of Kubernetes request
  • Loading branch information
michaelmdresser authored Mar 10, 2021
2 parents c35841c + 17bfab3 commit ed2f29b
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 41 deletions.
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ kubectl cost deployment --window month -A

Show the projected monthly rate for each deployment in the `kubecost` namespace based on the last 3 days of activity with CPU cost breakdown.
``` sh
kubectl cost deployment --window 3d --show-cpu -N kubecost
kubectl cost deployment --window 3d --show-cpu -n kubecost
```

The same, but with a non-standard Kubecost deployment in the namespace `kubecost-staging` with the cost analyzer service called `kubecost-staging-cost-analyzer`.
``` sh
kubectl cost deployment --window 3d --show-cpu -N kubecost -n kubecost-staging --service-name kubecost-staging-cost-analyzer
kubectl cost deployment --window 3d --show-cpu -n kubecost -N kubecost-staging --service-name kubecost-staging-cost-analyzer
```


Expand All @@ -85,19 +85,20 @@ See `kubectl cost [subcommand] --help` for the full set of flags.

The following flags modify the behavior of the subcommands:
```
--historical show the total cost during the window instead of the projected monthly rate based on the data in the window"
--show-cpu show data for CPU cost
--show-efficiency show efficiency of cost alongside CPU and memory cost (default true)
--show-gpu show data for GPU cost
--show-memory show data for memory cost
--show-network show data for network cost
--show-pv show data for PV (physical volume) cost
--show-shared show shared cost data
-A, --show-all-resources Equivalent to --show-cpu --show-memory --show-gpu --show-pv --show-network.
--window string the window of data to query (default "yesterday")
-N, --namespace-filter string Limit results to only one namespace. Defaults to all namespaces.
--service-name string The name of the kubecost cost analyzer service. Change if you're running a non-standard deployment, like the staging helm chart. (default "kubecost-cost-analyzer")
-n, --namespace string If present, the namespace scope for this CLI request (i.e. the namespace that Kubecost is running in). (default "kubecost")
--historical show the total cost during the window instead of the projected monthly rate based on the data in the window"
--show-cpu show data for CPU cost
--show-efficiency show efficiency of cost alongside CPU and memory cost (default true)
--show-gpu show data for GPU cost
--show-memory show data for memory cost
--show-network show data for network cost
--show-pv show data for PV (physical volume) cost
--show-shared show shared cost data
-A, --show-all-resources Equivalent to --show-cpu --show-memory --show-gpu --show-pv --show-network.
--window string the window of data to query (default "yesterday")
-N, --namespace-filter string Limit results to only one namespace. Defaults to all namespaces.
--service-name string The name of the kubecost cost analyzer service. Change if you're running a non-standard deployment, like the staging helm chart. (default "kubecost-cost-analyzer")
-n, --namespace string Limit results to only one namespace. Defaults to all namespaces.
-N, --kubecost-namespace string The namespace that kubecost is deployed in. Requests to the API will be directed to this namespace. (default "kubecost")
```


Expand All @@ -114,7 +115,6 @@ The following flags modify the behavior of the subcommands:
-h, --help help for cost
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
-n, --namespace string If present, the namespace scope for this CLI request (i.e. the namespace that Kubecost is running in). (default "kubecost")
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
Expand Down
22 changes: 22 additions & 0 deletions pkg/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ func addCostOptionsFlags(cmd *cobra.Command, options *CostOptions) {
cmd.Flags().StringVar(&options.serviceName, "service-name", "kubecost-cost-analyzer", "The name of the kubecost cost analyzer service. Change if you're running a non-standard deployment, like the staging helm chart.")
}

// addKubeOptionsFlags sets up the cobra command with the flags from
// KubeOptions' configFlags so that a kube client can be built to a
// user's specification. Its one modification is to change the name
// of the namespace flag to kubecost-namespace because we want to
// "behave as expected", i.e. --namespace affects the request to the
// kubecost API, not the request to the k8s API.
func addKubeOptionsFlags(cmd *cobra.Command, ko *KubeOptions) {
// By setting Namespace to nil, AddFlags won't create
// the --namespace flag, which we want to use for scoping
// kubecost requests (for some subcommands). We can then
// create a differently-named flag for the same variable.
ko.configFlags.Namespace = nil
ko.configFlags.AddFlags(cmd.Flags())

// Reset Namespace to a valid string to avoid a nil pointer
// deref.
emptyStr := ""
ko.configFlags.Namespace = &emptyStr

cmd.Flags().StringVarP(ko.configFlags.Namespace, "kubecost-namespace", "N", "kubecost", "The namespace that kubecost is deployed in. Requests to the API will be directed to this namespace.")
}

func (co *CostOptions) Complete() {
if co.showAll {
co.showCPUCost = true
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ func newCmdCostController(streams genericclioptions.IOStreams) *cobra.Command {
},
}

cmd.Flags().StringVarP(&controllerO.filterNamespace, "namespace-filter", "N", "", "Limit results to only one namespace. Defaults to all namespaces.")
cmd.Flags().StringVarP(&controllerO.filterNamespace, "namespace", "n", "", "Limit results to only one namespace. Defaults to all namespaces.")
addCostOptionsFlags(cmd, &controllerO.CostOptions)
kubeO.configFlags.AddFlags(cmd.Flags())
addKubeOptionsFlags(cmd, kubeO)

return cmd
}
Expand Down
23 changes: 5 additions & 18 deletions pkg/cmd/cost.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ var (
%[1]s cost deployment --window month -A
# Show the projected monthly rate for each deployment in the "kubecost" namespace based on the last 3 days of activity with CPU cost breakdown.
%[1]s cost deployment --window 3d --show-cpu -N kubecost
%[1]s cost deployment --window 3d --show-cpu -n kubecost
# The same, but with a non-standard Kubecost deployment in the namespace "kubecost-staging" with the cost analyzer service called "kubecost-staging-cost-analyzer".
%[1]s cost deployment --window 3d --show-cpu -N kubecost -n kubecost-staging --service-name kubecost-staging-cost-analyzer
%[1]s cost deployment --window 3d --show-cpu -n kubecost -N kubecost-staging --service-name kubecost-staging-cost-analyzer
`

errNoContext = fmt.Errorf("no context is currently set, use %q to select a new one", "kubectl config use-context <context>")
Expand All @@ -66,7 +66,9 @@ func NewKubeOptions(streams genericclioptions.IOStreams) *KubeOptions {
}
}

// NewCmdCost provides a cobra command wrapping CostOptions
// NewCmdCost provides a cobra command that acts as a parent command
// for all subcommands. It provides only basic usage information. See
// common.go and the subcommands for the actual functionality.
func NewCmdCost(
streams genericclioptions.IOStreams,
GitCommit string,
Expand All @@ -75,31 +77,16 @@ func NewCmdCost(
GitSummary string,
BuildDate string,
) *cobra.Command {
o := NewKubeOptions(streams)

cmd := &cobra.Command{
Use: "cost",
Short: "View cluster cost information.",
Example: fmt.Sprintf(costExample, "kubectl"),
SilenceUsage: true,
RunE: func(c *cobra.Command, args []string) error {
// if err := o.Complete(c, args); err != nil {
// return err
// }
// if err := o.Validate(); err != nil {
// return err
// }
// if err := o.Run(); err != nil {
// return err
// }
return fmt.Errorf("please use a subcommand")

// return nil
},
}

o.configFlags.AddFlags(cmd.Flags())

cmd.AddCommand(newCmdCostNamespace(streams))
cmd.AddCommand(newCmdCostDeployment(streams))
cmd.AddCommand(newCmdCostController(streams))
Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ func newCmdCostDeployment(streams genericclioptions.IOStreams) *cobra.Command {
},
}

cmd.Flags().StringVarP(&deploymentO.filterNamespace, "namespace-filter", "N", "", "Limit results to only one namespace. Defaults to all namespaces.")
addCostOptionsFlags(cmd, &deploymentO.CostOptions)
cmd.Flags().StringVarP(&deploymentO.filterNamespace, "namespace", "n", "", "Limit results to only one namespace. Defaults to all namespaces.")

kubeO.configFlags.AddFlags(cmd.Flags())
addCostOptionsFlags(cmd, &deploymentO.CostOptions)
addKubeOptionsFlags(cmd, kubeO)

return cmd
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ func newCmdCostLabel(streams genericclioptions.IOStreams) *cobra.Command {

cmd.Flags().StringVarP(&labelO.queryLabel, "label", "l", "", "The label to perform aggregation on, \"app\" is a common one.")
cmd.MarkFlagRequired("label")

addCostOptionsFlags(cmd, &labelO.CostOptions)
kubeO.configFlags.AddFlags(cmd.Flags())
addKubeOptionsFlags(cmd, kubeO)

return cmd
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func newCmdCostNamespace(streams genericclioptions.IOStreams) *cobra.Command {
}

addCostOptionsFlags(cmd, &namespaceO.CostOptions)
kubeO.configFlags.AddFlags(cmd.Flags())
addKubeOptionsFlags(cmd, kubeO)

return cmd
}
Expand Down

0 comments on commit ed2f29b

Please sign in to comment.