Update go dependencies

This commit is contained in:
Manuel Alejandro de Brito Fontes 2020-01-26 10:24:11 -03:00
parent 2f8cbeb8fa
commit 23e7565ebc
396 changed files with 57233 additions and 47523 deletions

View file

@ -20,17 +20,16 @@ import (
"flag"
"fmt"
"os"
"os/user"
"path/filepath"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
logf "sigs.k8s.io/controller-runtime/pkg/internal/log"
)
var (
kubeconfig, masterURL string
log = logf.KBLog.WithName("client").WithName("config")
kubeconfig, apiServerURL string
log = logf.RuntimeLog.WithName("client").WithName("config")
)
func init() {
@ -38,15 +37,19 @@ func init() {
flag.StringVar(&kubeconfig, "kubeconfig", "",
"Paths to a kubeconfig. Only required if out-of-cluster.")
flag.StringVar(&masterURL, "master", "",
"The address of the Kubernetes API server. Overrides any value in kubeconfig. "+
// This flag is deprecated, it'll be removed in a future iteration, please switch to --kubeconfig.
flag.StringVar(&apiServerURL, "master", "",
"(Deprecated: switch to `--kubeconfig`) The address of the Kubernetes API server. Overrides any value in kubeconfig. "+
"Only required if out-of-cluster.")
}
// GetConfig creates a *rest.Config for talking to a Kubernetes apiserver.
// GetConfig creates a *rest.Config for talking to a Kubernetes API server.
// If --kubeconfig is set, will use the kubeconfig file at that location. Otherwise will assume running
// in cluster and use the cluster provided kubeconfig.
//
// It also applies saner defaults for QPS and burst based on the Kubernetes
// controller manager defaults (20 QPS, 30 burst)
//
// Config precedence
//
// * --kubeconfig flag pointing at a file
@ -57,29 +60,81 @@ func init() {
//
// * $HOME/.kube/config if exists
func GetConfig() (*rest.Config, error) {
return GetConfigWithContext("")
}
// GetConfigWithContext creates a *rest.Config for talking to a Kubernetes API server with a specific context.
// If --kubeconfig is set, will use the kubeconfig file at that location. Otherwise will assume running
// in cluster and use the cluster provided kubeconfig.
//
// It also applies saner defaults for QPS and burst based on the Kubernetes
// controller manager defaults (20 QPS, 30 burst)
//
// Config precedence
//
// * --kubeconfig flag pointing at a file
//
// * KUBECONFIG environment variable pointing at a file
//
// * In-cluster config if running in cluster
//
// * $HOME/.kube/config if exists
func GetConfigWithContext(context string) (*rest.Config, error) {
cfg, err := loadConfig(context)
if err != nil {
return nil, err
}
if cfg.QPS == 0.0 {
cfg.QPS = 20.0
cfg.Burst = 30.0
}
return cfg, nil
}
// loadInClusterConfig is a function used to load the in-cluster
// Kubernetes client config. This variable makes is possible to
// test the precedence of loading the config.
var loadInClusterConfig = rest.InClusterConfig
// loadConfig loads a REST Config as per the rules specified in GetConfig
func loadConfig(context string) (*rest.Config, error) {
// If a flag is specified with the config location, use that
if len(kubeconfig) > 0 {
return clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
return loadConfigWithContext(apiServerURL, &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}, context)
}
// If an env variable is specified with the config locaiton, use that
if len(os.Getenv("KUBECONFIG")) > 0 {
return clientcmd.BuildConfigFromFlags(masterURL, os.Getenv("KUBECONFIG"))
}
// If no explicit location, try the in-cluster config
if c, err := rest.InClusterConfig(); err == nil {
return c, nil
}
// If no in-cluster config, try the default location in the user's home directory
if usr, err := user.Current(); err == nil {
if c, err := clientcmd.BuildConfigFromFlags(
"", filepath.Join(usr.HomeDir, ".kube", "config")); err == nil {
// If the recommended kubeconfig env variable is not specified,
// try the in-cluster config.
kubeconfigPath := os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
if len(kubeconfigPath) == 0 {
if c, err := loadInClusterConfig(); err == nil {
return c, nil
}
}
// If the recommended kubeconfig env variable is set, or there
// is no in-cluster config, try the default recommended locations.
if c, err := loadConfigWithContext(apiServerURL, clientcmd.NewDefaultClientConfigLoadingRules(), context); err == nil {
return c, nil
}
return nil, fmt.Errorf("could not locate a kubeconfig")
}
func loadConfigWithContext(apiServerURL string, loader clientcmd.ClientConfigLoader, context string) (*rest.Config, error) {
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
loader,
&clientcmd.ConfigOverrides{
ClusterInfo: clientcmdapi.Cluster{
Server: apiServerURL,
},
CurrentContext: context,
}).ClientConfig()
}
// GetConfigOrDie creates a *rest.Config for talking to a Kubernetes apiserver.
// If --kubeconfig is set, will use the kubeconfig file at that location. Otherwise will assume running
// in cluster and use the cluster provided kubeconfig.

View file

@ -14,5 +14,5 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package config contains libraries for initializing rest configs for talking to the Kubernetes API
// Package config contains libraries for initializing REST configs for talking to the Kubernetes API
package config

View file

@ -17,23 +17,27 @@ limitations under the License.
package envtest
import (
"bufio"
"bytes"
"io"
"io/ioutil"
"os"
"path/filepath"
"time"
"github.com/ghodss/yaml"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/rest"
"sigs.k8s.io/yaml"
)
// CRDInstallOptions are the options for installing CRDs
type CRDInstallOptions struct {
// Paths is the path to the directory containing CRDs
// Paths is a list of paths to the directories containing CRDs
Paths []string
// CRDs is a list of CRDs to install
@ -42,11 +46,11 @@ type CRDInstallOptions struct {
// ErrorIfPathMissing will cause an error if a Path does not exist
ErrorIfPathMissing bool
// maxTime is the max time to wait
maxTime time.Duration
// MaxTime is the max time to wait
MaxTime time.Duration
// pollInterval is the interval to check
pollInterval time.Duration
// PollInterval is the interval to check
PollInterval time.Duration
}
const defaultPollInterval = 100 * time.Millisecond
@ -93,11 +97,11 @@ func readCRDFiles(options *CRDInstallOptions) error {
// defaultCRDOptions sets the default values for CRDs
func defaultCRDOptions(o *CRDInstallOptions) {
if o.maxTime == 0 {
o.maxTime = defaultMaxWait
if o.MaxTime == 0 {
o.MaxTime = defaultMaxWait
}
if o.pollInterval == 0 {
o.pollInterval = defaultPollInterval
if o.PollInterval == 0 {
o.PollInterval = defaultPollInterval
}
}
@ -106,18 +110,29 @@ func WaitForCRDs(config *rest.Config, crds []*apiextensionsv1beta1.CustomResourc
// Add each CRD to a map of GroupVersion to Resource
waitingFor := map[schema.GroupVersion]*sets.String{}
for _, crd := range crds {
gv := schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}
if _, found := waitingFor[gv]; !found {
// Initialize the set
waitingFor[gv] = &sets.String{}
gvs := []schema.GroupVersion{}
if crd.Spec.Version != "" {
gvs = append(gvs, schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version})
}
for _, ver := range crd.Spec.Versions {
if ver.Served {
gvs = append(gvs, schema.GroupVersion{Group: crd.Spec.Group, Version: ver.Name})
}
}
for _, gv := range gvs {
log.V(1).Info("adding API in waitlist", "GV", gv)
if _, found := waitingFor[gv]; !found {
// Initialize the set
waitingFor[gv] = &sets.String{}
}
// Add the Resource
waitingFor[gv].Insert(crd.Spec.Names.Plural)
}
// Add the Resource
waitingFor[gv].Insert(crd.Spec.Names.Plural)
}
// Poll until all resources are found in discovery
p := &poller{config: config, waitingFor: waitingFor}
return wait.PollImmediate(options.pollInterval, options.maxTime, p.poll)
return wait.PollImmediate(options.PollInterval, options.MaxTime, p.poll)
}
// poller checks if all the resources have been found in discovery, and returns false if not
@ -174,7 +189,7 @@ func CreateCRDs(config *rest.Config, crds []*apiextensionsv1beta1.CustomResource
// Create each CRD
for _, crd := range crds {
log.V(1).Info("installing CRD", "crd", crd)
log.V(1).Info("installing CRD", "crd", crd.Name)
if _, err := cs.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd); err != nil {
return err
}
@ -202,23 +217,52 @@ func readCRDs(path string) ([]*apiextensionsv1beta1.CustomResourceDefinition, er
continue
}
// Unmarshal the file into a struct
b, err := ioutil.ReadFile(filepath.Join(path, file.Name()))
// Unmarshal CRDs from file into structs
docs, err := readDocuments(filepath.Join(path, file.Name()))
if err != nil {
return nil, err
}
crd := &apiextensionsv1beta1.CustomResourceDefinition{}
if err = yaml.Unmarshal(b, crd); err != nil {
return nil, err
for _, doc := range docs {
crd := &apiextensionsv1beta1.CustomResourceDefinition{}
if err = yaml.Unmarshal(doc, crd); err != nil {
return nil, err
}
// Check that it is actually a CRD
if crd.Spec.Names.Kind == "" || crd.Spec.Group == "" {
continue
}
crds = append(crds, crd)
}
// Check that it is actually a CRD
if crd.Spec.Names.Kind == "" || crd.Spec.Group == "" {
continue
}
log.V(1).Info("read CRD from file", "file", file)
crds = append(crds, crd)
log.V(1).Info("read CRDs from file", "file", file.Name())
}
return crds, nil
}
// readDocuments reads documents from file
func readDocuments(fp string) ([][]byte, error) {
b, err := ioutil.ReadFile(fp)
if err != nil {
return nil, err
}
docs := [][]byte{}
reader := k8syaml.NewYAMLReader(bufio.NewReader(bytes.NewReader(b)))
for {
// Read document
doc, err := reader.Read()
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
docs = append(docs, doc)
}
return docs, nil
}

View file

@ -15,4 +15,12 @@ limitations under the License.
*/
// Package envtest provides libraries for integration testing by starting a local control plane
//
// Control plane binaries (etcd and kube-apiserver) are loaded by default from
// /usr/local/kubebuilder/bin. This can be overridden by setting the
// KUBEBUILDER_ASSETS environment variable, or by directly creating a
// ControlPlane for the Environment to use.
//
// Environment can also be configured to work with an existing cluster, and
// simply load CRDs and provide client configuration.
package envtest

View file

@ -1,11 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: foos.bar.example.com
spec:
group: bar.example.com
names:
kind: Foo
plural: foos
scope: Namespaced
version: "v1beta1"

View file

@ -1,11 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: bazs.qux.example.com
spec:
group: qux.example.com
names:
kind: Baz
plural: bazs
scope: Namespaced
version: "v1beta1"

View file

@ -0,0 +1,41 @@
package envtest
import apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
// mergePaths merges two string slices containing paths.
// This function makes no guarantees about order of the merged slice.
func mergePaths(s1, s2 []string) []string {
m := make(map[string]struct{})
for _, s := range s1 {
m[s] = struct{}{}
}
for _, s := range s2 {
m[s] = struct{}{}
}
merged := make([]string, len(m))
i := 0
for key := range m {
merged[i] = key
i++
}
return merged
}
// mergeCRDs merges two CRD slices using their names.
// This function makes no guarantees about order of the merged slice.
func mergeCRDs(s1, s2 []*apiextensionsv1beta1.CustomResourceDefinition) []*apiextensionsv1beta1.CustomResourceDefinition {
m := make(map[string]*apiextensionsv1beta1.CustomResourceDefinition)
for _, crd := range s1 {
m[crd.Name] = crd
}
for _, crd := range s2 {
m[crd.Name] = crd
}
merged := make([]*apiextensionsv1beta1.CustomResourceDefinition, len(m))
i := 0
for _, crd := range m {
merged[i] = crd
i++
}
return merged
}

View file

@ -1,18 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package printer contains setup for a friendlier Ginkgo printer that's easier
// to parse by test automation.
package printer
import (

View file

@ -20,6 +20,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
@ -27,19 +28,32 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/testing_frameworks/integration"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
logf "sigs.k8s.io/controller-runtime/pkg/internal/log"
)
var log = logf.KBLog.WithName("test-env")
var log = logf.RuntimeLog.WithName("test-env")
// Default binary path for test framework
/*
It's possible to override some defaults, by setting the following environment variables:
USE_EXISTING_CLUSTER (boolean): if set to true, envtest will use an existing cluster
TEST_ASSET_KUBE_APISERVER (string): path to the api-server binary to use
TEST_ASSET_ETCD (string): path to the etcd binary to use
TEST_ASSET_KUBECTL (string): path to the kubectl binary to use
KUBEBUILDER_ASSETS (string): directory containing the binaries to use (api-server, etcd and kubectl). Defaults to /usr/local/kubebuilder/bin.
KUBEBUILDER_CONTROLPLANE_START_TIMEOUT (string supported by time.ParseDuration): timeout for test control plane to start. Defaults to 20s.
KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT (string supported by time.ParseDuration): timeout for test control plane to start. Defaults to 20s.
KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT (boolean): if set to true, the control plane's stdout and stderr are attached to os.Stdout and os.Stderr
*/
const (
envUseExistingCluster = "USE_EXISTING_CLUSTER"
envKubeAPIServerBin = "TEST_ASSET_KUBE_APISERVER"
envEtcdBin = "TEST_ASSET_ETCD"
envKubectlBin = "TEST_ASSET_KUBECTL"
envKubebuilderPath = "KUBEBUILDER_ASSETS"
envStartTimeout = "KUBEBUILDER_CONTROLPLANE_START_TIMEOUT"
envStopTimeout = "KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT"
envAttachOutput = "KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT"
defaultKubebuilderPath = "/usr/local/kubebuilder/bin"
StartTimeout = 60
StopTimeout = 60
@ -48,6 +62,7 @@ const (
defaultKubebuilderControlPlaneStopTimeout = 20 * time.Second
)
// Default binary path for test framework
func defaultAssetPath(binary string) string {
assetPath := os.Getenv(envKubebuilderPath)
if assetPath == "" {
@ -59,12 +74,16 @@ func defaultAssetPath(binary string) string {
// DefaultKubeAPIServerFlags are default flags necessary to bring up apiserver.
var DefaultKubeAPIServerFlags = []string{
// Allow tests to run offline, by preventing API server from attempting to
// use default route to determine its --advertise-address
"--advertise-address=127.0.0.1",
"--etcd-servers={{ if .EtcdURL }}{{ .EtcdURL.String }}{{ end }}",
"--cert-dir={{ .CertDir }}",
"--insecure-port={{ if .URL }}{{ .URL.Port }}{{ end }}",
"--insecure-bind-address={{ if .URL }}{{ .URL.Hostname }}{{ end }}",
"--secure-port={{ if .SecurePort }}{{ .SecurePort }}{{ end }}",
"--admission-control=AlwaysAdmit",
"--service-cluster-ip-range=10.0.0.0/24",
}
// Environment creates a Kubernetes test environment that will start / stop the Kubernetes control plane and
@ -73,19 +92,28 @@ type Environment struct {
// ControlPlane is the ControlPlane including the apiserver and etcd
ControlPlane integration.ControlPlane
// Config can be used to talk to the apiserver
// Config can be used to talk to the apiserver. It's automatically
// populated if not set using the standard controller-runtime config
// loading.
Config *rest.Config
// CRDs is a list of CRDs to install
// CRDInstallOptions are the options for installing CRDs.
CRDInstallOptions CRDInstallOptions
// CRDs is a list of CRDs to install.
// If both this field and CRDs field in CRDInstallOptions are specified, the
// values are merged.
CRDs []*apiextensionsv1beta1.CustomResourceDefinition
// CRDDirectoryPaths is a list of paths containing CRD yaml or json configs.
// If both this field and Paths field in CRDInstallOptions are specified, the
// values are merged.
CRDDirectoryPaths []string
// UseExisting indicates that this environments should use an
// existing kubeconfig, instead of trying to stand up a new control plane.
// This is useful in cases that need aggregated API servers and the like.
UseExistingCluster bool
UseExistingCluster *bool
// ControlPlaneStartTimeout is the maximum duration each controlplane component
// may take to start. It defaults to the KUBEBUILDER_CONTROLPLANE_START_TIMEOUT
@ -99,11 +127,17 @@ type Environment struct {
// KubeAPIServerFlags is the set of flags passed while starting the api server.
KubeAPIServerFlags []string
// AttachControlPlaneOutput indicates if control plane output will be attached to os.Stdout and os.Stderr.
// Enable this to get more visibility of the testing control plane.
// It respect KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT environment variable.
AttachControlPlaneOutput bool
}
// Stop stops a running server
// Stop stops a running server.
// If USE_EXISTING_CLUSTER is set to true, this method is a no-op.
func (te *Environment) Stop() error {
if te.UseExistingCluster {
if te.useExistingCluster() {
return nil
}
return te.ControlPlane.Stop()
@ -115,12 +149,23 @@ func (te Environment) getAPIServerFlags() []string {
if len(te.KubeAPIServerFlags) == 0 {
return DefaultKubeAPIServerFlags
}
// Check KubeAPIServerFlags contains service-cluster-ip-range, if not, set default value to service-cluster-ip-range
containServiceClusterIPRange := false
for _, flag := range te.KubeAPIServerFlags {
if strings.Contains(flag, "service-cluster-ip-range") {
containServiceClusterIPRange = true
break
}
}
if !containServiceClusterIPRange {
te.KubeAPIServerFlags = append(te.KubeAPIServerFlags, "--service-cluster-ip-range=10.0.0.0/24")
}
return te.KubeAPIServerFlags
}
// Start starts a local Kubernetes server and updates te.ApiserverPort with the port it is listening on
func (te *Environment) Start() (*rest.Config, error) {
if te.UseExistingCluster {
if te.useExistingCluster() {
log.V(1).Info("using existing cluster")
if te.Config == nil {
// we want to allow people to pass in their own config, so
@ -134,9 +179,28 @@ func (te *Environment) Start() (*rest.Config, error) {
}
}
} else {
te.ControlPlane = integration.ControlPlane{}
te.ControlPlane.APIServer = &integration.APIServer{Args: te.getAPIServerFlags()}
te.ControlPlane.Etcd = &integration.Etcd{}
if te.ControlPlane.APIServer == nil {
te.ControlPlane.APIServer = &integration.APIServer{Args: te.getAPIServerFlags()}
}
if te.ControlPlane.Etcd == nil {
te.ControlPlane.Etcd = &integration.Etcd{}
}
if os.Getenv(envAttachOutput) == "true" {
te.AttachControlPlaneOutput = true
}
if te.ControlPlane.APIServer.Out == nil && te.AttachControlPlaneOutput {
te.ControlPlane.APIServer.Out = os.Stdout
}
if te.ControlPlane.APIServer.Err == nil && te.AttachControlPlaneOutput {
te.ControlPlane.APIServer.Err = os.Stderr
}
if te.ControlPlane.Etcd.Out == nil && te.AttachControlPlaneOutput {
te.ControlPlane.Etcd.Out = os.Stdout
}
if te.ControlPlane.Etcd.Err == nil && te.AttachControlPlaneOutput {
te.ControlPlane.Etcd.Err = os.Stderr
}
if os.Getenv(envKubeAPIServerBin) == "" {
te.ControlPlane.APIServer.Path = defaultAssetPath("kube-apiserver")
@ -167,14 +231,16 @@ func (te *Environment) Start() (*rest.Config, error) {
// Create the *rest.Config for creating new clients
te.Config = &rest.Config{
Host: te.ControlPlane.APIURL().Host,
// gotta go fast during tests -- we don't really care about overwhelming our test API server
QPS: 1000.0,
Burst: 2000.0,
}
}
log.V(1).Info("installing CRDs")
_, err := InstallCRDs(te.Config, CRDInstallOptions{
Paths: te.CRDDirectoryPaths,
CRDs: te.CRDs,
})
te.CRDInstallOptions.CRDs = mergeCRDs(te.CRDInstallOptions.CRDs, te.CRDs)
te.CRDInstallOptions.Paths = mergePaths(te.CRDInstallOptions.Paths, te.CRDDirectoryPaths)
_, err := InstallCRDs(te.Config, te.CRDInstallOptions)
return te.Config, err
}
@ -220,3 +286,10 @@ func (te *Environment) defaultTimeouts() error {
}
return nil
}
func (te *Environment) useExistingCluster() bool {
if te.UseExistingCluster == nil {
return strings.ToLower(os.Getenv(envUseExistingCluster)) == "true"
}
return *te.UseExistingCluster
}

View file

@ -0,0 +1,35 @@
/*
Copyright 2018 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 log contains utilities for fetching a new logger
// when one is not already available.
// Deprecated: use pkg/log
package log
import (
"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/log"
)
var (
// RuntimeLog is a base parent logger for use inside controller-runtime.
RuntimeLog logr.Logger
)
func init() {
RuntimeLog = log.Log.WithName("controller-runtime")
}

View file

@ -17,6 +17,8 @@ limitations under the License.
package log
import (
"sync"
"github.com/go-logr/logr"
)
@ -25,6 +27,7 @@ import (
type loggerPromise struct {
logger *DelegatingLogger
childPromises []*loggerPromise
promisesLock sync.Mutex
name *string
tags []interface{}
@ -33,9 +36,13 @@ type loggerPromise struct {
// WithName provides a new Logger with the name appended
func (p *loggerPromise) WithName(l *DelegatingLogger, name string) *loggerPromise {
res := &loggerPromise{
logger: l,
name: &name,
logger: l,
name: &name,
promisesLock: sync.Mutex{},
}
p.promisesLock.Lock()
defer p.promisesLock.Unlock()
p.childPromises = append(p.childPromises, res)
return res
}
@ -43,9 +50,13 @@ func (p *loggerPromise) WithName(l *DelegatingLogger, name string) *loggerPromis
// WithValues provides a new Logger with the tags appended
func (p *loggerPromise) WithValues(l *DelegatingLogger, tags ...interface{}) *loggerPromise {
res := &loggerPromise{
logger: l,
tags: tags,
logger: l,
tags: tags,
promisesLock: sync.Mutex{},
}
p.promisesLock.Lock()
defer p.promisesLock.Unlock()
p.childPromises = append(p.childPromises, res)
return res
}
@ -119,7 +130,7 @@ func (l *DelegatingLogger) Fulfill(actual logr.Logger) {
func NewDelegatingLogger(initial logr.Logger) *DelegatingLogger {
l := &DelegatingLogger{
Logger: initial,
promise: &loggerPromise{},
promise: &loggerPromise{promisesLock: sync.Mutex{}},
}
l.promise.logger = l
return l

48
vendor/sigs.k8s.io/controller-runtime/pkg/log/log.go generated vendored Normal file
View file

@ -0,0 +1,48 @@
/*
Copyright 2018 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 log contains utilities for fetching a new logger
// when one is not already available.
//
// The Log Handle
//
// This package contains a root logr.Logger Log. It may be used to
// get a handle to whatever the root logging implementation is. By
// default, no implementation exists, and the handle returns "promises"
// to loggers. When the implementation is set using SetLogger, these
// "promises" will be converted over to real loggers.
//
// Logr
//
// All logging in controller-runtime is structured, using a set of interfaces
// defined by a package called logr
// (https://godoc.org/github.com/go-logr/logr). The sub-package zap provides
// helpers for setting up logr backed by Zap (go.uber.org/zap).
package log
import (
"github.com/go-logr/logr"
)
// SetLogger sets a concrete logging implementation for all deferred Loggers.
func SetLogger(l logr.Logger) {
Log.Fulfill(l)
}
// Log is the base logger used by kubebuilder. It delegates
// to another logr.Logger. You *must* call SetLogger to
// get any actual logging.
var Log = NewDelegatingLogger(NullLogger{})

View file

@ -1,129 +0,0 @@
/*
Copyright 2018 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 log contains utilities for fetching a new logger
// when one is not already available.
package log
import (
"fmt"
"go.uber.org/zap/buffer"
"go.uber.org/zap/zapcore"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
)
// KubeAwareEncoder is a Kubernetes-aware Zap Encoder.
// Instead of trying to force Kubernetes objects to implement
// ObjectMarshaller, we just implement a wrapper around a normal
// ObjectMarshaller that checks for Kubernetes objects.
type KubeAwareEncoder struct {
// Encoder is the zapcore.Encoder that this encoder delegates to
zapcore.Encoder
// Verbose controls whether or not the full object is printed.
// If false, only name, namespace, api version, and kind are printed.
// Otherwise, the full object is logged.
Verbose bool
}
// namespacedNameWrapper is a zapcore.ObjectMarshaler for Kubernetes NamespacedName
type namespacedNameWrapper struct {
types.NamespacedName
}
func (w namespacedNameWrapper) MarshalLogObject(enc zapcore.ObjectEncoder) error {
if w.Namespace != "" {
enc.AddString("namespace", w.Namespace)
}
enc.AddString("name", w.Name)
return nil
}
// kubeObjectWrapper is a zapcore.ObjectMarshaler for Kubernetes objects.
type kubeObjectWrapper struct {
obj runtime.Object
}
// MarshalLogObject implements zapcore.ObjectMarshaler
func (w kubeObjectWrapper) MarshalLogObject(enc zapcore.ObjectEncoder) error {
// TODO(directxman12): log kind and apiversion if not set explicitly (common case)
// -- needs an a scheme to convert to the GVK.
gvk := w.obj.GetObjectKind().GroupVersionKind()
if gvk.Version != "" {
enc.AddString("apiVersion", gvk.GroupVersion().String())
enc.AddString("kind", gvk.Kind)
}
objMeta, err := meta.Accessor(w.obj)
if err != nil {
return fmt.Errorf("got runtime.Object without object metadata: %v", w.obj)
}
ns := objMeta.GetNamespace()
if ns != "" {
enc.AddString("namespace", ns)
}
enc.AddString("name", objMeta.GetName())
return nil
}
// NB(directxman12): can't just override AddReflected, since the encoder calls AddReflected on itself directly
// Clone implements zapcore.Encoder
func (k *KubeAwareEncoder) Clone() zapcore.Encoder {
return &KubeAwareEncoder{
Encoder: k.Encoder.Clone(),
}
}
// EncodeEntry implements zapcore.Encoder
func (k *KubeAwareEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
if k.Verbose {
// Kubernetes objects implement fmt.Stringer, so if we
// want verbose output, just delegate to that.
return k.Encoder.EncodeEntry(entry, fields)
}
for i, field := range fields {
// intercept stringer fields that happen to be Kubernetes runtime.Object or
// types.NamespacedName values (Kubernetes runtime.Objects commonly
// implement String, apparently).
if field.Type == zapcore.StringerType {
switch val := field.Interface.(type) {
case runtime.Object:
fields[i] = zapcore.Field{
Type: zapcore.ObjectMarshalerType,
Key: field.Key,
Interface: kubeObjectWrapper{obj: val},
}
case types.NamespacedName:
fields[i] = zapcore.Field{
Type: zapcore.ObjectMarshalerType,
Key: field.Key,
Interface: namespacedNameWrapper{NamespacedName: val},
}
}
}
}
return k.Encoder.EncodeEntry(entry, fields)
}

View file

@ -1,85 +0,0 @@
/*
Copyright 2018 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 log contains utilities for fetching a new logger
// when one is not already available.
package log
import (
"io"
"os"
"time"
"github.com/go-logr/logr"
"github.com/go-logr/zapr"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// ZapLogger is a Logger implementation.
// If development is true, a Zap development config will be used
// (stacktraces on warnings, no sampling), otherwise a Zap production
// config will be used (stacktraces on errors, sampling).
func ZapLogger(development bool) logr.Logger {
return ZapLoggerTo(os.Stderr, development)
}
// ZapLoggerTo returns a new Logger implementation using Zap which logs
// to the given destination, instead of stderr. It otherise behaves like
// ZapLogger.
func ZapLoggerTo(destWriter io.Writer, development bool) logr.Logger {
// this basically mimics New<type>Config, but with a custom sink
sink := zapcore.AddSync(destWriter)
var enc zapcore.Encoder
var lvl zap.AtomicLevel
var opts []zap.Option
if development {
encCfg := zap.NewDevelopmentEncoderConfig()
enc = zapcore.NewConsoleEncoder(encCfg)
lvl = zap.NewAtomicLevelAt(zap.DebugLevel)
opts = append(opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel))
} else {
encCfg := zap.NewProductionEncoderConfig()
enc = zapcore.NewJSONEncoder(encCfg)
lvl = zap.NewAtomicLevelAt(zap.InfoLevel)
opts = append(opts, zap.AddStacktrace(zap.WarnLevel),
zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return zapcore.NewSampler(core, time.Second, 100, 100)
}))
}
opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: enc, Verbose: development}, sink, lvl))
log = log.WithOptions(opts...)
return zapr.NewLogger(log)
}
// SetLogger sets a concrete logging implementation for all deferred Loggers.
func SetLogger(l logr.Logger) {
Log.Fulfill(l)
}
// Log is the base logger used by kubebuilder. It delegates
// to another logr.Logger. You *must* call SetLogger to
// get any actual logging.
var Log = NewDelegatingLogger(NullLogger{})
// KBLog is a base parent logger.
var KBLog logr.Logger
func init() {
KBLog = Log.WithName("kubebuilder")
}