mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-19 14:53:07 +00:00
nfd-master: use flag for command line parsing
This commit is contained in:
parent
a7d0439af6
commit
47033db9c1
8 changed files with 171 additions and 205 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Kubernetes Authors.
|
Copyright 2019-2021 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -17,14 +17,14 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/docopt/docopt-go"
|
|
||||||
master "sigs.k8s.io/node-feature-discovery/pkg/nfd-master"
|
master "sigs.k8s.io/node-feature-discovery/pkg/nfd-master"
|
||||||
|
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,17 +34,29 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
flags := flag.NewFlagSet(ProgramName, flag.ExitOnError)
|
||||||
|
|
||||||
|
printVersion := flags.Bool("version", false, "Print version and exit.")
|
||||||
|
|
||||||
|
args := initFlags(flags)
|
||||||
|
|
||||||
|
_ = flags.Parse(os.Args[1:])
|
||||||
|
if len(flags.Args()) > 0 {
|
||||||
|
fmt.Printf("unknown command line argument: %s\n", flags.Args()[0])
|
||||||
|
flags.Usage()
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *printVersion {
|
||||||
|
fmt.Println(ProgramName, version.Get())
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
// Assert that the version is known
|
// Assert that the version is known
|
||||||
if version.Undefined() {
|
if version.Undefined() {
|
||||||
log.Print("WARNING: version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.")
|
log.Print("WARNING: version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse command-line arguments.
|
|
||||||
args, err := argsParse(nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to parse command line: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get new NfdMaster instance
|
// Get new NfdMaster instance
|
||||||
instance, err := master.NewNfdMaster(args)
|
instance, err := master.NewNfdMaster(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -56,88 +68,37 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// argsParse parses the command line arguments passed to the program.
|
func initFlags(flagset *flag.FlagSet) *master.Args {
|
||||||
// The argument argv is passed only for testing purposes.
|
args := &master.Args{
|
||||||
func argsParse(argv []string) (master.Args, error) {
|
LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")},
|
||||||
args := master.Args{}
|
|
||||||
usage := fmt.Sprintf(`%s.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
%s [--prune] [--no-publish] [--label-whitelist=<pattern>] [--port=<port>]
|
|
||||||
[--ca-file=<path>] [--cert-file=<path>] [--key-file=<path>]
|
|
||||||
[--verify-node-name] [--extra-label-ns=<list>] [--resource-labels=<list>]
|
|
||||||
[--kubeconfig=<path>] [--instance=<name>]
|
|
||||||
%s -h | --help
|
|
||||||
%s --version
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h --help Show this screen.
|
|
||||||
--version Output version and exit.
|
|
||||||
--prune Prune all NFD related attributes from all nodes
|
|
||||||
of the cluster and exit.
|
|
||||||
--instance=<name> Instance name. Used to separate annotation
|
|
||||||
namespaces for multiple parallel deployments.
|
|
||||||
[Default: ]
|
|
||||||
--kubeconfig=<path> Kubeconfig to use [Default: ]
|
|
||||||
of the cluster and exit.
|
|
||||||
--port=<port> Port on which to listen for connections.
|
|
||||||
[Default: 8080]
|
|
||||||
--ca-file=<path> Root certificate for verifying connections
|
|
||||||
[Default: ]
|
|
||||||
--cert-file=<path> Certificate used for authenticating connections
|
|
||||||
[Default: ]
|
|
||||||
--key-file=<path> Private key matching --cert-file
|
|
||||||
[Default: ]
|
|
||||||
--verify-node-name Verify worker node name against CN from the TLS
|
|
||||||
certificate. Only has effect when TLS authentication
|
|
||||||
has been enabled.
|
|
||||||
--no-publish Do not publish feature labels
|
|
||||||
--label-whitelist=<pattern> Regular expression to filter label names to
|
|
||||||
publish to the Kubernetes API server.
|
|
||||||
NB: the label namespace is omitted i.e. the filter
|
|
||||||
is only applied to the name part after '/'.
|
|
||||||
[Default: ]
|
|
||||||
--extra-label-ns=<list> Comma separated list of allowed extra label namespaces
|
|
||||||
[Default: ]
|
|
||||||
--resource-labels=<list> Comma separated list of labels to be exposed as extended resources.
|
|
||||||
[Default: ]`,
|
|
||||||
ProgramName,
|
|
||||||
ProgramName,
|
|
||||||
ProgramName,
|
|
||||||
ProgramName,
|
|
||||||
)
|
|
||||||
|
|
||||||
arguments, _ := docopt.ParseArgs(usage, argv,
|
|
||||||
fmt.Sprintf("%s %s", ProgramName, version.Get()))
|
|
||||||
|
|
||||||
// Parse argument values as usable types.
|
|
||||||
var err error
|
|
||||||
args.Instance = arguments["--instance"].(string)
|
|
||||||
if ok, _ := regexp.MatchString(`^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$`, args.Instance); args.Instance != "" && !ok {
|
|
||||||
return args, fmt.Errorf("invalid --instance %q: instance name "+
|
|
||||||
"must start and end with an alphanumeric character and may only contain "+
|
|
||||||
"alphanumerics, `-`, `_` or `.`", args.Instance)
|
|
||||||
}
|
}
|
||||||
args.CaFile = arguments["--ca-file"].(string)
|
|
||||||
args.CertFile = arguments["--cert-file"].(string)
|
|
||||||
args.KeyFile = arguments["--key-file"].(string)
|
|
||||||
args.NoPublish = arguments["--no-publish"].(bool)
|
|
||||||
args.Port, err = strconv.Atoi(arguments["--port"].(string))
|
|
||||||
if err != nil {
|
|
||||||
return args, fmt.Errorf("invalid --port defined: %s", err)
|
|
||||||
}
|
|
||||||
args.LabelWhiteList, err = regexp.Compile(arguments["--label-whitelist"].(string))
|
|
||||||
if err != nil {
|
|
||||||
return args, fmt.Errorf("error parsing whitelist regex (%s): %s", arguments["--label-whitelist"], err)
|
|
||||||
}
|
|
||||||
args.VerifyNodeName = arguments["--verify-node-name"].(bool)
|
|
||||||
args.ExtraLabelNs = map[string]struct{}{}
|
|
||||||
for _, n := range strings.Split(arguments["--extra-label-ns"].(string), ",") {
|
|
||||||
args.ExtraLabelNs[n] = struct{}{}
|
|
||||||
}
|
|
||||||
args.ResourceLabels = strings.Split(arguments["--resource-labels"].(string), ",")
|
|
||||||
args.Prune = arguments["--prune"].(bool)
|
|
||||||
args.Kubeconfig = arguments["--kubeconfig"].(string)
|
|
||||||
|
|
||||||
return args, nil
|
flagset.StringVar(&args.CaFile, "ca-file", "",
|
||||||
|
"Root certificate for verifying connections")
|
||||||
|
flagset.StringVar(&args.CertFile, "cert-file", "",
|
||||||
|
"Certificate used for authenticating connections")
|
||||||
|
flagset.Var(&args.ExtraLabelNs, "extra-label-ns",
|
||||||
|
"Comma separated list of allowed extra label namespaces")
|
||||||
|
flagset.StringVar(&args.Instance, "instance", "",
|
||||||
|
"Instance name. Used to separate annotation namespaces for multiple parallel deployments.")
|
||||||
|
flagset.StringVar(&args.KeyFile, "key-file", "",
|
||||||
|
"Private key matching -cert-file")
|
||||||
|
flagset.StringVar(&args.Kubeconfig, "kubeconfig", "",
|
||||||
|
"Kubeconfig to use")
|
||||||
|
flagset.Var(&args.LabelWhiteList, "label-whitelist",
|
||||||
|
"Regular expression to filter label names to publish to the Kubernetes API server. "+
|
||||||
|
"NB: the label namespace is omitted i.e. the filter is only applied to the name part after '/'.")
|
||||||
|
flagset.BoolVar(&args.NoPublish, "no-publish", false,
|
||||||
|
"Do not publish feature labels")
|
||||||
|
flagset.IntVar(&args.Port, "port", 8080,
|
||||||
|
"Port on which to listen for connections.")
|
||||||
|
flagset.BoolVar(&args.Prune, "prune", false,
|
||||||
|
"Prune all NFD related attributes from all nodes of the cluaster and exit.")
|
||||||
|
flagset.Var(&args.ResourceLabels, "resource-labels",
|
||||||
|
"Comma separated list of labels to be exposed as extended resources.")
|
||||||
|
flagset.BoolVar(&args.VerifyNodeName, "verify-node-name", false,
|
||||||
|
"Verify worker node name against CN from the TLS certificate. "+
|
||||||
|
"Only takes effect when TLS authentication has been enabled.")
|
||||||
|
|
||||||
|
return args
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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 main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestArgsParse(t *testing.T) {
|
|
||||||
Convey("When parsing command line arguments", t, func() {
|
|
||||||
Convey("When --no-publish and --oneshot flags are passed", func() {
|
|
||||||
args, err := argsParse([]string{"--no-publish"})
|
|
||||||
Convey("noPublish is set and args.sources is set to the default value", func() {
|
|
||||||
So(args.NoPublish, ShouldBeTrue)
|
|
||||||
So(len(args.LabelWhiteList.String()), ShouldEqual, 0)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("When valid args are specified", func() {
|
|
||||||
args, err := argsParse([]string{"--label-whitelist=.*rdt.*", "--port=1234", "--cert-file=crt", "--key-file=key", "--ca-file=ca"})
|
|
||||||
Convey("Argument parsing should succeed and args set to correct values", func() {
|
|
||||||
So(args.NoPublish, ShouldBeFalse)
|
|
||||||
So(args.Port, ShouldEqual, 1234)
|
|
||||||
So(args.CertFile, ShouldEqual, "crt")
|
|
||||||
So(args.KeyFile, ShouldEqual, "key")
|
|
||||||
So(args.CaFile, ShouldEqual, "ca")
|
|
||||||
So(args.LabelWhiteList.String(), ShouldResemble, ".*rdt.*")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Convey("When invalid --port is defined", func() {
|
|
||||||
_, err := argsParse([]string{"--port=123a"})
|
|
||||||
Convey("argsParse should fail", func() {
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -164,43 +164,34 @@ $ docker run --rm --name=nfd-test ${NFD_CONTAINER_IMAGE} nfd-master --no-publish
|
||||||
Command line flags of nfd-master:
|
Command line flags of nfd-master:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker run --rm ${NFD_CONTAINER_IMAGE} nfd-master --help
|
$ docker run --rm ${NFD_CONTAINER_IMAGE} nfd-master -help
|
||||||
...
|
Usage of nfd-master:
|
||||||
Usage:
|
-ca-file string
|
||||||
nfd-master [--prune] [--no-publish] [--label-whitelist=<pattern>] [--port=<port>]
|
Root certificate for verifying connections
|
||||||
[--ca-file=<path>] [--cert-file=<path>] [--key-file=<path>]
|
-cert-file string
|
||||||
[--verify-node-name] [--extra-label-ns=<list>] [--resource-labels=<list>]
|
Certificate used for authenticating connections
|
||||||
[--kubeconfig=<path>]
|
-extra-label-ns value
|
||||||
nfd-master -h | --help
|
Comma separated list of allowed extra label namespaces
|
||||||
nfd-master --version
|
-instance string
|
||||||
|
Instance name. Used to separate annotation namespaces for multiple parallel deployments.
|
||||||
Options:
|
-key-file string
|
||||||
-h --help Show this screen.
|
Private key matching -cert-file
|
||||||
--version Output version and exit.
|
-kubeconfig string
|
||||||
--prune Prune all NFD related attributes from all nodes
|
Kubeconfig to use
|
||||||
of the cluster and exit.
|
-label-whitelist value
|
||||||
--kubeconfig=<path> Kubeconfig to use [Default: ]
|
Regular expression to filter label names to publish to the Kubernetes API server. NB: the label namespace is omitted i.e. the filter is only applied to the name part after '/'.
|
||||||
--port=<port> Port on which to listen for connections.
|
-no-publish
|
||||||
[Default: 8080]
|
Do not publish feature labels
|
||||||
--ca-file=<path> Root certificate for verifying connections
|
-port int
|
||||||
[Default: ]
|
Port on which to listen for connections. (default 8080)
|
||||||
--cert-file=<path> Certificate used for authenticating connections
|
-prune
|
||||||
[Default: ]
|
Prune all NFD related attributes from all nodes of the cluaster and exit.
|
||||||
--key-file=<path> Private key matching --cert-file
|
-resource-labels value
|
||||||
[Default: ]
|
Comma separated list of labels to be exposed as extended resources.
|
||||||
--verify-node-name Verify worker node name against CN from the TLS
|
-verify-node-name
|
||||||
certificate. Only has effect when TLS authentication
|
Verify worker node name against CN from the TLS certificate. Only takes effect when TLS authentication has been enabled.
|
||||||
has been enabled.
|
-version
|
||||||
--no-publish Do not publish feature labels
|
Print version and exit.
|
||||||
--label-whitelist=<pattern> Regular expression to filter label names to
|
|
||||||
publish to the Kubernetes API server.
|
|
||||||
NB: the label namespace is omitted i.e. the filter
|
|
||||||
is only applied to the name part after '/'.
|
|
||||||
[Default: ]
|
|
||||||
--extra-label-ns=<list> Comma separated list of allowed extra label namespaces
|
|
||||||
[Default: ]
|
|
||||||
--resource-labels=<list> Comma separated list of labels to be exposed as extended resources.
|
|
||||||
[Default: ]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### NFD-Worker
|
### NFD-Worker
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Kubernetes Authors.
|
Copyright 2019-2021 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -34,6 +34,7 @@ import (
|
||||||
k8sclient "k8s.io/client-go/kubernetes"
|
k8sclient "k8s.io/client-go/kubernetes"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
|
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/labeler"
|
"sigs.k8s.io/node-feature-discovery/pkg/labeler"
|
||||||
|
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
@ -55,7 +56,7 @@ func newMockMaster(apihelper apihelper.APIHelpers) *nfdMaster {
|
||||||
return &nfdMaster{
|
return &nfdMaster{
|
||||||
nodeName: mockNodeName,
|
nodeName: mockNodeName,
|
||||||
annotationNs: AnnotationNsBase,
|
annotationNs: AnnotationNsBase,
|
||||||
args: Args{LabelWhiteList: regexp.MustCompile("")},
|
args: Args{LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")}},
|
||||||
apihelper: apihelper,
|
apihelper: apihelper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +340,7 @@ func TestSetLabels(t *testing.T) {
|
||||||
apihelper.NewJsonPatch("add", "/metadata/labels", LabelNs+"/feature-2", mockLabels["feature-2"]),
|
apihelper.NewJsonPatch("add", "/metadata/labels", LabelNs+"/feature-2", mockLabels["feature-2"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
mockMaster.args.LabelWhiteList = regexp.MustCompile("^f.*2$")
|
mockMaster.args.LabelWhiteList.Regexp = *regexp.MustCompile("^f.*2$")
|
||||||
mockHelper.On("GetClient").Return(mockClient, nil)
|
mockHelper.On("GetClient").Return(mockClient, nil)
|
||||||
mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil)
|
mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil)
|
||||||
mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil)
|
mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil)
|
||||||
|
@ -390,7 +391,7 @@ func TestSetLabels(t *testing.T) {
|
||||||
apihelper.NewJsonPatch("add", "/status/capacity", LabelNs+"/feature-3", mockLabels["feature-3"]),
|
apihelper.NewJsonPatch("add", "/status/capacity", LabelNs+"/feature-3", mockLabels["feature-3"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
mockMaster.args.ResourceLabels = []string{"feature-3", "feature-1"}
|
mockMaster.args.ResourceLabels = map[string]struct{}{"feature-3": struct{}{}, "feature-1": struct{}{}}
|
||||||
mockHelper.On("GetClient").Return(mockClient, nil)
|
mockHelper.On("GetClient").Return(mockClient, nil)
|
||||||
mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil)
|
mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil)
|
||||||
mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil)
|
mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Kubernetes Authors.
|
Copyright 2019-2021 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -38,6 +38,7 @@ import (
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
|
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
|
||||||
pb "sigs.k8s.io/node-feature-discovery/pkg/labeler"
|
pb "sigs.k8s.io/node-feature-discovery/pkg/labeler"
|
||||||
|
"sigs.k8s.io/node-feature-discovery/pkg/utils"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
"sigs.k8s.io/node-feature-discovery/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,16 +75,16 @@ type Annotations map[string]string
|
||||||
type Args struct {
|
type Args struct {
|
||||||
CaFile string
|
CaFile string
|
||||||
CertFile string
|
CertFile string
|
||||||
ExtraLabelNs map[string]struct{}
|
ExtraLabelNs utils.StringSetVal
|
||||||
Instance string
|
Instance string
|
||||||
KeyFile string
|
KeyFile string
|
||||||
Kubeconfig string
|
Kubeconfig string
|
||||||
LabelWhiteList *regexp.Regexp
|
LabelWhiteList utils.RegexpVal
|
||||||
NoPublish bool
|
NoPublish bool
|
||||||
Port int
|
Port int
|
||||||
Prune bool
|
Prune bool
|
||||||
VerifyNodeName bool
|
VerifyNodeName bool
|
||||||
ResourceLabels []string
|
ResourceLabels utils.StringSetVal
|
||||||
}
|
}
|
||||||
|
|
||||||
type NfdMaster interface {
|
type NfdMaster interface {
|
||||||
|
@ -102,8 +103,8 @@ type nfdMaster struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new NfdMaster server instance.
|
// Create new NfdMaster server instance.
|
||||||
func NewNfdMaster(args Args) (NfdMaster, error) {
|
func NewNfdMaster(args *Args) (NfdMaster, error) {
|
||||||
nfd := &nfdMaster{args: args,
|
nfd := &nfdMaster{args: *args,
|
||||||
nodeName: os.Getenv("NODE_NAME"),
|
nodeName: os.Getenv("NODE_NAME"),
|
||||||
ready: make(chan bool, 1),
|
ready: make(chan bool, 1),
|
||||||
}
|
}
|
||||||
|
@ -111,6 +112,11 @@ func NewNfdMaster(args Args) (NfdMaster, error) {
|
||||||
if args.Instance == "" {
|
if args.Instance == "" {
|
||||||
nfd.annotationNs = AnnotationNsBase
|
nfd.annotationNs = AnnotationNsBase
|
||||||
} else {
|
} else {
|
||||||
|
if ok, _ := regexp.MatchString(`^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$`, args.Instance); !ok {
|
||||||
|
return nfd, fmt.Errorf("invalid --instance %q: instance name "+
|
||||||
|
"must start and end with an alphanumeric character and may only contain "+
|
||||||
|
"alphanumerics, `-`, `_` or `.`", args.Instance)
|
||||||
|
}
|
||||||
nfd.annotationNs = args.Instance + "." + AnnotationNsBase
|
nfd.annotationNs = args.Instance + "." + AnnotationNsBase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +289,7 @@ func (m *nfdMaster) updateMasterNode() error {
|
||||||
// into extended resources. This function also handles proper namespacing of
|
// into extended resources. This function also handles proper namespacing of
|
||||||
// labels and ERs, i.e. adds the possibly missing default namespace for labels
|
// labels and ERs, i.e. adds the possibly missing default namespace for labels
|
||||||
// arriving through the gRPC API.
|
// arriving through the gRPC API.
|
||||||
func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelWhiteList *regexp.Regexp, extendedResourceNames []string) (Labels, ExtendedResources) {
|
func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelWhiteList regexp.Regexp, extendedResourceNames map[string]struct{}) (Labels, ExtendedResources) {
|
||||||
outLabels := Labels{}
|
outLabels := Labels{}
|
||||||
|
|
||||||
for label, value := range labels {
|
for label, value := range labels {
|
||||||
|
@ -310,7 +316,7 @@ func filterFeatureLabels(labels Labels, extraLabelNs map[string]struct{}, labelW
|
||||||
|
|
||||||
// Remove labels which are intended to be extended resources
|
// Remove labels which are intended to be extended resources
|
||||||
extendedResources := ExtendedResources{}
|
extendedResources := ExtendedResources{}
|
||||||
for _, extendedResourceName := range extendedResourceNames {
|
for extendedResourceName := range extendedResourceNames {
|
||||||
// Add possibly missing default ns
|
// Add possibly missing default ns
|
||||||
extendedResourceName = addNs(extendedResourceName, LabelNs)
|
extendedResourceName = addNs(extendedResourceName, LabelNs)
|
||||||
if value, ok := outLabels[extendedResourceName]; ok {
|
if value, ok := outLabels[extendedResourceName]; ok {
|
||||||
|
@ -354,7 +360,7 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
|
||||||
}
|
}
|
||||||
stdoutLogger.Printf("REQUEST Node: %s NFD-version: %s Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
|
stdoutLogger.Printf("REQUEST Node: %s NFD-version: %s Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
|
||||||
|
|
||||||
labels, extendedResources := filterFeatureLabels(r.Labels, m.args.ExtraLabelNs, m.args.LabelWhiteList, m.args.ResourceLabels)
|
labels, extendedResources := filterFeatureLabels(r.Labels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
|
||||||
|
|
||||||
if !m.args.NoPublish {
|
if !m.args.NoPublish {
|
||||||
// Advertise NFD worker version as an annotation
|
// Advertise NFD worker version as an annotation
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Kubernetes Authors.
|
Copyright 2019-2021 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -26,9 +26,9 @@ import (
|
||||||
func TestNewNfdMaster(t *testing.T) {
|
func TestNewNfdMaster(t *testing.T) {
|
||||||
Convey("When initializing new NfdMaster instance", t, func() {
|
Convey("When initializing new NfdMaster instance", t, func() {
|
||||||
Convey("When one of --cert-file, --key-file or --ca-file is missing", func() {
|
Convey("When one of --cert-file, --key-file or --ca-file is missing", func() {
|
||||||
_, err := m.NewNfdMaster(m.Args{CertFile: "crt", KeyFile: "key"})
|
_, err := m.NewNfdMaster(&m.Args{CertFile: "crt", KeyFile: "key"})
|
||||||
_, err2 := m.NewNfdMaster(m.Args{KeyFile: "key", CaFile: "ca"})
|
_, err2 := m.NewNfdMaster(&m.Args{KeyFile: "key", CaFile: "ca"})
|
||||||
_, err3 := m.NewNfdMaster(m.Args{CertFile: "crt", CaFile: "ca"})
|
_, err3 := m.NewNfdMaster(&m.Args{CertFile: "crt", CaFile: "ca"})
|
||||||
Convey("An error should be returned", func() {
|
Convey("An error should be returned", func() {
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err2, ShouldNotBeNil)
|
So(err2, ShouldNotBeNil)
|
||||||
|
|
|
@ -34,11 +34,11 @@ type testContext struct {
|
||||||
errs chan error
|
errs chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupTest(args nfdmaster.Args) testContext {
|
func setupTest(args *nfdmaster.Args) testContext {
|
||||||
// Fixed port and no-publish, for convenience
|
// Fixed port and no-publish, for convenience
|
||||||
args.NoPublish = true
|
args.NoPublish = true
|
||||||
args.Port = 8192
|
args.Port = 8192
|
||||||
args.LabelWhiteList = regexp.MustCompile("")
|
args.LabelWhiteList.Regexp = *regexp.MustCompile("")
|
||||||
m, err := nfdmaster.NewNfdMaster(args)
|
m, err := nfdmaster.NewNfdMaster(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Test setup failed: %v\n", err)
|
fmt.Printf("Test setup failed: %v\n", err)
|
||||||
|
@ -86,7 +86,7 @@ func TestNewNfdWorker(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRun(t *testing.T) {
|
func TestRun(t *testing.T) {
|
||||||
ctx := setupTest(nfdmaster.Args{})
|
ctx := setupTest(&nfdmaster.Args{})
|
||||||
defer teardownTest(ctx)
|
defer teardownTest(ctx)
|
||||||
Convey("When running nfd-worker against nfd-master", t, func() {
|
Convey("When running nfd-worker against nfd-master", t, func() {
|
||||||
Convey("When publishing features from fake source", func() {
|
Convey("When publishing features from fake source", func() {
|
||||||
|
@ -100,7 +100,7 @@ func TestRun(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunTls(t *testing.T) {
|
func TestRunTls(t *testing.T) {
|
||||||
masterArgs := nfdmaster.Args{
|
masterArgs := &nfdmaster.Args{
|
||||||
CaFile: data.FilePath("ca.crt"),
|
CaFile: data.FilePath("ca.crt"),
|
||||||
CertFile: data.FilePath("nfd-test-master.crt"),
|
CertFile: data.FilePath("nfd-test-master.crt"),
|
||||||
KeyFile: data.FilePath("nfd-test-master.key"),
|
KeyFile: data.FilePath("nfd-test-master.key"),
|
||||||
|
|
62
pkg/utils/flags.go
Normal file
62
pkg/utils/flags.go
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegexpVal is a wrapper for regexp command line flags
|
||||||
|
type RegexpVal struct {
|
||||||
|
regexp.Regexp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set implements the flag.Value interface
|
||||||
|
func (a *RegexpVal) Set(val string) error {
|
||||||
|
r, err := regexp.Compile(val)
|
||||||
|
a.Regexp = *r
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSetVal is a Value encapsulating a set of comma-separated strings
|
||||||
|
type StringSetVal map[string]struct{}
|
||||||
|
|
||||||
|
// Set implements the flag.Value interface
|
||||||
|
func (a *StringSetVal) Set(val string) error {
|
||||||
|
m := map[string]struct{}{}
|
||||||
|
for _, n := range strings.Split(val, ",") {
|
||||||
|
m[n] = struct{}{}
|
||||||
|
}
|
||||||
|
*a = m
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements the flag.Value interface
|
||||||
|
func (a *StringSetVal) String() string {
|
||||||
|
if *a == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
vals := make([]string, len(*a), 0)
|
||||||
|
for val := range *a {
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
sort.Strings(vals)
|
||||||
|
return strings.Join(vals, ",")
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue