Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Follow-up PR] Add flag to list all avialable configurations. #17099

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions Documentation/cmdref/cilium_config.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions Documentation/cmdref/cilium_config_get.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions api/v1/models/daemon_configuration_status.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/v1/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2198,6 +2198,10 @@ definitions:
egress-multi-home-ip-rule-compat:
description: Configured compatibility mode for --egress-multi-home-ip-rule-compat
type: boolean
daemonConfigurationMap:
description: Config map which contains all the active daemon configurations
additionalProperties:
type: object
DatapathMode:
description: Datapath mode
type: string
Expand Down
12 changes: 12 additions & 0 deletions api/v1/server/embedded_spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 76 additions & 15 deletions cilium/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package cmd
import (
"fmt"
"os"
"reflect"
"sort"
"strconv"
"strings"

Expand All @@ -16,7 +18,11 @@ import (
"github.com/spf13/cobra"
)

var numPages int
var (
numPages int
listReadOnlyConfigurations bool
listAllConfigurations bool
)

// configCmd represents the config command
var configCmd = &cobra.Command{
Expand All @@ -37,6 +43,8 @@ var configCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(configCmd)
configCmd.Flags().BoolVarP(&listOptions, "list-options", "", false, "List available options")
configCmd.Flags().BoolVarP(&listReadOnlyConfigurations, "read-only", "r", false, "Display Read Only Configurations")
configCmd.Flags().BoolVarP(&listAllConfigurations, "all", "a", false, "Display All Cilium Configurations")
configCmd.Flags().IntVarP(&numPages, "num-pages", "n", 0, "Number of pages for perf ring buffer. New values have to be > 0")
command.AddJSONOutput(configCmd)
}
Expand All @@ -58,20 +66,7 @@ func configDaemon(cmd *cobra.Command, opts []string) {
dOpts["MonitorNumPages"] = strconv.Itoa(numPages)
}
} else if len(opts) == 0 {
if command.OutputJSON() {
if err := command.PrintOutput(cfgStatus.Realized.Options); err != nil {
os.Exit(1)
}
return
}
dumpConfig(cfgStatus.Immutable)
dumpConfig(cfgStatus.Realized.Options)
fmt.Printf("%-24s %s\n", "k8s-configuration", cfgStatus.K8sConfiguration)
fmt.Printf("%-24s %s\n", "k8s-endpoint", cfgStatus.K8sEndpoint)
fmt.Printf("%-24s %s\n", "PolicyEnforcement", cfgStatus.Realized.PolicyEnforcement)
if cfgStatus.NodeMonitor != nil {
fmt.Printf("%-24s %d\n", "MonitorNumPages", cfgStatus.NodeMonitor.Npages)
}
printConfigurations(cfgStatus)
return
}

Expand Down Expand Up @@ -111,3 +106,69 @@ func configDaemon(cmd *cobra.Command, opts []string) {
Fatalf("Unable to change agent configuration: %s\n", err)
}
}

func printConfigurations(cfgStatus *models.DaemonConfigurationStatus) {
if command.OutputJSON() {
if listReadOnlyConfigurations {
if err := command.PrintOutput(cfgStatus.DaemonConfigurationMap); err != nil {
os.Exit(1)
}
} else if listAllConfigurations {
if err := command.PrintOutputWithPatch(cfgStatus.DaemonConfigurationMap, cfgStatus.Realized); err != nil {
os.Exit(1)
}
} else {
if err := command.PrintOutput(cfgStatus.Realized); err != nil {
os.Exit(1)
}
}
return
}
if listReadOnlyConfigurations {
dumpReadOnlyConfigs(cfgStatus)
} else if listAllConfigurations {
dumpReadOnlyConfigs(cfgStatus)
dumpReadWriteConfigs(cfgStatus)
} else {
dumpReadWriteConfigs(cfgStatus)
}
}

func dumpReadOnlyConfigs(cfgStatus *models.DaemonConfigurationStatus) {
fmt.Print("#### Read-Only Configurations ####\n")
keys := make([]string, 0, len(cfgStatus.DaemonConfigurationMap))
for k := range cfgStatus.DaemonConfigurationMap {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := cfgStatus.DaemonConfigurationMap[k]
if reflect.ValueOf(v).Kind() == reflect.Map {
mapString := make(map[string]string)
m, ok := v.(map[string]interface{})
if ok {
fmt.Println(k)
for key, value := range m {
mapString[key] = fmt.Sprintf("%v", value)
}
dumpConfig(mapString, true)
continue
} else {
fmt.Fprintf(os.Stderr, "Error: cannot cast daemon config map to map[string]interface{}\n")
}
}
fmt.Printf("%-34s: %v\n", k, v)
}
fmt.Printf("%-34s: %s\n", "k8s-configuration", cfgStatus.K8sConfiguration)
fmt.Printf("%-34s: %s\n", "k8s-endpoint", cfgStatus.K8sEndpoint)
dumpConfig(cfgStatus.Immutable, false)
}

func dumpReadWriteConfigs(cfgStatus *models.DaemonConfigurationStatus) {
fmt.Print("##### Read-Write Configurations #####\n")
dumpConfig(cfgStatus.Realized.Options, false)
if cfgStatus.NodeMonitor != nil {
fmt.Printf("%-34s: %d\n", "MonitorNumPages", cfgStatus.NodeMonitor.Npages)
}
fmt.Printf("%-34s: %s\n", "PolicyEnforcement", cfgStatus.Realized.PolicyEnforcement)
}
84 changes: 84 additions & 0 deletions cilium/cmd/config_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2021 Authors of Cilium
//
// Licensed 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 cmd

import (
"fmt"
"regexp"
"strings"

"github.com/cilium/cilium/pkg/command"
"github.com/cilium/cilium/test/helpers"
"github.com/spf13/cobra"
)

var (
removeHyphen = regexp.MustCompile(`[^\w]`)
)

// configGetCmd represents the config get command
var configGetCmd = &cobra.Command{
Use: "get <config name>",
Short: "Retrieve cilium configuration",
PreRun: requireConfigName,
Run: func(cmd *cobra.Command, args []string) {
// removing hyphen from the config name and transforming it to lower case
configName := removeHyphen.ReplaceAllString(strings.ToLower(args[0]), "")
resp, err := client.ConfigGet()
if err != nil {
Fatalf("Error while retrieving configuration: %s", err)
}
if resp.Status == nil {
Fatalf("Empty configuration status returned")
}

readWriteConfigMap := make(map[string]interface{})
readOnlyConfigMap := resp.Status.DaemonConfigurationMap

for k, v := range resp.Status.Realized.Options {
readWriteConfigMap[k] = v
}
readWriteConfigMap[helpers.PolicyEnforcement] = resp.Status.Realized.PolicyEnforcement

// Key values are named as field names of `DaemonConfig` struct
// to match configuration input, map keys are transformed to lower case
readWriteConfigMap = mapKeysToLowerCase(readWriteConfigMap)
readOnlyConfigMap = mapKeysToLowerCase(readOnlyConfigMap)

// conifgMap holds both read-only and read-write configurations
configMap := mergeMaps(readOnlyConfigMap, readWriteConfigMap)

if value, ok := configMap[configName]; ok {
fmt.Printf("%v\n", value)
} else {
Fatalf("Configuration does not exist")
}
},
}

func init() {
configCmd.AddCommand(configGetCmd)
command.AddJSONOutput(configGetCmd)
}

func requireConfigName(cmd *cobra.Command, args []string) {
if len(args) < 1 {
Usagef(cmd, "Missing config name argument")
}

if args[0] == "" {
Usagef(cmd, "Empty config argument")
}
}
4 changes: 2 additions & 2 deletions cilium/cmd/endpoint_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ func configEndpoint(cmd *cobra.Command, args []string) {
return
}

dumpConfig(cfg.Immutable)
dumpConfig(cfg.Realized.Options)
dumpConfig(cfg.Immutable, false)
dumpConfig(cfg.Realized.Options, false)
return
}

Expand Down
33 changes: 29 additions & 4 deletions cilium/cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"os"
"path/filepath"
"reflect"
"regexp"
"sort"
"strconv"
Expand Down Expand Up @@ -358,7 +359,7 @@ func updatePolicyKey(pa *PolicyUpdateArgs, add bool) {
}

// dumpConfig pretty prints boolean options
func dumpConfig(Opts map[string]string) {
func dumpConfig(Opts map[string]string, indented bool) {
opts := []string{}
for k := range Opts {
opts = append(opts, k)
Expand All @@ -368,17 +369,34 @@ func dumpConfig(Opts map[string]string) {
for _, k := range opts {
// XXX: Reuse the format function from *option.Library
value = Opts[k]
formatStr := "%-34s: %s\n"
if indented {
formatStr = "\t%-26s: %s\n"
}
if enabled, err := option.NormalizeBool(value); err != nil {
// If it cannot be parsed as a bool, just format the value.
fmt.Printf("%-24s %s\n", k, value)
fmt.Printf(formatStr, k, value)
} else if enabled == option.OptionDisabled {
fmt.Printf("%-24s %s\n", k, "Disabled")
fmt.Printf(formatStr, k, "Disabled")
} else {
fmt.Printf("%-24s %s\n", k, "Enabled")
fmt.Printf(formatStr, k, "Enabled")
}
}
}

func mapKeysToLowerCase(s map[string]interface{}) map[string]interface{} {
m := make(map[string]interface{})
for k, v := range s {
if reflect.ValueOf(v).Kind() == reflect.Map {
for i, j := range v.(map[string]interface{}) {
m[strings.ToLower(i)] = j
}
}
m[strings.ToLower(k)] = v
}
return m
}

// getIpv6EnableStatus api returns the EnableIPv6 status
// by consulting the cilium-agent otherwise reads from the
// runtime system config
Expand Down Expand Up @@ -406,3 +424,10 @@ func getIpv6EnableStatus() bool {
// returning the EnableIPv6 default status
return defaults.EnableIPv6
}

func mergeMaps(m1, m2 map[string]interface{}) map[string]interface{} {
for k, v := range m1 {
m2[k] = v
}
return m2
}
2 changes: 1 addition & 1 deletion clustermesh-apiserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (c configuration) LocalClusterName() string {
return c.clusterName
}

func (c configuration) K8sServiceProxyName() string {
func (c configuration) K8sServiceProxyNameValue() string {
return c.serviceProxyName
}

Expand Down