From 1fc630caa003bafc47141899478590bd42f32732 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Thu, 21 Jan 2016 11:45:24 -0800 Subject: [PATCH] add ip validation to componentconfig command line --- cmd/kubelet/app/options/options.go | 4 +- docs/admin/kubelet.md | 6 +- pkg/apis/componentconfig/helpers.go | 50 +++++++++++++++++ pkg/apis/componentconfig/helpers_test.go | 71 ++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 pkg/apis/componentconfig/helpers.go create mode 100644 pkg/apis/componentconfig/helpers_test.go diff --git a/cmd/kubelet/app/options/options.go b/cmd/kubelet/app/options/options.go index ef985ae8790..56ad1b6b6b0 100644 --- a/cmd/kubelet/app/options/options.go +++ b/cmd/kubelet/app/options/options.go @@ -134,7 +134,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.ManifestURL, "manifest-url", s.ManifestURL, "URL for accessing the container manifest") fs.StringVar(&s.ManifestURLHeader, "manifest-url-header", s.ManifestURLHeader, "HTTP header to use when accessing the manifest URL, with the key separated from the value with a ':', as in 'key:value'") fs.BoolVar(&s.EnableServer, "enable-server", s.EnableServer, "Enable the Kubelet's server") - fs.StringVar(&s.Address, "address", s.Address, "The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces)") + fs.Var(componentconfig.IPVar{&s.Address}, "address", "The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces)") fs.UintVar(&s.Port, "port", s.Port, "The port for the Kubelet to serve on.") fs.UintVar(&s.ReadOnlyPort, "read-only-port", s.ReadOnlyPort, "The read-only port for the Kubelet to serve on with no authentication/authorization (set to 0 to disable)") fs.StringVar(&s.TLSCertFile, "tls-cert-file", s.TLSCertFile, ""+ @@ -166,7 +166,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) { fs.Var(&s.KubeConfig, "kubeconfig", "Path to a kubeconfig file, specifying how to authenticate to API server (the master location is set by the api-servers flag).") fs.UintVar(&s.CAdvisorPort, "cadvisor-port", s.CAdvisorPort, "The port of the localhost cAdvisor endpoint") fs.IntVar(&s.HealthzPort, "healthz-port", s.HealthzPort, "The port of the localhost healthz endpoint") - fs.StringVar(&s.HealthzBindAddress, "healthz-bind-address", s.HealthzBindAddress, "The IP address for the healthz server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces)") + fs.Var(componentconfig.IPVar{&s.HealthzBindAddress}, "healthz-bind-address", "The IP address for the healthz server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces)") fs.IntVar(&s.OOMScoreAdj, "oom-score-adj", s.OOMScoreAdj, "The oom-score-adj value for kubelet process. Values must be within the range [-1000, 1000]") fs.StringSliceVar(&s.APIServerList, "api-servers", []string{}, "List of Kubernetes API servers for publishing events, and reading pods and services. (ip:port), comma separated.") fs.BoolVar(&s.RegisterNode, "register-node", s.RegisterNode, "Register the node with the apiserver (defaults to true if --api-servers is set)") diff --git a/docs/admin/kubelet.md b/docs/admin/kubelet.md index 42a99a7aca7..36bb9c46c77 100644 --- a/docs/admin/kubelet.md +++ b/docs/admin/kubelet.md @@ -64,7 +64,7 @@ kubelet ### Options ``` - --address="0.0.0.0": The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces) + --address=0.0.0.0: The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces) --allow-privileged[=false]: If true, allow containers to request privileged mode. [default=false] --api-servers=[]: List of Kubernetes API servers for publishing events, and reading pods and services. (ip:port), comma separated. --cadvisor-port=4194: The port of the localhost cAdvisor endpoint @@ -89,7 +89,7 @@ kubelet --experimental-flannel-overlay[=false]: Experimental support for starting the kubelet with the default overlay network (flannel). Assumes flanneld is already running in client mode. [default=false] --file-check-frequency=20s: Duration between checking config files for new data --google-json-key="": The Google Cloud Platform Service Account JSON Key to use for authentication. - --healthz-bind-address="127.0.0.1": The IP address for the healthz server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces) + --healthz-bind-address=127.0.0.1: The IP address for the healthz server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces) --healthz-port=10248: The port of the localhost healthz endpoint --host-ipc-sources="*": Comma-separated list of sources from which the Kubelet allows pods to use the host ipc namespace. [default="*"] --host-network-sources="*": Comma-separated list of sources from which the Kubelet allows pods to use of host network. [default="*"] @@ -145,7 +145,7 @@ kubelet --volume-plugin-dir="/usr/libexec/kubernetes/kubelet-plugins/volume/exec/": The full path of the directory in which to search for additional third party volume plugins ``` -###### Auto generated by spf13/cobra on 15-Jan-2016 +###### Auto generated by spf13/cobra on 21-Jan-2016 diff --git a/pkg/apis/componentconfig/helpers.go b/pkg/apis/componentconfig/helpers.go new file mode 100644 index 00000000000..e18dcea93b1 --- /dev/null +++ b/pkg/apis/componentconfig/helpers.go @@ -0,0 +1,50 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 componentconfig + +import ( + "fmt" + "net" +) + +// used for validating command line ip addresses. +type IPVar struct { + Val *string +} + +func (v IPVar) Set(s string) error { + if net.ParseIP(s) == nil { + return fmt.Errorf("%q is not a valid IP address", s) + } + if v.Val == nil { + // it's okay to panic here since this is programmer error + panic("the string pointer passed into IPVar should not be nil") + } + *v.Val = s + return nil +} + +func (v IPVar) String() string { + if v.Val == nil { + return "" + } + return *v.Val +} + +func (v IPVar) Type() string { + return "ip" +} diff --git a/pkg/apis/componentconfig/helpers_test.go b/pkg/apis/componentconfig/helpers_test.go new file mode 100644 index 00000000000..7aece8257f1 --- /dev/null +++ b/pkg/apis/componentconfig/helpers_test.go @@ -0,0 +1,71 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 componentconfig + +import ( + "strings" + "testing" + + "github.com/spf13/pflag" +) + +func TestIPVar(t *testing.T) { + defaultIP := "0.0.0.0" + cases := []struct { + argc string + expectErr bool + expectVal string + }{ + + { + argc: "blah --ip=1.2.3.4", + expectVal: "1.2.3.4", + }, + { + argc: "blah --ip=1.2.3.4a", + expectErr: true, + expectVal: defaultIP, + }, + } + for _, c := range cases { + fs := pflag.NewFlagSet("blah", pflag.PanicOnError) + ip := defaultIP + fs.Var(IPVar{&ip}, "ip", "the ip") + + var err error + func() { + defer func() { + if r := recover(); r != nil { + err = r.(error) + } + }() + fs.Parse(strings.Split(c.argc, " ")) + }() + + if c.expectErr && err == nil { + t.Errorf("did not observe an expected error") + continue + } + if !c.expectErr && err != nil { + t.Errorf("observed an unexpected error") + continue + } + if c.expectVal != ip { + t.Errorf("unexpected ip: expected %q, saw %q", c.expectVal, ip) + } + } +}