Merge branch 'master' into upgrade_aliases_branch

This commit is contained in:
Jing Ai
2017-11-22 22:04:11 -08:00
192 changed files with 15355 additions and 1613 deletions

File diff suppressed because it is too large Load Diff

114
api/swagger-spec/events.k8s.io.json generated Normal file
View File

@@ -0,0 +1,114 @@
{
"swaggerVersion": "1.2",
"apiVersion": "",
"basePath": "https://10.10.10.10:6443",
"resourcePath": "/apis/events.k8s.io",
"info": {
"title": "",
"description": ""
},
"apis": [
{
"path": "/apis/events.k8s.io",
"description": "get information of a group",
"operations": [
{
"type": "v1.APIGroup",
"method": "GET",
"summary": "get information of a group",
"nickname": "getAPIGroup",
"parameters": [],
"produces": [
"application/json",
"application/yaml",
"application/vnd.kubernetes.protobuf"
],
"consumes": [
"application/json",
"application/yaml",
"application/vnd.kubernetes.protobuf"
]
}
]
}
],
"models": {
"v1.APIGroup": {
"id": "v1.APIGroup",
"description": "APIGroup contains the name, the supported versions, and the preferred version of a group.",
"required": [
"name",
"versions",
"serverAddressByClientCIDRs"
],
"properties": {
"kind": {
"type": "string",
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds"
},
"apiVersion": {
"type": "string",
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources"
},
"name": {
"type": "string",
"description": "name is the name of the group."
},
"versions": {
"type": "array",
"items": {
"$ref": "v1.GroupVersionForDiscovery"
},
"description": "versions are the versions supported in this group."
},
"preferredVersion": {
"$ref": "v1.GroupVersionForDiscovery",
"description": "preferredVersion is the version preferred by the API server, which probably is the storage version."
},
"serverAddressByClientCIDRs": {
"type": "array",
"items": {
"$ref": "v1.ServerAddressByClientCIDR"
},
"description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP."
}
}
},
"v1.GroupVersionForDiscovery": {
"id": "v1.GroupVersionForDiscovery",
"description": "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensibility.",
"required": [
"groupVersion",
"version"
],
"properties": {
"groupVersion": {
"type": "string",
"description": "groupVersion specifies the API group and version in the form \"group/version\""
},
"version": {
"type": "string",
"description": "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion."
}
}
},
"v1.ServerAddressByClientCIDR": {
"id": "v1.ServerAddressByClientCIDR",
"description": "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.",
"required": [
"clientCIDR",
"serverAddress"
],
"properties": {
"clientCIDR": {
"type": "string",
"description": "The CIDR with which clients can match their IP to figure out the server address that they should use."
},
"serverAddress": {
"type": "string",
"description": "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port."
}
}
}
}
}

1600
api/swagger-spec/events.k8s.io_v1beta1.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -180,6 +180,14 @@
{
"path": "/apis/admissionregistration.k8s.io",
"description": "get information of a group"
},
{
"path": "/apis/events.k8s.io/v1beta1",
"description": "API at /apis/events.k8s.io/v1beta1"
},
{
"path": "/apis/events.k8s.io",
"description": "get information of a group"
}
],
"apiVersion": "",

View File

@@ -19634,7 +19634,9 @@
"description": "Event is a report of an event somewhere in the cluster.",
"required": [
"metadata",
"involvedObject"
"involvedObject",
"reportingComponent",
"reportingInstance"
],
"properties": {
"kind": {
@@ -19681,6 +19683,30 @@
"type": {
"type": "string",
"description": "Type of this event (Normal, Warning), new types could be added in the future"
},
"eventTime": {
"type": "string",
"description": "Time when this Event was first observed."
},
"series": {
"$ref": "v1.EventSeries",
"description": "Data about the Event series this event represents or nil if it's a singleton Event."
},
"action": {
"type": "string",
"description": "What action was taken/failed regarding to the Regarding object."
},
"related": {
"$ref": "v1.ObjectReference",
"description": "Optional secondary object for more complex actions."
},
"reportingComponent": {
"type": "string",
"description": "Name of the controller that emitted this Event, e.g. `kubernetes.io/kubelet`."
},
"reportingInstance": {
"type": "string",
"description": "ID of the controller instance, e.g. `kubelet-xyzf`."
}
}
},
@@ -19698,6 +19724,25 @@
}
}
},
"v1.EventSeries": {
"id": "v1.EventSeries",
"description": "EventSeries contain information on series of events, i.e. thing that was/is happening continously for some time.",
"properties": {
"count": {
"type": "integer",
"format": "int32",
"description": "Number of occurrences in this series up to the last heartbeat time"
},
"lastObservedTime": {
"type": "string",
"description": "Time of the last occurence observed"
},
"state": {
"type": "string",
"description": "State of this Series: Ongoing or Finished"
}
}
},
"v1.LimitRangeList": {
"id": "v1.LimitRangeList",
"description": "LimitRangeList is a list of LimitRange items.",

View File

@@ -55,7 +55,7 @@ spec:
command:
- /heapster
- --source=kubernetes.summary_api:''
- --sink=stackdriver:?cluster_name={{ cluster_name }}&min_interval_sec=100&batch_export_timeout_sec=110
- --sink=stackdriver:?cluster_name={{ cluster_name }}&use_old_resources={{ use_old_resources }}&use_new_resources={{ use_new_resources }}&min_interval_sec=100&batch_export_timeout_sec=110
# BEGIN_PROMETHEUS_TO_SD
- name: prom-to-sd
image: gcr.io/google-containers/prometheus-to-sd:v0.2.2

View File

@@ -1279,6 +1279,7 @@ EOF
controller_yaml="${controller_yaml}/heapster-controller.yaml"
fi
remove-salt-config-comments "${controller_yaml}"
sed -i -e "s@{{ cluster_name }}@${CLUSTER_NAME}@g" "${controller_yaml}"
sed -i -e "s@{{ *base_metrics_memory *}}@${base_metrics_memory}@g" "${controller_yaml}"
sed -i -e "s@{{ *base_metrics_cpu *}}@${base_metrics_cpu}@g" "${controller_yaml}"
@@ -1288,6 +1289,13 @@ EOF
sed -i -e "s@{{ *nanny_memory *}}@${nanny_memory}@g" "${controller_yaml}"
sed -i -e "s@{{ *metrics_cpu_per_node *}}@${metrics_cpu_per_node}@g" "${controller_yaml}"
update-prometheus-to-sd-parameters ${controller_yaml}
if [[ "${ENABLE_CLUSTER_MONITORING:-}" == "stackdriver" ]]; then
use_old_resources="${HEAPSTER_USE_OLD_STACKDRIVER_RESOURCES:-true}"
use_new_resources="${HEAPSTER_USE_NEW_STACKDRIVER_RESOURCES:-false}"
sed -i -e "s@{{ use_old_resources }}@${use_old_resources}@g" "${controller_yaml}"
sed -i -e "s@{{ use_new_resources }}@${use_new_resources}@g" "${controller_yaml}"
fi
fi
if [[ "${ENABLE_METRICS_SERVER:-}" == "true" ]]; then
setup-addon-manifests "addons" "metrics-server"

View File

@@ -2058,6 +2058,7 @@ EOF
controller_yaml="${controller_yaml}/heapster-controller.yaml"
fi
remove-salt-config-comments "${controller_yaml}"
sed -i -e "s@{{ cluster_name }}@${CLUSTER_NAME}@g" "${controller_yaml}"
sed -i -e "s@{{ *base_metrics_memory *}}@${base_metrics_memory}@g" "${controller_yaml}"
sed -i -e "s@{{ *base_metrics_cpu *}}@${base_metrics_cpu}@g" "${controller_yaml}"
@@ -2067,6 +2068,13 @@ EOF
sed -i -e "s@{{ *nanny_memory *}}@${nanny_memory}@g" "${controller_yaml}"
sed -i -e "s@{{ *metrics_cpu_per_node *}}@${metrics_cpu_per_node}@g" "${controller_yaml}"
update-prometheus-to-sd-parameters ${controller_yaml}
if [[ "${ENABLE_CLUSTER_MONITORING:-}" == "stackdriver" ]]; then
use_old_resources="${HEAPSTER_USE_OLD_STACKDRIVER_RESOURCES:-true}"
use_new_resources="${HEAPSTER_USE_NEW_STACKDRIVER_RESOURCES:-false}"
sed -i -e "s@{{ use_old_resources }}@${use_old_resources}@g" "${controller_yaml}"
sed -i -e "s@{{ use_new_resources }}@${use_new_resources}@g" "${controller_yaml}"
fi
fi
if [[ "${ENABLE_METRICS_SERVER:-}" == "true" ]]; then
setup-addon-manifests "addons" "metrics-server"

View File

@@ -20,6 +20,7 @@ go_library(
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/events:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/networking:go_default_library",
"//pkg/apis/storage:go_default_library",

View File

@@ -205,6 +205,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{
{Group: "apps", Version: "v1beta1"}: {group: 17800, version: 1},
{Group: "apps", Version: "v1beta2"}: {group: 17800, version: 9},
{Group: "apps", Version: "v1"}: {group: 17800, version: 15},
{Group: "events.k8s.io", Version: "v1beta1"}: {group: 17750, version: 5},
{Group: "authentication.k8s.io", Version: "v1"}: {group: 17700, version: 15},
{Group: "authentication.k8s.io", Version: "v1beta1"}: {group: 17700, version: 9},
{Group: "authorization.k8s.io", Version: "v1"}: {group: 17600, version: 15},

View File

@@ -66,6 +66,7 @@ import (
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/events"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/apis/storage"
@@ -579,6 +580,7 @@ func BuildStorageFactory(s *options.ServerRunOptions) (*serverstorage.DefaultSto
storageFactory.AddCohabitatingResources(extensions.Resource("deployments"), apps.Resource("deployments"))
storageFactory.AddCohabitatingResources(extensions.Resource("daemonsets"), apps.Resource("daemonsets"))
storageFactory.AddCohabitatingResources(extensions.Resource("replicasets"), apps.Resource("replicasets"))
storageFactory.AddCohabitatingResources(api.Resource("events"), events.Resource("events"))
for _, override := range s.Etcd.EtcdServersOverrides {
tokens := strings.Split(override, "#")
if len(tokens) != 2 {

View File

@@ -34,6 +34,7 @@ go_library(
"//pkg/apis/certificates/install:go_default_library",
"//pkg/apis/componentconfig:go_default_library",
"//pkg/apis/core/install:go_default_library",
"//pkg/apis/events/install:go_default_library",
"//pkg/apis/extensions/install:go_default_library",
"//pkg/apis/policy/install:go_default_library",
"//pkg/apis/rbac/install:go_default_library",

View File

@@ -30,6 +30,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
_ "k8s.io/kubernetes/pkg/apis/core/install"
_ "k8s.io/kubernetes/pkg/apis/events/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/policy/install"
_ "k8s.io/kubernetes/pkg/apis/rbac/install"

View File

@@ -17,6 +17,8 @@ limitations under the License.
package phases
import (
"strings"
"github.com/spf13/cobra"
clientset "k8s.io/client-go/kubernetes"
@@ -24,6 +26,7 @@ import (
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
@@ -93,7 +96,7 @@ func getAddonsSubCommands() []*cobra.Command {
// Default values for the cobra help text
legacyscheme.Scheme.Default(cfg)
var cfgPath, kubeConfigFile string
var cfgPath, kubeConfigFile, featureGatesString string
var subCmds []*cobra.Command
subCmdProperties := []struct {
@@ -131,7 +134,7 @@ func getAddonsSubCommands() []*cobra.Command {
Short: properties.short,
Long: properties.long,
Example: properties.examples,
Run: runAddonsCmdFunc(properties.cmdFunc, cfg, &kubeConfigFile, &cfgPath),
Run: runAddonsCmdFunc(properties.cmdFunc, cfg, &kubeConfigFile, &cfgPath, &featureGatesString),
}
// Add flags to the command
@@ -149,6 +152,8 @@ func getAddonsSubCommands() []*cobra.Command {
if properties.use == "all" || properties.use == "kube-dns" {
cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, `Alternative domain for services`)
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, `The range of IP address used for service VIPs`)
cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features."+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
}
subCmds = append(subCmds, cmd)
}
@@ -157,7 +162,7 @@ func getAddonsSubCommands() []*cobra.Command {
}
// runAddonsCmdFunc creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error, cfg *kubeadmapiext.MasterConfiguration, kubeConfigFile *string, cfgPath *string) func(cmd *cobra.Command, args []string) {
func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error, cfg *kubeadmapiext.MasterConfiguration, kubeConfigFile *string, cfgPath *string, featureGatesString *string) func(cmd *cobra.Command, args []string) {
// the following statement build a clousure that wraps a call to a cmdFunc, binding
// the function itself with the specific parameters of each sub command.
@@ -165,16 +170,24 @@ func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client c
// are shared between sub commands and gets access to current value e.g. flags value.
return func(cmd *cobra.Command, args []string) {
var err error
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
kubeadmutil.CheckErr(err)
}
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, *featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
}
internalcfg := &kubeadmapi.MasterConfiguration{}
legacyscheme.Scheme.Convert(cfg, internalcfg, nil)
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
internalcfg, err = configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
kubeadmutil.CheckErr(err)
if err := features.ValidateVersion(features.InitFeatureGates, internalcfg.FeatureGates, internalcfg.KubernetesVersion); err != nil {
kubeadmutil.CheckErr(err)
}
// Execute the cmdFunc
err = cmdFunc(internalcfg, client)

View File

@@ -16,6 +16,7 @@ go_library(
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/cmd/util:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/phases/controlplane:go_default_library",
"//cmd/kubeadm/app/phases/upgrade:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",

View File

@@ -119,7 +119,7 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command {
func RunApply(flags *applyFlags) error {
// Start with the basics, verify that the cluster is healthy and get the configuration from the cluster (using the ConfigMap)
upgradeVars, err := enforceRequirements(flags.parent.kubeConfigPath, flags.parent.cfgPath, flags.parent.printConfig, flags.dryRun)
upgradeVars, err := enforceRequirements(flags.parent.featureGatesString, flags.parent.kubeConfigPath, flags.parent.cfgPath, flags.parent.printConfig, flags.dryRun)
if err != nil {
return err
}

View File

@@ -30,6 +30,7 @@ import (
fakediscovery "k8s.io/client-go/discovery/fake"
clientset "k8s.io/client-go/kubernetes"
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
@@ -47,7 +48,7 @@ type upgradeVariables struct {
}
// enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure
func enforceRequirements(kubeConfigPath, cfgPath string, printConfig, dryRun bool) (*upgradeVariables, error) {
func enforceRequirements(featureGatesString, kubeConfigPath, cfgPath string, printConfig, dryRun bool) (*upgradeVariables, error) {
client, err := getClient(kubeConfigPath, dryRun)
if err != nil {
return nil, fmt.Errorf("couldn't create a Kubernetes client from file %q: %v", kubeConfigPath, err)
@@ -69,6 +70,14 @@ func enforceRequirements(kubeConfigPath, cfgPath string, printConfig, dryRun boo
printConfiguration(cfg, os.Stdout)
}
cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
if err != nil {
return nil, fmt.Errorf("[upgrade/config] FATAL: %v", err)
}
if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil {
return nil, err
}
return &upgradeVariables{
client: client,
cfg: cfg,

View File

@@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
)
@@ -53,29 +54,29 @@ func NewCmdPlan(parentFlags *cmdUpgradeFlags) *cobra.Command {
// RunPlan takes care of outputting available versions to upgrade to for the user
func RunPlan(parentFlags *cmdUpgradeFlags) error {
// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never set dry-run for plan.
upgradeVars, err := enforceRequirements(parentFlags.kubeConfigPath, parentFlags.cfgPath, parentFlags.printConfig, false)
upgradeVars, err := enforceRequirements(parentFlags.featureGatesString, parentFlags.kubeConfigPath, parentFlags.cfgPath, parentFlags.printConfig, false)
if err != nil {
return err
}
// Define Local Etcd cluster to be able to retrieve information
etcdCluster := kubeadmutil.LocalEtcdCluster{}
// Compute which upgrade possibilities there are
availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, parentFlags.allowExperimentalUpgrades, parentFlags.allowRCUpgrades, etcdCluster)
availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, parentFlags.allowExperimentalUpgrades, parentFlags.allowRCUpgrades, etcdCluster, upgradeVars.cfg.FeatureGates)
if err != nil {
return fmt.Errorf("[upgrade/versions] FATAL: %v", err)
}
// Tell the user which upgrades are available
printAvailableUpgrades(availUpgrades, os.Stdout)
printAvailableUpgrades(availUpgrades, os.Stdout, upgradeVars.cfg.FeatureGates)
return nil
}
// printAvailableUpgrades prints a UX-friendly overview of what versions are available to upgrade to
// TODO look into columnize or some other formatter when time permits instead of using the tabwriter
func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer) {
func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGates map[string]bool) {
// Return quickly if no upgrades can be made
if len(upgrades) == 0 {
@@ -117,7 +118,11 @@ func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer) {
fmt.Fprintf(tabw, "Controller Manager\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion)
if features.Enabled(featureGates, features.CoreDNS) {
fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion)
} else {
fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion)
}
fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion)
// The tabwriter should be flushed at this stage as we have now put in all the required content for this time. This is required for the tabs' size to be correct.

View File

@@ -60,6 +60,7 @@ func TestSortedSliceFromStringIntMap(t *testing.T) {
// TODO Think about modifying this test to be less verbose checking b/c it can be brittle.
func TestPrintAvailableUpgrades(t *testing.T) {
featureGates := make(map[string]bool)
var tests = []struct {
upgrades []upgrade.Upgrade
buf *bytes.Buffer
@@ -334,7 +335,7 @@ _____________________________________________________________________
}
for _, rt := range tests {
rt.buf = bytes.NewBufferString("")
printAvailableUpgrades(rt.upgrades, rt.buf)
printAvailableUpgrades(rt.upgrades, rt.buf, featureGates)
actualBytes := rt.buf.Bytes()
if !bytes.Equal(actualBytes, rt.expectedBytes) {
t.Errorf(

View File

@@ -18,16 +18,19 @@ package upgrade
import (
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/sets"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
)
// cmdUpgradeFlags holds the values for the common flags in `kubeadm upgrade`
type cmdUpgradeFlags struct {
kubeConfigPath string
cfgPath string
featureGatesString string
allowExperimentalUpgrades bool
allowRCUpgrades bool
printConfig bool
@@ -41,6 +44,7 @@ func NewCmdUpgrade(out io.Writer) *cobra.Command {
flags := &cmdUpgradeFlags{
kubeConfigPath: "/etc/kubernetes/admin.conf",
cfgPath: "",
featureGatesString: "",
allowExperimentalUpgrades: false,
allowRCUpgrades: false,
printConfig: false,
@@ -62,6 +66,8 @@ func NewCmdUpgrade(out io.Writer) *cobra.Command {
cmd.PersistentFlags().StringSliceVar(&flags.ignoreChecksErrors, "ignore-checks-errors", flags.ignoreChecksErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.")
cmd.PersistentFlags().BoolVar(&flags.skipPreFlight, "skip-preflight-checks", flags.skipPreFlight, "Skip preflight checks that normally run before modifying the system.")
cmd.PersistentFlags().MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-checks-errors=all")
cmd.PersistentFlags().StringVar(&flags.featureGatesString, "feature-gates", flags.featureGatesString, "A set of key=value pairs that describe feature gates for various features."+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
cmd.AddCommand(NewCmdApply(flags))
cmd.AddCommand(NewCmdPlan(flags))

View File

@@ -196,7 +196,7 @@ const (
DefaultCIImageRepository = "gcr.io/kubernetes-ci-images"
// CoreDNS defines a variable used internally when referring to the CoreDNS addon for a cluster
CoreDNS = "CoreDNS"
CoreDNS = "coredns"
// KubeDNS defines a variable used internally when referring to the kube-dns addon for a cluster
KubeDNS = "kube-dns"
)

View File

@@ -21,6 +21,7 @@ go_library(
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/phases/addons/dns:go_default_library",
"//cmd/kubeadm/app/phases/addons/proxy:go_default_library",

View File

@@ -21,6 +21,7 @@ import (
"strings"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
"k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/pkg/util/version"
@@ -49,6 +50,14 @@ func (u *Upgrade) CanUpgradeKubelets() bool {
return !sameVersionFound
}
// ActiveDNSAddon returns the version of CoreDNS or kube-dns
func ActiveDNSAddon(featureGates map[string]bool) string {
if features.Enabled(featureGates, features.CoreDNS) {
return kubeadmconstants.CoreDNS
}
return kubeadmconstants.KubeDNS
}
// ClusterState describes the state of certain versions for a cluster
type ClusterState struct {
// KubeVersion describes the version of the Kubernetes API Server, Controller Manager, Scheduler and Proxy.
@@ -65,7 +74,7 @@ type ClusterState struct {
// GetAvailableUpgrades fetches all versions from the specified VersionGetter and computes which
// kinds of upgrades can be performed
func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, cluster util.EtcdCluster) ([]Upgrade, error) {
func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, cluster util.EtcdCluster, featureGates map[string]bool) ([]Upgrade, error) {
fmt.Println("[upgrade] Fetching available versions to upgrade to")
// Collect the upgrades kubeadm can do in this list
@@ -104,10 +113,9 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
}
// Construct a descriptor for the current state of the world
// TODO: Make CoreDNS available here.
beforeState := ClusterState{
KubeVersion: clusterVersionStr,
DNSVersion: dns.GetDNSVersion(clusterVersion, kubeadmconstants.KubeDNS),
DNSVersion: dns.GetDNSVersion(clusterVersion, ActiveDNSAddon(featureGates)),
KubeadmVersion: kubeadmVersionStr,
KubeletVersions: kubeletVersions,
EtcdVersion: etcdStatus.Version,
@@ -150,7 +158,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
Before: beforeState,
After: ClusterState{
KubeVersion: patchVersionStr,
DNSVersion: dns.GetDNSVersion(patchVersion, kubeadmconstants.KubeDNS),
DNSVersion: dns.GetDNSVersion(patchVersion, ActiveDNSAddon(featureGates)),
KubeadmVersion: newKubeadmVer,
EtcdVersion: getSuggestedEtcdVersion(patchVersionStr),
// KubeletVersions is unset here as it is not used anywhere in .After
@@ -166,7 +174,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
Before: beforeState,
After: ClusterState{
KubeVersion: stableVersionStr,
DNSVersion: dns.GetDNSVersion(stableVersion, kubeadmconstants.KubeDNS),
DNSVersion: dns.GetDNSVersion(stableVersion, ActiveDNSAddon(featureGates)),
KubeadmVersion: stableVersionStr,
EtcdVersion: getSuggestedEtcdVersion(stableVersionStr),
// KubeletVersions is unset here as it is not used anywhere in .After
@@ -211,7 +219,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
Before: beforeState,
After: ClusterState{
KubeVersion: previousBranchLatestVersionStr,
DNSVersion: dns.GetDNSVersion(previousBranchLatestVersion, kubeadmconstants.KubeDNS),
DNSVersion: dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates)),
KubeadmVersion: previousBranchLatestVersionStr,
EtcdVersion: getSuggestedEtcdVersion(previousBranchLatestVersionStr),
// KubeletVersions is unset here as it is not used anywhere in .After
@@ -224,12 +232,12 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA
// Default to assume that the experimental version to show is the unstable one
unstableKubeVersion := latestVersionStr
unstableKubeDNSVersion := dns.GetDNSVersion(latestVersion, kubeadmconstants.KubeDNS)
unstableKubeDNSVersion := dns.GetDNSVersion(latestVersion, ActiveDNSAddon(featureGates))
// Ẃe should not display alpha.0. The previous branch's beta/rc versions are more relevant due how the kube branching process works.
if latestVersion.PreRelease() == "alpha.0" {
unstableKubeVersion = previousBranchLatestVersionStr
unstableKubeDNSVersion = dns.GetDNSVersion(previousBranchLatestVersion, kubeadmconstants.KubeDNS)
unstableKubeDNSVersion = dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates))
}
upgrades = append(upgrades, Upgrade{

View File

@@ -69,6 +69,7 @@ func (f fakeEtcdCluster) GetEtcdClusterStatus() (*clientv3.StatusResponse, error
}
func TestGetAvailableUpgrades(t *testing.T) {
featureGates := make(map[string]bool)
tests := []struct {
vg *fakeVersionGetter
expectedUpgrades []Upgrade
@@ -444,7 +445,7 @@ func TestGetAvailableUpgrades(t *testing.T) {
testCluster := fakeEtcdCluster{}
for _, rt := range tests {
actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, testCluster)
actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, testCluster, featureGates)
if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) {
t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades)
}

View File

@@ -19,16 +19,20 @@ package upgrade
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/errors"
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
"k8s.io/kubernetes/pkg/util/version"
)
@@ -88,8 +92,33 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC
if err := dns.EnsureDNSAddon(cfg, client); err != nil {
errs = append(errs, err)
}
if err := coreDNSDeployment(cfg, client); err != nil {
errs = append(errs, err)
}
if err := proxy.EnsureProxyAddon(cfg, client); err != nil {
errs = append(errs, err)
}
return errors.NewAggregate(errs)
}
func coreDNSDeployment(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error {
if features.Enabled(cfg.FeatureGates, features.CoreDNS) {
return apiclient.TryRunCommand(func() error {
getCoreDNS, err := client.AppsV1beta2().Deployments(metav1.NamespaceSystem).Get(kubeadmconstants.CoreDNS, metav1.GetOptions{})
if err != nil {
return err
}
if getCoreDNS.Status.ReadyReplicas == 0 {
return fmt.Errorf("the CodeDNS deployment isn't ready yet")
}
err = client.AppsV1beta2().Deployments(metav1.NamespaceSystem).Delete(kubeadmconstants.KubeDNS, nil)
if err != nil {
return err
}
return nil
}, 5)
}
return nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3743,6 +3743,54 @@ Examples:<br>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_eventseries">v1.EventSeries</h3>
<div class="paragraph">
<p>EventSeries contain information on series of events, i.e. thing that was/is happening continously for some time.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">count</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Number of occurrences in this series up to the last heartbeat time</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">lastObservedTime</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Time of the last occurence observed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">state</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">State of this Series: Ongoing or Finished</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_httpgetaction">v1.HTTPGetAction</h3>
@@ -5300,6 +5348,48 @@ Examples:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">eventTime</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Time when this Event was first observed.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">series</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Data about the Event series this event represents or nil if it&#8217;s a singleton Event.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_eventseries">v1.EventSeries</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">action</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">What action was taken/failed regarding to the Regarding object.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">related</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional secondary object for more complex actions.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_objectreference">v1.ObjectReference</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">reportingComponent</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Name of the controller that emitted this Event, e.g. <code>kubernetes.io/kubelet</code>.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">reportingInstance</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ID of the controller instance, e.g. <code>kubelet-xyzf</code>.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>

View File

@@ -53,6 +53,8 @@ pkg/apis/core/v1/helper
pkg/apis/core/v1/helper/qos
pkg/apis/core/v1/validation
pkg/apis/core/validation
pkg/apis/events
pkg/apis/events/v1beta1
pkg/apis/extensions
pkg/apis/extensions/validation
pkg/apis/imagepolicy
@@ -292,6 +294,7 @@ pkg/registry/core/service/portallocator
pkg/registry/core/service/portallocator/controller
pkg/registry/core/service/storage
pkg/registry/core/serviceaccount/storage
pkg/registry/events/rest
pkg/registry/extensions/controller/storage
pkg/registry/extensions/daemonset
pkg/registry/extensions/daemonset/storage
@@ -449,6 +452,7 @@ staging/src/k8s.io/api/batch/v1beta1
staging/src/k8s.io/api/batch/v2alpha1
staging/src/k8s.io/api/certificates/v1beta1
staging/src/k8s.io/api/core/v1
staging/src/k8s.io/api/events/v1beta1
staging/src/k8s.io/api/extensions/v1beta1
staging/src/k8s.io/api/imagepolicy/v1alpha1
staging/src/k8s.io/api/networking/v1
@@ -659,6 +663,8 @@ staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1
staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake
staging/src/k8s.io/client-go/kubernetes/typed/core/v1
staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake
staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1
staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1/fake
staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1
staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake
staging/src/k8s.io/client-go/kubernetes/typed/networking/v1

View File

@@ -4,6 +4,7 @@
- k8s.io/apiserver/pkg/util/feature
- k8s.io/kubernetes/pkg/apis/core
- k8s.io/kubernetes/pkg/features
- k8s.io/kubernetes/pkg/fieldpath
- k8s.io/kubernetes/pkg/util
- k8s.io/api/core/v1

View File

@@ -69,6 +69,7 @@ batch/v1beta1 \
batch/v2alpha1 \
certificates.k8s.io/v1beta1 \
extensions/v1beta1 \
events.k8s.io/v1beta1 \
imagepolicy.k8s.io/v1alpha1 \
networking.k8s.io/v1 \
policy/v1beta1 \

View File

@@ -59,10 +59,10 @@ for gv in "${GROUP_VERSIONS[@]}"; do
# collect internal groups
int_group="${pkg_dir%/*}/"
if [[ "${pkg_dir}" = core/* ]]; then
int_group="api/"
int_group="api/"
fi
if ! [[ " ${INTERNAL_DIRS[@]:-} " =~ " ${int_group} " ]]; then
INTERNAL_DIRS+=("${int_group}")
INTERNAL_DIRS+=("${int_group}")
fi
done
# delimit by commas for the command

View File

@@ -60,6 +60,7 @@ PACKAGES=(
k8s.io/api/apps/v1
k8s.io/api/authentication/v1
k8s.io/api/authentication/v1beta1
k8s.io/api/events/v1beta1
k8s.io/api/rbac/v1alpha1
k8s.io/api/rbac/v1beta1
k8s.io/api/rbac/v1

View File

@@ -40,6 +40,7 @@ filegroup(
"//pkg/apis/certificates:all-srcs",
"//pkg/apis/componentconfig:all-srcs",
"//pkg/apis/core:all-srcs",
"//pkg/apis/events:all-srcs",
"//pkg/apis/extensions:all-srcs",
"//pkg/apis/imagepolicy:all-srcs",
"//pkg/apis/networking:all-srcs",

View File

@@ -30,6 +30,8 @@ go_library(
"//pkg/apis/componentconfig/install:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/install:go_default_library",
"//pkg/apis/events:go_default_library",
"//pkg/apis/events/install:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/install:go_default_library",
"//pkg/apis/imagepolicy:go_default_library",

View File

@@ -43,6 +43,7 @@ import (
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/certificates"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/events"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/imagepolicy"
"k8s.io/kubernetes/pkg/apis/networking"
@@ -62,6 +63,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/core/install"
_ "k8s.io/kubernetes/pkg/apis/events/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
_ "k8s.io/kubernetes/pkg/apis/networking/install"
@@ -79,6 +81,7 @@ var (
Autoscaling TestGroup
Batch TestGroup
Extensions TestGroup
Events TestGroup
Apps TestGroup
Policy TestGroup
Rbac TestGroup
@@ -314,6 +317,15 @@ func init() {
externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion),
}
}
if _, ok := Groups[events.GroupName]; !ok {
externalGroupVersion := schema.GroupVersion{Group: events.GroupName, Version: legacyscheme.Registry.GroupOrDie(events.GroupName).GroupVersion.Version}
Groups[events.GroupName] = TestGroup{
externalGroupVersion: externalGroupVersion,
internalGroupVersion: events.SchemeGroupVersion,
internalTypes: legacyscheme.Scheme.KnownTypes(events.SchemeGroupVersion),
externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion),
}
}
Default = Groups[api.GroupName]
Autoscaling = Groups[autoscaling.GroupName]
@@ -322,6 +334,7 @@ func init() {
Policy = Groups[policy.GroupName]
Certificates = Groups[certificates.GroupName]
Extensions = Groups[extensions.GroupName]
Events = Groups[events.GroupName]
Rbac = Groups[rbac.GroupName]
Scheduling = Groups[scheduling.GroupName]
Settings = Groups[settings.GroupName]

View File

@@ -51,6 +51,7 @@ filegroup(
"//pkg/apis/core/fuzzer:all-srcs",
"//pkg/apis/core/helper:all-srcs",
"//pkg/apis/core/install:all-srcs",
"//pkg/apis/core/pods:all-srcs",
"//pkg/apis/core/v1:all-srcs",
"//pkg/apis/core/validation:all-srcs",
],

View File

@@ -25,8 +25,8 @@ const (
PodStatusField = "status.phase"
SecretTypeField = "type"
EventReasonField = "reason"
EventSourceField = "source"
EventReasonField = "action"
EventSourceField = "reportingComponent"
EventTypeField = "type"
EventInvolvedKindField = "involvedObject.kind"
EventInvolvedNamespaceField = "involvedObject.namespace"

View File

@@ -13,6 +13,7 @@ go_library(
"//pkg/apis/core:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@@ -19,10 +19,12 @@ package fuzzer
import (
"reflect"
"strconv"
"time"
fuzz "github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@@ -483,5 +485,12 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
c.FuzzNoCustom(s)
s.Allocatable = s.Capacity
},
func(e *core.Event, c fuzz.Continue) {
c.FuzzNoCustom(e)
e.EventTime = metav1.MicroTime{Time: time.Unix(1, 1000)}
if e.Series != nil {
e.Series.LastObservedTime = metav1.MicroTime{Time: time.Unix(3, 3000)}
}
},
}
}

30
pkg/apis/core/pods/BUILD Normal file
View File

@@ -0,0 +1,30 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["helpers.go"],
importpath = "k8s.io/kubernetes/pkg/apis/core/pods",
visibility = ["//visibility:public"],
deps = ["//pkg/fieldpath:go_default_library"],
)
go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
importpath = "k8s.io/kubernetes/pkg/apis/core/pods",
library = ":go_default_library",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,63 @@
/*
Copyright 2017 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 pods
import (
"fmt"
"k8s.io/kubernetes/pkg/fieldpath"
)
// ConvertDownwardAPIFieldLabel converts the specified downward API field label
// and its value in the pod of the specified version to the internal version,
// and returns the converted label and value. This function returns an error if
// the conversion fails.
func ConvertDownwardAPIFieldLabel(version, label, value string) (string, string, error) {
if version != "v1" {
return "", "", fmt.Errorf("unsupported pod version: %s", version)
}
if path, _, ok := fieldpath.SplitMaybeSubscriptedPath(label); ok {
switch path {
case "metadata.annotations", "metadata.labels":
return label, value, nil
default:
return "", "", fmt.Errorf("field label does not support subscript: %s", label)
}
}
switch label {
case "metadata.annotations",
"metadata.labels",
"metadata.name",
"metadata.namespace",
"metadata.uid",
"spec.nodeName",
"spec.restartPolicy",
"spec.serviceAccountName",
"spec.schedulerName",
"status.phase",
"status.hostIP",
"status.podIP":
return label, value, nil
// This is for backwards compatibility with old v1 clients which send spec.host
case "spec.host":
return "spec.nodeName", value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
}

View File

@@ -0,0 +1,87 @@
/*
Copyright 2017 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 pods
import (
"testing"
)
func TestConvertDownwardAPIFieldLabel(t *testing.T) {
testCases := []struct {
version string
label string
value string
expectedErr bool
expectedLabel string
expectedValue string
}{
{
version: "v2",
label: "metadata.name",
value: "test-pod",
expectedErr: true,
},
{
version: "v1",
label: "invalid-label",
value: "value",
expectedErr: true,
},
{
version: "v1",
label: "metadata.name",
value: "test-pod",
expectedLabel: "metadata.name",
expectedValue: "test-pod",
},
{
version: "v1",
label: "metadata.annotations",
value: "myValue",
expectedLabel: "metadata.annotations",
expectedValue: "myValue",
},
{
version: "v1",
label: "metadata.annotations['myKey']",
value: "myValue",
expectedLabel: "metadata.annotations['myKey']",
expectedValue: "myValue",
},
{
version: "v1",
label: "spec.host",
value: "127.0.0.1",
expectedLabel: "spec.nodeName",
expectedValue: "127.0.0.1",
},
}
for _, tc := range testCases {
label, value, err := ConvertDownwardAPIFieldLabel(tc.version, tc.label, tc.value)
if err != nil {
if tc.expectedErr {
continue
}
t.Errorf("ConvertDownwardAPIFieldLabel(%s, %s, %s) failed: %s",
tc.version, tc.label, tc.value, err)
}
if tc.expectedLabel != label || tc.expectedValue != value {
t.Errorf("ConvertDownwardAPIFieldLabel(%s, %s, %s) = (%s, %s, nil), expected (%s, %s, nil)",
tc.version, tc.label, tc.value, label, value, tc.expectedLabel, tc.expectedValue)
}
}
}

View File

@@ -3958,7 +3958,7 @@ type Event struct {
// +optional
metav1.ObjectMeta
// Required. The object that this event is about.
// Required. The object that this event is about. Mapped to events.Event.regarding
// +optional
InvolvedObject ObjectReference
@@ -3970,7 +3970,7 @@ type Event struct {
Reason string
// Optional. A human-readable description of the status of this operation.
// TODO: decide on maximum length.
// TODO: decide on maximum length. Mapped to events.Event.note
// +optional
Message string
@@ -3993,8 +3993,49 @@ type Event struct {
// Type of this event (Normal, Warning), new types could be added in the future.
// +optional
Type string
// Time when this Event was first observed.
// +optional
EventTime metav1.MicroTime
// Data about the Event series this event represents or nil if it's a singleton Event.
// +optional
Series *EventSeries
// What action was taken/failed regarding to the Regarding object.
// +optional
Action string
// Optional secondary object for more complex actions.
// +optional
Related *ObjectReference
// Name of the controller that emitted this Event, e.g. `kubernetes.io/kubelet`.
// +optional
ReportingController string
// ID of the controller instance, e.g. `kubelet-xyzf`.
// +optional
ReportingInstance string
}
type EventSeries struct {
// Number of occurrences in this series up to the last heartbeat time
Count int32
// Time of the last occurence observed
LastObservedTime metav1.MicroTime
// State of this Series: Ongoing or Finished
State EventSeriesState
}
type EventSeriesState string
const (
EventSeriesStateOngoing EventSeriesState = "Ongoing"
EventSeriesStateFinished EventSeriesState = "Finished"
EventSeriesStateUnknown EventSeriesState = "Unknown"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// EventList is a list of events.

View File

@@ -157,20 +157,15 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
err = scheme.AddFieldLabelConversionFunc("v1", "Pod",
func(label, value string) (string, string, error) {
switch label {
case "metadata.annotations",
"metadata.labels",
"metadata.name",
case "metadata.name",
"metadata.namespace",
"metadata.uid",
"spec.nodeName",
"spec.restartPolicy",
"spec.serviceAccountName",
"spec.schedulerName",
"status.phase",
"status.hostIP",
"status.podIP":
return label, value, nil
// This is for backwards compatibility with old v1 clients which send spec.host
// This is for backwards compatibility with old v1 clients which send spec.host
case "spec.host":
return "spec.nodeName", value, nil
default:

View File

@@ -133,6 +133,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_core_Event_To_v1_Event,
Convert_v1_EventList_To_core_EventList,
Convert_core_EventList_To_v1_EventList,
Convert_v1_EventSeries_To_core_EventSeries,
Convert_core_EventSeries_To_v1_EventSeries,
Convert_v1_EventSource_To_core_EventSource,
Convert_core_EventSource_To_v1_EventSource,
Convert_v1_ExecAction_To_core_ExecAction,
@@ -1598,6 +1600,12 @@ func autoConvert_v1_Event_To_core_Event(in *v1.Event, out *core.Event, s convers
out.LastTimestamp = in.LastTimestamp
out.Count = in.Count
out.Type = in.Type
out.EventTime = in.EventTime
out.Series = (*core.EventSeries)(unsafe.Pointer(in.Series))
out.Action = in.Action
out.Related = (*core.ObjectReference)(unsafe.Pointer(in.Related))
out.ReportingController = in.ReportingController
out.ReportingInstance = in.ReportingInstance
return nil
}
@@ -1620,6 +1628,12 @@ func autoConvert_core_Event_To_v1_Event(in *core.Event, out *v1.Event, s convers
out.LastTimestamp = in.LastTimestamp
out.Count = in.Count
out.Type = in.Type
out.EventTime = in.EventTime
out.Series = (*v1.EventSeries)(unsafe.Pointer(in.Series))
out.Action = in.Action
out.Related = (*v1.ObjectReference)(unsafe.Pointer(in.Related))
out.ReportingController = in.ReportingController
out.ReportingInstance = in.ReportingInstance
return nil
}
@@ -1650,6 +1664,30 @@ func Convert_core_EventList_To_v1_EventList(in *core.EventList, out *v1.EventLis
return autoConvert_core_EventList_To_v1_EventList(in, out, s)
}
func autoConvert_v1_EventSeries_To_core_EventSeries(in *v1.EventSeries, out *core.EventSeries, s conversion.Scope) error {
out.Count = in.Count
out.LastObservedTime = in.LastObservedTime
out.State = core.EventSeriesState(in.State)
return nil
}
// Convert_v1_EventSeries_To_core_EventSeries is an autogenerated conversion function.
func Convert_v1_EventSeries_To_core_EventSeries(in *v1.EventSeries, out *core.EventSeries, s conversion.Scope) error {
return autoConvert_v1_EventSeries_To_core_EventSeries(in, out, s)
}
func autoConvert_core_EventSeries_To_v1_EventSeries(in *core.EventSeries, out *v1.EventSeries, s conversion.Scope) error {
out.Count = in.Count
out.LastObservedTime = in.LastObservedTime
out.State = v1.EventSeriesState(in.State)
return nil
}
// Convert_core_EventSeries_To_v1_EventSeries is an autogenerated conversion function.
func Convert_core_EventSeries_To_v1_EventSeries(in *core.EventSeries, out *v1.EventSeries, s conversion.Scope) error {
return autoConvert_core_EventSeries_To_v1_EventSeries(in, out, s)
}
func autoConvert_v1_EventSource_To_core_EventSource(in *v1.EventSource, out *core.EventSource, s conversion.Scope) error {
out.Component = in.Component
out.Host = in.Host

View File

@@ -18,10 +18,12 @@ go_library(
"//pkg/api/service:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/helper:go_default_library",
"//pkg/apis/core/pods:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/features:go_default_library",
"//pkg/fieldpath:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",

View File

@@ -18,6 +18,7 @@ package validation
import (
"fmt"
"time"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -28,24 +29,68 @@ import (
"k8s.io/kubernetes/pkg/apis/core"
)
const (
ReportingInstanceLengthLimit = 128
ActionLengthLimit = 128
ReasonLengthLimit = 128
NoteLengthLimit = 1024
)
// ValidateEvent makes sure that the event makes sense.
func ValidateEvent(event *core.Event) field.ErrorList {
allErrs := field.ErrorList{}
// Because go
zeroTime := time.Time{}
// Make sure event.Namespace and the involvedObject.Namespace agree
if len(event.InvolvedObject.Namespace) == 0 {
// event.Namespace must also be empty (or "default", for compatibility with old clients)
if event.Namespace != metav1.NamespaceNone && event.Namespace != metav1.NamespaceDefault {
// "New" Events need to have EventTime set, so it's validating old object.
if event.EventTime.Time == zeroTime {
// Make sure event.Namespace and the involvedInvolvedObject.Namespace agree
if len(event.InvolvedObject.Namespace) == 0 {
// event.Namespace must also be empty (or "default", for compatibility with old clients)
if event.Namespace != metav1.NamespaceNone && event.Namespace != metav1.NamespaceDefault {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace"))
}
} else {
// event namespace must match
if event.Namespace != event.InvolvedObject.Namespace {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace"))
}
}
} else {
if len(event.InvolvedObject.Namespace) == 0 && event.Namespace != metav1.NamespaceSystem {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace"))
}
} else {
// event namespace must match
if event.Namespace != event.InvolvedObject.Namespace {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace"))
if len(event.ReportingController) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("reportingController"), ""))
}
for _, msg := range validation.IsQualifiedName(event.ReportingController) {
allErrs = append(allErrs, field.Invalid(field.NewPath("reportingController"), event.ReportingController, msg))
}
if len(event.ReportingInstance) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("reportingInstance"), ""))
}
if len(event.ReportingInstance) > ReportingInstanceLengthLimit {
allErrs = append(allErrs, field.Invalid(field.NewPath("repotingIntance"), "", fmt.Sprintf("can have at most %v characters", ReportingInstanceLengthLimit)))
}
if len(event.Action) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("action"), ""))
}
if len(event.Action) > ActionLengthLimit {
allErrs = append(allErrs, field.Invalid(field.NewPath("action"), "", fmt.Sprintf("can have at most %v characters", ActionLengthLimit)))
}
if len(event.Reason) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("reason"), ""))
}
if len(event.Reason) > ReasonLengthLimit {
allErrs = append(allErrs, field.Invalid(field.NewPath("reason"), "", fmt.Sprintf("can have at most %v characters", ReasonLengthLimit)))
}
if len(event.Message) > NoteLengthLimit {
allErrs = append(allErrs, field.Invalid(field.NewPath("message"), "", fmt.Sprintf("can have at most %v characters", NoteLengthLimit)))
}
}
// For kinds we recognize, make sure involvedObject.Namespace is set for namespaced kinds
// For kinds we recognize, make sure InvolvedObject.Namespace is set for namespaced kinds
if namespaced, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion); err == nil {
if namespaced && len(event.InvolvedObject.Namespace) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("involvedObject", "namespace"), fmt.Sprintf("required for kind %s", event.InvolvedObject.Kind)))

View File

@@ -18,6 +18,7 @@ package validation
import (
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/apis/core"
@@ -215,7 +216,177 @@ func TestValidateEvent(t *testing.T) {
for _, item := range table {
if e, a := item.valid, len(ValidateEvent(item.Event)) == 0; e != a {
t.Errorf("%v: expected %v, got %v", item.Event.Name, e, a)
t.Errorf("%v: expected %v, got %v: %v", item.Event.Name, e, a, ValidateEvent(item.Event))
}
}
}
func TestValidateNewEvent(t *testing.T) {
someTime := metav1.MicroTime{Time: time.Unix(1505828956, 0)}
table := []struct {
*core.Event
valid bool
msg string
}{
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
},
valid: false,
msg: "Old Event with EventTime should trigger new validation and fail",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Action: "Do",
Reason: "Because",
},
valid: true,
msg: "Valid new Event",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "my-contr@ller",
ReportingInstance: "node-xyz",
Action: "Do",
Reason: "Because",
},
valid: false,
msg: "not qualified reportingController",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
Action: "Do",
Reason: "Because",
},
valid: false,
msg: "too long reporting instance",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Action: "Do",
},
valid: false,
msg: "missing reason",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Reason: "Because",
},
valid: false,
msg: "missing action",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Reason: "Because",
},
valid: false,
msg: "missing namespace",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Action: "Do",
Reason: "Because",
Message: `zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz`,
},
valid: false,
msg: "too long message",
},
}
for _, item := range table {
if e, a := item.valid, len(ValidateEvent(item.Event)) == 0; e != a {
t.Errorf("%v: expected %v, got %v: %v", item.msg, e, a, ValidateEvent(item.Event))
}
}
}

View File

@@ -42,14 +42,15 @@ import (
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
apiservice "k8s.io/kubernetes/pkg/api/service"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
podshelper "k8s.io/kubernetes/pkg/apis/core/pods"
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/fieldpath"
"k8s.io/kubernetes/pkg/security/apparmor"
)
@@ -960,7 +961,7 @@ func validateFlockerVolumeSource(flocker *core.FlockerVolumeSource, fldPath *fie
return allErrs
}
var validDownwardAPIFieldPathExpressions = sets.NewString(
var validVolumeDownwardAPIFieldPathExpressions = sets.NewString(
"metadata.name",
"metadata.namespace",
"metadata.labels",
@@ -975,7 +976,7 @@ func validateDownwardAPIVolumeFile(file *core.DownwardAPIVolumeFile, fldPath *fi
}
allErrs = append(allErrs, validateLocalNonReservedPath(file.Path, fldPath.Child("path"))...)
if file.FieldRef != nil {
allErrs = append(allErrs, validateObjectFieldSelector(file.FieldRef, &validDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
allErrs = append(allErrs, validateObjectFieldSelector(file.FieldRef, &validVolumeDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
if file.ResourceFieldRef != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "resource", "fieldRef and resourceFieldRef can not be specified simultaneously"))
}
@@ -1898,7 +1899,14 @@ func ValidateEnv(vars []core.EnvVar, fldPath *field.Path) field.ErrorList {
return allErrs
}
var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP")
var validEnvDownwardAPIFieldPathExpressions = sets.NewString(
"metadata.name",
"metadata.namespace",
"metadata.uid",
"spec.nodeName",
"spec.serviceAccountName",
"status.hostIP",
"status.podIP")
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "limits.ephemeral-storage", "requests.cpu", "requests.memory", "requests.ephemeral-storage")
func validateEnvVarValueFrom(ev core.EnvVar, fldPath *field.Path) field.ErrorList {
@@ -1912,7 +1920,7 @@ func validateEnvVarValueFrom(ev core.EnvVar, fldPath *field.Path) field.ErrorLis
if ev.ValueFrom.FieldRef != nil {
numSources++
allErrs = append(allErrs, validateObjectFieldSelector(ev.ValueFrom.FieldRef, &validFieldPathExpressionsEnv, fldPath.Child("fieldRef"))...)
allErrs = append(allErrs, validateObjectFieldSelector(ev.ValueFrom.FieldRef, &validEnvDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
}
if ev.ValueFrom.ResourceFieldRef != nil {
numSources++
@@ -1945,15 +1953,35 @@ func validateObjectFieldSelector(fs *core.ObjectFieldSelector, expressions *sets
if len(fs.APIVersion) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("apiVersion"), ""))
} else if len(fs.FieldPath) == 0 {
return allErrs
}
if len(fs.FieldPath) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("fieldPath"), ""))
} else {
internalFieldPath, _, err := legacyscheme.Scheme.ConvertFieldLabel(fs.APIVersion, "Pod", fs.FieldPath, "")
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("fieldPath"), fs.FieldPath, fmt.Sprintf("error converting fieldPath: %v", err)))
} else if !expressions.Has(internalFieldPath) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("fieldPath"), internalFieldPath, expressions.List()))
return allErrs
}
internalFieldPath, _, err := podshelper.ConvertDownwardAPIFieldLabel(fs.APIVersion, fs.FieldPath, "")
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("fieldPath"), fs.FieldPath, fmt.Sprintf("error converting fieldPath: %v", err)))
return allErrs
}
if path, subscript, ok := fieldpath.SplitMaybeSubscriptedPath(internalFieldPath); ok {
switch path {
case "metadata.annotations":
for _, msg := range validation.IsQualifiedName(strings.ToLower(subscript)) {
allErrs = append(allErrs, field.Invalid(fldPath, subscript, msg))
}
case "metadata.labels":
for _, msg := range validation.IsQualifiedName(subscript) {
allErrs = append(allErrs, field.Invalid(fldPath, subscript, msg))
}
default:
allErrs = append(allErrs, field.Invalid(fldPath, path, "does not support subscript"))
}
} else if !expressions.Has(path) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("fieldPath"), path, expressions.List()))
return allErrs
}
return allErrs

View File

@@ -2628,6 +2628,20 @@ func TestValidateVolumes(t *testing.T) {
FieldPath: "metadata.labels",
},
},
{
Path: "labels with subscript",
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.labels['key']",
},
},
{
Path: "labels with complex subscript",
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.labels['test.example.com/key']",
},
},
{
Path: "annotations",
FieldRef: &core.ObjectFieldSelector{
@@ -2635,6 +2649,20 @@ func TestValidateVolumes(t *testing.T) {
FieldPath: "metadata.annotations",
},
},
{
Path: "annotations with subscript",
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.annotations['key']",
},
},
{
Path: "annotations with complex subscript",
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.annotations['TEST.EXAMPLE.COM/key']",
},
},
{
Path: "namespace",
FieldRef: &core.ObjectFieldSelector{
@@ -3824,6 +3852,24 @@ func TestValidateEnv(t *testing.T) {
{Name: "abc", Value: ""},
{Name: "a.b.c", Value: "value"},
{Name: "a-b-c", Value: "value"},
{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(),
FieldPath: "metadata.annotations['key']",
},
},
},
{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: legacyscheme.Registry.GroupOrDie(core.GroupName).GroupVersion.String(),
FieldPath: "metadata.labels['key']",
},
},
},
{
Name: "abc",
ValueFrom: &core.EnvVarSource{
@@ -4095,7 +4141,20 @@ func TestValidateEnv(t *testing.T) {
expectedError: `[0].valueFrom.fieldRef.fieldPath: Invalid value: "metadata.whoops": error converting fieldPath`,
},
{
name: "invalid fieldPath labels",
name: "metadata.name with subscript",
envs: []core.EnvVar{{
Name: "labels",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.name['key']",
APIVersion: "v1",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Invalid value: "metadata.name['key']": error converting fieldPath: field label does not support subscript`,
},
{
name: "metadata.labels without subscript",
envs: []core.EnvVar{{
Name: "labels",
ValueFrom: &core.EnvVarSource{
@@ -4108,7 +4167,7 @@ func TestValidateEnv(t *testing.T) {
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP"`,
},
{
name: "invalid fieldPath annotations",
name: "metadata.annotations without subscript",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
@@ -4120,6 +4179,32 @@ func TestValidateEnv(t *testing.T) {
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP"`,
},
{
name: "metadata.annotations with invalid key",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.annotations['invalid~key']",
APIVersion: "v1",
},
},
}},
expectedError: `field[0].valueFrom.fieldRef: Invalid value: "invalid~key"`,
},
{
name: "metadata.labels with invalid key",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.labels['Www.k8s.io/test']",
APIVersion: "v1",
},
},
}},
expectedError: `field[0].valueFrom.fieldRef: Invalid value: "Www.k8s.io/test"`,
},
{
name: "unsupported fieldPath",
envs: []core.EnvVar{{

View File

@@ -1383,6 +1383,25 @@ func (in *Event) DeepCopyInto(out *Event) {
out.Source = in.Source
in.FirstTimestamp.DeepCopyInto(&out.FirstTimestamp)
in.LastTimestamp.DeepCopyInto(&out.LastTimestamp)
in.EventTime.DeepCopyInto(&out.EventTime)
if in.Series != nil {
in, out := &in.Series, &out.Series
if *in == nil {
*out = nil
} else {
*out = new(EventSeries)
(*in).DeepCopyInto(*out)
}
}
if in.Related != nil {
in, out := &in.Related, &out.Related
if *in == nil {
*out = nil
} else {
*out = new(ObjectReference)
**out = **in
}
}
return
}
@@ -1439,6 +1458,23 @@ func (in *EventList) DeepCopyObject() runtime.Object {
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EventSeries) DeepCopyInto(out *EventSeries) {
*out = *in
in.LastObservedTime.DeepCopyInto(&out.LastObservedTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventSeries.
func (in *EventSeries) DeepCopy() *EventSeries {
if in == nil {
return nil
}
out := new(EventSeries)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EventSource) DeepCopyInto(out *EventSource) {
*out = *in

34
pkg/apis/events/BUILD Normal file
View File

@@ -0,0 +1,34 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/events",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/apis/events/install:all-srcs",
"//pkg/apis/events/v1beta1:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

18
pkg/apis/events/doc.go Normal file
View File

@@ -0,0 +1,18 @@
/*
Copyright 2017 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.
*/
// +groupName=events.k8s.io
package events // import "k8s.io/kubernetes/pkg/apis/events"

View File

@@ -0,0 +1,30 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["install.go"],
importpath = "k8s.io/kubernetes/pkg/apis/events/install",
visibility = ["//visibility:public"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/events:go_default_library",
"//pkg/apis/events/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,48 @@
/*
Copyright 2016 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 install installs the events API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/events"
"k8s.io/kubernetes/pkg/apis/events/v1beta1"
)
func init() {
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}
// Install registers the API group and adds types to a scheme
func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{
GroupName: events.GroupName,
VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: events.AddToScheme,
},
announced.VersionToSchemeFunc{
v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme,
},
).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,52 @@
/*
Copyright 2017 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 events
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/apis/core"
)
// GroupName is the group name use in this package
const GroupName = "events.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&core.Event{},
&core.EventList{},
)
return nil
}

View File

@@ -0,0 +1,37 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"doc.go",
"register.go",
"zz_generated.conversion.go",
"zz_generated.defaults.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/events/v1beta1",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/events/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,58 @@
/*
Copyright 2017 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 v1beta1
import (
v1beta1 "k8s.io/api/events/v1beta1"
conversion "k8s.io/apimachinery/pkg/conversion"
k8s_api "k8s.io/kubernetes/pkg/apis/core"
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
)
func Convert_v1beta1_Event_To_core_Event(in *v1beta1.Event, out *k8s_api.Event, s conversion.Scope) error {
if err := autoConvert_v1beta1_Event_To_core_Event(in, out, s); err != nil {
return err
}
if err := k8s_api_v1.Convert_v1_ObjectReference_To_core_ObjectReference(&in.Regarding, &out.InvolvedObject, s); err != nil {
return err
}
if err := k8s_api_v1.Convert_v1_EventSource_To_core_EventSource(&in.DeprecatedSource, &out.Source, s); err != nil {
return err
}
out.Message = in.Note
out.FirstTimestamp = in.DeprecatedFirstTimestamp
out.LastTimestamp = in.DeprecatedLastTimestamp
out.Count = in.DeprecatedCount
return nil
}
func Convert_core_Event_To_v1beta1_Event(in *k8s_api.Event, out *v1beta1.Event, s conversion.Scope) error {
if err := autoConvert_core_Event_To_v1beta1_Event(in, out, s); err != nil {
return err
}
if err := k8s_api_v1.Convert_core_ObjectReference_To_v1_ObjectReference(&in.InvolvedObject, &out.Regarding, s); err != nil {
return err
}
if err := k8s_api_v1.Convert_core_EventSource_To_v1_EventSource(&in.Source, &out.DeprecatedSource, s); err != nil {
return err
}
out.Note = in.Message
out.DeprecatedFirstTimestamp = in.FirstTimestamp
out.DeprecatedLastTimestamp = in.LastTimestamp
out.DeprecatedCount = in.Count
return nil
}

View File

@@ -0,0 +1,23 @@
/*
Copyright 2017 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.
*/
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/events
// +k8s:conversion-gen-external-types=../../../../vendor/k8s.io/api/events/v1beta1
// +k8s:defaulter-gen=TypeMeta
// +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/events/v1beta1
// +groupName=events.k8s.io
package v1beta1 // import "k8s.io/kubernetes/pkg/apis/events/v1beta1"

View File

@@ -0,0 +1,45 @@
/*
Copyright 2017 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 v1beta1
import (
eventsv1beta1 "k8s.io/api/events/v1beta1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name use in this package
const GroupName = "events.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
localSchemeBuilder = &eventsv1beta1.SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(RegisterDefaults)
}

View File

@@ -0,0 +1,151 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by conversion-gen. Do not edit it manually!
package v1beta1
import (
v1 "k8s.io/api/core/v1"
v1beta1 "k8s.io/api/events/v1beta1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
core "k8s.io/kubernetes/pkg/apis/core"
unsafe "unsafe"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1beta1_Event_To_core_Event,
Convert_core_Event_To_v1beta1_Event,
Convert_v1beta1_EventList_To_core_EventList,
Convert_core_EventList_To_v1beta1_EventList,
Convert_v1beta1_EventSeries_To_core_EventSeries,
Convert_core_EventSeries_To_v1beta1_EventSeries,
)
}
func autoConvert_v1beta1_Event_To_core_Event(in *v1beta1.Event, out *core.Event, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.EventTime = in.EventTime
out.Series = (*core.EventSeries)(unsafe.Pointer(in.Series))
out.ReportingController = in.ReportingController
out.ReportingInstance = in.ReportingInstance
out.Action = in.Action
out.Reason = in.Reason
// WARNING: in.Regarding requires manual conversion: does not exist in peer-type
out.Related = (*core.ObjectReference)(unsafe.Pointer(in.Related))
// WARNING: in.Note requires manual conversion: does not exist in peer-type
out.Type = in.Type
// WARNING: in.DeprecatedSource requires manual conversion: does not exist in peer-type
// WARNING: in.DeprecatedFirstTimestamp requires manual conversion: does not exist in peer-type
// WARNING: in.DeprecatedLastTimestamp requires manual conversion: does not exist in peer-type
// WARNING: in.DeprecatedCount requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_core_Event_To_v1beta1_Event(in *core.Event, out *v1beta1.Event, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
// WARNING: in.InvolvedObject requires manual conversion: does not exist in peer-type
out.Reason = in.Reason
// WARNING: in.Message requires manual conversion: does not exist in peer-type
// WARNING: in.Source requires manual conversion: does not exist in peer-type
// WARNING: in.FirstTimestamp requires manual conversion: does not exist in peer-type
// WARNING: in.LastTimestamp requires manual conversion: does not exist in peer-type
// WARNING: in.Count requires manual conversion: does not exist in peer-type
out.Type = in.Type
out.EventTime = in.EventTime
out.Series = (*v1beta1.EventSeries)(unsafe.Pointer(in.Series))
out.Action = in.Action
out.Related = (*v1.ObjectReference)(unsafe.Pointer(in.Related))
out.ReportingController = in.ReportingController
out.ReportingInstance = in.ReportingInstance
return nil
}
func autoConvert_v1beta1_EventList_To_core_EventList(in *v1beta1.EventList, out *core.EventList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]core.Event, len(*in))
for i := range *in {
if err := Convert_v1beta1_Event_To_core_Event(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
// Convert_v1beta1_EventList_To_core_EventList is an autogenerated conversion function.
func Convert_v1beta1_EventList_To_core_EventList(in *v1beta1.EventList, out *core.EventList, s conversion.Scope) error {
return autoConvert_v1beta1_EventList_To_core_EventList(in, out, s)
}
func autoConvert_core_EventList_To_v1beta1_EventList(in *core.EventList, out *v1beta1.EventList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1beta1.Event, len(*in))
for i := range *in {
if err := Convert_core_Event_To_v1beta1_Event(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
// Convert_core_EventList_To_v1beta1_EventList is an autogenerated conversion function.
func Convert_core_EventList_To_v1beta1_EventList(in *core.EventList, out *v1beta1.EventList, s conversion.Scope) error {
return autoConvert_core_EventList_To_v1beta1_EventList(in, out, s)
}
func autoConvert_v1beta1_EventSeries_To_core_EventSeries(in *v1beta1.EventSeries, out *core.EventSeries, s conversion.Scope) error {
out.Count = in.Count
out.LastObservedTime = in.LastObservedTime
out.State = core.EventSeriesState(in.State)
return nil
}
// Convert_v1beta1_EventSeries_To_core_EventSeries is an autogenerated conversion function.
func Convert_v1beta1_EventSeries_To_core_EventSeries(in *v1beta1.EventSeries, out *core.EventSeries, s conversion.Scope) error {
return autoConvert_v1beta1_EventSeries_To_core_EventSeries(in, out, s)
}
func autoConvert_core_EventSeries_To_v1beta1_EventSeries(in *core.EventSeries, out *v1beta1.EventSeries, s conversion.Scope) error {
out.Count = in.Count
out.LastObservedTime = in.LastObservedTime
out.State = v1beta1.EventSeriesState(in.State)
return nil
}
// Convert_core_EventSeries_To_v1beta1_EventSeries is an autogenerated conversion function.
func Convert_core_EventSeries_To_v1beta1_EventSeries(in *core.EventSeries, out *v1beta1.EventSeries, s conversion.Scope) error {
return autoConvert_core_EventSeries_To_v1beta1_EventSeries(in, out, s)
}

View File

@@ -0,0 +1,32 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by defaulter-gen. Do not edit it manually!
package v1beta1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
return nil
}

View File

@@ -21,6 +21,7 @@ go_library(
"//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:go_default_library",
@@ -56,6 +57,7 @@ filegroup(
"//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion:all-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:all-srcs",

View File

@@ -29,6 +29,7 @@ import (
batchinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion"
certificatesinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion"
coreinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
eventsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion"
extensionsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
networkinginternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion"
policyinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion"
@@ -48,6 +49,7 @@ type Interface interface {
Autoscaling() autoscalinginternalversion.AutoscalingInterface
Batch() batchinternalversion.BatchInterface
Certificates() certificatesinternalversion.CertificatesInterface
Events() eventsinternalversion.EventsInterface
Extensions() extensionsinternalversion.ExtensionsInterface
Networking() networkinginternalversion.NetworkingInterface
Policy() policyinternalversion.PolicyInterface
@@ -69,6 +71,7 @@ type Clientset struct {
autoscaling *autoscalinginternalversion.AutoscalingClient
batch *batchinternalversion.BatchClient
certificates *certificatesinternalversion.CertificatesClient
events *eventsinternalversion.EventsClient
extensions *extensionsinternalversion.ExtensionsClient
networking *networkinginternalversion.NetworkingClient
policy *policyinternalversion.PolicyClient
@@ -118,6 +121,11 @@ func (c *Clientset) Certificates() certificatesinternalversion.CertificatesInter
return c.certificates
}
// Events retrieves the EventsClient
func (c *Clientset) Events() eventsinternalversion.EventsInterface {
return c.events
}
// Extensions retrieves the ExtensionsClient
func (c *Clientset) Extensions() extensionsinternalversion.ExtensionsInterface {
return c.extensions
@@ -201,6 +209,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.events, err = eventsinternalversion.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.extensions, err = extensionsinternalversion.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@@ -250,6 +262,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
cs.autoscaling = autoscalinginternalversion.NewForConfigOrDie(c)
cs.batch = batchinternalversion.NewForConfigOrDie(c)
cs.certificates = certificatesinternalversion.NewForConfigOrDie(c)
cs.events = eventsinternalversion.NewForConfigOrDie(c)
cs.extensions = extensionsinternalversion.NewForConfigOrDie(c)
cs.networking = networkinginternalversion.NewForConfigOrDie(c)
cs.policy = policyinternalversion.NewForConfigOrDie(c)
@@ -273,6 +286,7 @@ func New(c rest.Interface) *Clientset {
cs.autoscaling = autoscalinginternalversion.New(c)
cs.batch = batchinternalversion.New(c)
cs.certificates = certificatesinternalversion.New(c)
cs.events = eventsinternalversion.New(c)
cs.extensions = extensionsinternalversion.New(c)
cs.networking = networkinginternalversion.New(c)
cs.policy = policyinternalversion.New(c)

View File

@@ -22,6 +22,7 @@ go_library(
"//pkg/apis/batch:go_default_library",
"//pkg/apis/certificates:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/events:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/networking:go_default_library",
"//pkg/apis/policy:go_default_library",
@@ -46,6 +47,8 @@ go_library(
"//pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/networking/internalversion:go_default_library",

View File

@@ -39,6 +39,8 @@ import (
fakecertificatesinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake"
coreinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
fakecoreinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake"
eventsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion"
fakeeventsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake"
extensionsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
fakeextensionsinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake"
networkinginternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/networking/internalversion"
@@ -128,6 +130,11 @@ func (c *Clientset) Certificates() certificatesinternalversion.CertificatesInter
return &fakecertificatesinternalversion.FakeCertificates{Fake: &c.Fake}
}
// Events retrieves the EventsClient
func (c *Clientset) Events() eventsinternalversion.EventsInterface {
return &fakeeventsinternalversion.FakeEvents{Fake: &c.Fake}
}
// Extensions retrieves the ExtensionsClient
func (c *Clientset) Extensions() extensionsinternalversion.ExtensionsInterface {
return &fakeextensionsinternalversion.FakeExtensions{Fake: &c.Fake}

View File

@@ -29,6 +29,7 @@ import (
batchinternalversion "k8s.io/kubernetes/pkg/apis/batch"
certificatesinternalversion "k8s.io/kubernetes/pkg/apis/certificates"
coreinternalversion "k8s.io/kubernetes/pkg/apis/core"
eventsinternalversion "k8s.io/kubernetes/pkg/apis/events"
extensionsinternalversion "k8s.io/kubernetes/pkg/apis/extensions"
networkinginternalversion "k8s.io/kubernetes/pkg/apis/networking"
policyinternalversion "k8s.io/kubernetes/pkg/apis/policy"
@@ -70,6 +71,7 @@ func AddToScheme(scheme *runtime.Scheme) {
autoscalinginternalversion.AddToScheme(scheme)
batchinternalversion.AddToScheme(scheme)
certificatesinternalversion.AddToScheme(scheme)
eventsinternalversion.AddToScheme(scheme)
extensionsinternalversion.AddToScheme(scheme)
networkinginternalversion.AddToScheme(scheme)
policyinternalversion.AddToScheme(scheme)

View File

@@ -23,6 +23,7 @@ go_library(
"//pkg/apis/certificates/install:go_default_library",
"//pkg/apis/componentconfig/install:go_default_library",
"//pkg/apis/core/install:go_default_library",
"//pkg/apis/events/install:go_default_library",
"//pkg/apis/extensions/install:go_default_library",
"//pkg/apis/networking/install:go_default_library",
"//pkg/apis/policy/install:go_default_library",

View File

@@ -31,6 +31,7 @@ import (
batch "k8s.io/kubernetes/pkg/apis/batch/install"
certificates "k8s.io/kubernetes/pkg/apis/certificates/install"
core "k8s.io/kubernetes/pkg/apis/core/install"
events "k8s.io/kubernetes/pkg/apis/events/install"
extensions "k8s.io/kubernetes/pkg/apis/extensions/install"
networking "k8s.io/kubernetes/pkg/apis/networking/install"
policy "k8s.io/kubernetes/pkg/apis/policy/install"
@@ -63,6 +64,7 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r
autoscaling.Install(groupFactoryRegistry, registry, scheme)
batch.Install(groupFactoryRegistry, registry, scheme)
certificates.Install(groupFactoryRegistry, registry, scheme)
events.Install(groupFactoryRegistry, registry, scheme)
extensions.Install(groupFactoryRegistry, registry, scheme)
networking.Install(groupFactoryRegistry, registry, scheme)
policy.Install(groupFactoryRegistry, registry, scheme)

View File

@@ -0,0 +1,33 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"events_client.go",
"generated_expansion.go",
],
importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion",
visibility = ["//visibility:public"],
deps = [
"//pkg/client/clientset_generated/internalclientset/scheme:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,18 @@
/*
Copyright 2017 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.
*/
// This package has the automatically generated typed clients.
package internalversion

View File

@@ -0,0 +1,94 @@
/*
Copyright 2017 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 internalversion
import (
rest "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme"
)
type EventsInterface interface {
RESTClient() rest.Interface
}
// EventsClient is used to interact with features provided by the events.k8s.io group.
type EventsClient struct {
restClient rest.Interface
}
// NewForConfig creates a new EventsClient for the given config.
func NewForConfig(c *rest.Config) (*EventsClient, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &EventsClient{client}, nil
}
// NewForConfigOrDie creates a new EventsClient for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *EventsClient {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new EventsClient for the given RESTClient.
func New(c rest.Interface) *EventsClient {
return &EventsClient{c}
}
func setConfigDefaults(config *rest.Config) error {
g, err := scheme.Registry.Group("events.k8s.io")
if err != nil {
return err
}
config.APIPath = "/apis"
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group {
gv := g.GroupVersion
config.GroupVersion = &gv
}
config.NegotiatedSerializer = scheme.Codecs
if config.QPS == 0 {
config.QPS = 5
}
if config.Burst == 0 {
config.Burst = 10
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *EventsClient) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@@ -0,0 +1,29 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"fake_events_client.go",
],
importpath = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/events/internalversion/fake",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/testing:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,18 @@
/*
Copyright 2017 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 fake has the automatically generated clients.
package fake

View File

@@ -0,0 +1,33 @@
/*
Copyright 2017 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 fake
import (
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeEvents struct {
*testing.Fake
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeEvents) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -0,0 +1,17 @@
/*
Copyright 2017 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 internalversion

View File

@@ -559,14 +559,14 @@ func (gc *GarbageCollector) attemptToOrphanWorker() bool {
err := gc.orphanDependents(owner.identity, dependents)
if err != nil {
glog.V(5).Infof("orphanDependents for %s failed with %v", owner.identity, err)
utilruntime.HandleError(fmt.Errorf("orphanDependents for %s failed with %v", owner.identity, err))
gc.attemptToOrphan.AddRateLimited(item)
return true
}
// update the owner, remove "orphaningFinalizer" from its finalizers list
err = gc.removeFinalizer(owner, metav1.FinalizerOrphanDependents)
if err != nil {
glog.V(5).Infof("removeOrphanFinalizer for %s failed with %v", owner.identity, err)
utilruntime.HandleError(fmt.Errorf("removeOrphanFinalizer for %s failed with %v", owner.identity, err))
gc.attemptToOrphan.AddRateLimited(item)
}
return true

View File

@@ -13,7 +13,10 @@ go_library(
"fieldpath.go",
],
importpath = "k8s.io/kubernetes/pkg/fieldpath",
deps = ["//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
],
)
go_test(

View File

@@ -21,6 +21,7 @@ import (
"strings"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/util/validation"
)
// FormatMap formats map[string]string to a string.
@@ -42,6 +43,23 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error)
return "", nil
}
if path, subscript, ok := SplitMaybeSubscriptedPath(fieldPath); ok {
switch path {
case "metadata.annotations":
if errs := validation.IsQualifiedName(strings.ToLower(subscript)); len(errs) != 0 {
return "", fmt.Errorf("invalid key subscript in %s: %s", fieldPath, strings.Join(errs, ";"))
}
return accessor.GetAnnotations()[subscript], nil
case "metadata.labels":
if errs := validation.IsQualifiedName(subscript); len(errs) != 0 {
return "", fmt.Errorf("invalid key subscript in %s: %s", fieldPath, strings.Join(errs, ";"))
}
return accessor.GetLabels()[subscript], nil
default:
return "", fmt.Errorf("fieldPath %q does not support subscript", fieldPath)
}
}
switch fieldPath {
case "metadata.annotations":
return FormatMap(accessor.GetAnnotations()), nil
@@ -57,3 +75,29 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error)
return "", fmt.Errorf("unsupported fieldPath: %v", fieldPath)
}
// SplitMaybeSubscriptedPath checks whether the specified fieldPath is
// subscripted, and
// - if yes, this function splits the fieldPath into path and subscript, and
// returns (path, subscript, true).
// - if no, this function returns (fieldPath, "", false).
//
// Example inputs and outputs:
// - "metadata.annotations['myKey']" --> ("metadata.annotations", "myKey", true)
// - "metadata.annotations['a[b]c']" --> ("metadata.annotations", "a[b]c", true)
// - "metadata.labels['']" --> ("metadata.labels", "", true)
// - "metadata.labels" --> ("metadata.labels", "", false)
func SplitMaybeSubscriptedPath(fieldPath string) (string, string, bool) {
if !strings.HasSuffix(fieldPath, "']") {
return fieldPath, "", false
}
s := strings.TrimSuffix(fieldPath, "']")
parts := strings.SplitN(s, "['", 2)
if len(parts) < 2 {
return fieldPath, "", false
}
if len(parts[0]) == 0 {
return fieldPath, "", false
}
return parts[0], parts[1], true
}

View File

@@ -36,7 +36,6 @@ func TestExtractFieldPathAsString(t *testing.T) {
name: "not an API object",
fieldPath: "metadata.name",
obj: "",
expectedMessageFragment: "expected struct",
},
{
name: "ok - namespace",
@@ -88,7 +87,26 @@ func TestExtractFieldPathAsString(t *testing.T) {
},
expectedValue: "builder=\"john-doe\"",
},
{
name: "ok - annotation",
fieldPath: "metadata.annotations['spec.pod.beta.kubernetes.io/statefulset-index']",
obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{"spec.pod.beta.kubernetes.io/statefulset-index": "1"},
},
},
expectedValue: "1",
},
{
name: "ok - annotation",
fieldPath: "metadata.annotations['Www.k8s.io/test']",
obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{"Www.k8s.io/test": "1"},
},
},
expectedValue: "1",
},
{
name: "invalid expression",
fieldPath: "metadata.whoops",
@@ -99,6 +117,26 @@ func TestExtractFieldPathAsString(t *testing.T) {
},
expectedMessageFragment: "unsupported fieldPath",
},
{
name: "invalid annotation key",
fieldPath: "metadata.annotations['invalid~key']",
obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{"foo": "bar"},
},
},
expectedMessageFragment: "invalid key subscript in metadata.annotations",
},
{
name: "invalid label key",
fieldPath: "metadata.labels['Www.k8s.io/test']",
obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{"foo": "bar"},
},
},
expectedMessageFragment: "invalid key subscript in metadata.labels",
},
}
for _, tc := range cases {
@@ -111,8 +149,93 @@ func TestExtractFieldPathAsString(t *testing.T) {
} else {
t.Errorf("%v: unexpected error: %v", tc.name, err)
}
} else if tc.expectedMessageFragment != "" {
t.Errorf("%v: expected error: %v", tc.name, tc.expectedMessageFragment)
} else if e := tc.expectedValue; e != "" && e != actual {
t.Errorf("%v: unexpected result; got %q, expected %q", tc.name, actual, e)
}
}
}
func TestSplitMaybeSubscriptedPath(t *testing.T) {
cases := []struct {
fieldPath string
expectedPath string
expectedSubscript string
expectedOK bool
}{
{
fieldPath: "metadata.annotations['key']",
expectedPath: "metadata.annotations",
expectedSubscript: "key",
expectedOK: true,
},
{
fieldPath: "metadata.annotations['a[b']c']",
expectedPath: "metadata.annotations",
expectedSubscript: "a[b']c",
expectedOK: true,
},
{
fieldPath: "metadata.labels['['key']",
expectedPath: "metadata.labels",
expectedSubscript: "['key",
expectedOK: true,
},
{
fieldPath: "metadata.labels['key']']",
expectedPath: "metadata.labels",
expectedSubscript: "key']",
expectedOK: true,
},
{
fieldPath: "metadata.labels['']",
expectedPath: "metadata.labels",
expectedSubscript: "",
expectedOK: true,
},
{
fieldPath: "metadata.labels[' ']",
expectedPath: "metadata.labels",
expectedSubscript: " ",
expectedOK: true,
},
{
fieldPath: "metadata.labels[ 'key' ]",
expectedOK: false,
},
{
fieldPath: "metadata.labels[]",
expectedOK: false,
},
{
fieldPath: "metadata.labels[']",
expectedOK: false,
},
{
fieldPath: "metadata.labels['key']foo",
expectedOK: false,
},
{
fieldPath: "['key']",
expectedOK: false,
},
{
fieldPath: "metadata.labels",
expectedOK: false,
},
}
for _, tc := range cases {
path, subscript, ok := SplitMaybeSubscriptedPath(tc.fieldPath)
if !ok {
if tc.expectedOK {
t.Errorf("SplitMaybeSubscriptedPath(%q) expected to return (_, _, true)", tc.fieldPath)
}
continue
}
if path != tc.expectedPath || subscript != tc.expectedSubscript {
t.Errorf("SplitMaybeSubscriptedPath(%q) = (%q, %q, true), expect (%q, %q, true)",
tc.fieldPath, path, subscript, tc.expectedPath, tc.expectedSubscript)
}
}
}

View File

@@ -38,6 +38,7 @@ openapi_library(
"k8s.io/api/batch/v2alpha1",
"k8s.io/api/certificates/v1beta1",
"k8s.io/api/core/v1",
"k8s.io/api/events/v1beta1",
"k8s.io/api/extensions/v1beta1",
"k8s.io/api/imagepolicy/v1alpha1",
"k8s.io/api/networking/v1",

View File

@@ -29,10 +29,10 @@ go_library(
],
importpath = "k8s.io/kubernetes/pkg/kubelet",
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/api/v1/pod:go_default_library",
"//pkg/api/v1/resource:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/pods:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/apis/core/v1/helper/qos:go_default_library",

View File

@@ -101,8 +101,6 @@ go_test(
"//conditions:default": [],
}),
data = [
"fixtures/seccomp/sub/subtest",
"fixtures/seccomp/test",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/dockershim",
library = ":go_default_library",

View File

@@ -1,3 +0,0 @@
{
"abc": "def"
}

View File

@@ -1,3 +0,0 @@
{
"foo": "bar"
}

View File

@@ -62,7 +62,11 @@ func getSeccompDockerOpts(seccompProfile string) ([]dockerOpt, error) {
return nil, fmt.Errorf("unknown seccomp profile option: %s", seccompProfile)
}
fname := strings.TrimPrefix(seccompProfile, "localhost/") // by pod annotation validation, name is a valid subpath
// get the full path of seccomp profile when prefixed with 'localhost/'.
fname := strings.TrimPrefix(seccompProfile, "localhost/")
if !filepath.IsAbs(fname) {
return nil, fmt.Errorf("seccomp profile path must be absolute, but got relative path %q", fname)
}
file, err := ioutil.ReadFile(filepath.FromSlash(fname))
if err != nil {
return nil, fmt.Errorf("cannot load seccomp profile %q: %v", fname, err)

View File

@@ -20,9 +20,13 @@ package dockershim
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetSeccompSecurityOpts(t *testing.T) {
@@ -55,26 +59,31 @@ func TestGetSeccompSecurityOpts(t *testing.T) {
}
func TestLoadSeccompLocalhostProfiles(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "seccomp-local-profile-test")
require.NoError(t, err)
defer os.RemoveAll(tmpdir)
testProfile := `{"foo": "bar"}`
err = ioutil.WriteFile(filepath.Join(tmpdir, "test"), []byte(testProfile), 0644)
require.NoError(t, err)
tests := []struct {
msg string
seccompProfile string
expectedOpts []string
expectErr bool
}{{
msg: "Seccomp localhost/test profile",
// We are abusing localhost for loading test seccomp profiles.
// The profile should be an absolute path while we are using a relative one.
seccompProfile: "localhost/fixtures/seccomp/test",
msg: "Seccomp localhost/test profile should return correct seccomp profiles",
seccompProfile: "localhost/" + filepath.Join(tmpdir, "test"),
expectedOpts: []string{`seccomp={"foo":"bar"}`},
expectErr: false,
}, {
msg: "Seccomp localhost/sub/subtest profile",
seccompProfile: "localhost/fixtures/seccomp/sub/subtest",
expectedOpts: []string{`seccomp={"abc":"def"}`},
expectErr: false,
msg: "Non-existent profile should return error",
seccompProfile: "localhost/" + filepath.Join(tmpdir, "fixtures/non-existent"),
expectedOpts: nil,
expectErr: true,
}, {
msg: "Seccomp non-existent",
seccompProfile: "localhost/fixtures/seccomp/non-existent",
msg: "Relative profile path should return error",
seccompProfile: "localhost/fixtures/test",
expectedOpts: nil,
expectErr: true,
}}

View File

@@ -43,9 +43,9 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/tools/remotecommand"
"k8s.io/kubernetes/pkg/api/legacyscheme"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
"k8s.io/kubernetes/pkg/api/v1/resource"
podshelper "k8s.io/kubernetes/pkg/apis/core/pods"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
"k8s.io/kubernetes/pkg/apis/core/v1/validation"
@@ -777,7 +777,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
// podFieldSelectorRuntimeValue returns the runtime value of the given
// selector for a pod.
func (kl *Kubelet) podFieldSelectorRuntimeValue(fs *v1.ObjectFieldSelector, pod *v1.Pod, podIP string) (string, error) {
internalFieldPath, _, err := legacyscheme.Scheme.ConvertFieldLabel(fs.APIVersion, "Pod", fs.FieldPath, "")
internalFieldPath, _, err := podshelper.ConvertDownwardAPIFieldLabel(fs.APIVersion, fs.FieldPath, "")
if err != nil {
return "", err
}

View File

@@ -33,6 +33,10 @@ import (
proberesults "k8s.io/kubernetes/pkg/kubelet/prober/results"
)
const (
fakeSeccompProfileRoot = "/fakeSeccompProfileRoot"
)
type fakeHTTP struct {
url string
err error
@@ -78,6 +82,7 @@ func NewFakeKubeRuntimeManager(runtimeService internalapi.RuntimeService, imageS
runtimeService: runtimeService,
imageService: imageService,
keyring: keyring,
seccompProfileRoot: fakeSeccompProfileRoot,
internalLifecycle: cm.NewFakeInternalContainerLifecycle(),
}

View File

@@ -273,7 +273,7 @@ func (m *kubeGenericRuntimeManager) getSeccompProfileFromAnnotations(annotations
if strings.HasPrefix(profile, "localhost/") {
name := strings.TrimPrefix(profile, "localhost/")
fname := filepath.Join(m.seccompProfileRoot, filepath.FromSlash(name))
return fname
return "localhost/" + fname
}
return profile

View File

@@ -17,9 +17,12 @@ limitations under the License.
package kuberuntime
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimetesting "k8s.io/kubernetes/pkg/kubelet/apis/cri/testing"
@@ -205,3 +208,100 @@ func TestGetImageUser(t *testing.T) {
assert.Equal(t, test.expectedImageUserValues.username, username, "TestCase[%d]", j)
}
}
func TestGetSeccompProfileFromAnnotations(t *testing.T) {
_, _, m, err := createTestRuntimeManager()
require.NoError(t, err)
tests := []struct {
description string
annotation map[string]string
containerName string
expectedProfile string
}{
{
description: "no seccomp should return empty string",
expectedProfile: "",
},
{
description: "no seccomp with containerName should return exmpty string",
containerName: "container1",
expectedProfile: "",
},
{
description: "pod docker/default seccomp profile should return docker/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "docker/default",
},
expectedProfile: "docker/default",
},
{
description: "pod docker/default seccomp profile with containerName should return docker/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "docker/default",
},
containerName: "container1",
expectedProfile: "docker/default",
},
{
description: "pod unconfined seccomp profile should return unconfined",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "unconfined",
},
expectedProfile: "unconfined",
},
{
description: "pod unconfined seccomp profile with containerName should return unconfined",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "unconfined",
},
containerName: "container1",
expectedProfile: "unconfined",
},
{
description: "pod localhost seccomp profile should return local profile path",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/chmod.json",
},
expectedProfile: "localhost/" + filepath.Join(fakeSeccompProfileRoot, "chmod.json"),
},
{
description: "pod localhost seccomp profile with containerName should return local profile path",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: "localhost/" + filepath.Join(fakeSeccompProfileRoot, "chmod.json"),
},
{
description: "container localhost seccomp profile with containerName should return local profile path",
annotation: map[string]string{
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: "localhost/" + filepath.Join(fakeSeccompProfileRoot, "chmod.json"),
},
{
description: "container localhost seccomp profile should override pod profile",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "unconfined",
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: "localhost/" + filepath.Join(fakeSeccompProfileRoot, "chmod.json"),
},
{
description: "container localhost seccomp profile with unmatched containerName should return empty string",
annotation: map[string]string{
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container2",
expectedProfile: "",
},
}
for i, test := range tests {
seccompProfile := m.getSeccompProfileFromAnnotations(test.annotation, test.containerName)
assert.Equal(t, test.expectedProfile, seccompProfile, "TestCase[%d]", i)
}
}

View File

@@ -30,6 +30,7 @@ go_library(
"//pkg/apis/componentconfig/install:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/install:go_default_library",
"//pkg/apis/events/install:go_default_library",
"//pkg/apis/extensions/install:go_default_library",
"//pkg/apis/imagepolicy/install:go_default_library",
"//pkg/apis/networking/install:go_default_library",
@@ -57,6 +58,7 @@ go_library(
"//pkg/registry/core/service/ipallocator:go_default_library",
"//pkg/registry/core/service/ipallocator/controller:go_default_library",
"//pkg/registry/core/service/portallocator/controller:go_default_library",
"//pkg/registry/events/rest:go_default_library",
"//pkg/registry/extensions/rest:go_default_library",
"//pkg/registry/networking/rest:go_default_library",
"//pkg/registry/policy/rest:go_default_library",
@@ -82,6 +84,7 @@ go_library(
"//vendor/k8s.io/api/batch/v1beta1:go_default_library",
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/events/v1beta1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/api/networking/v1:go_default_library",
"//vendor/k8s.io/api/policy/v1beta1:go_default_library",

View File

@@ -32,6 +32,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/core/install"
_ "k8s.io/kubernetes/pkg/apis/events/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
_ "k8s.io/kubernetes/pkg/apis/networking/install"

View File

@@ -37,6 +37,7 @@ import (
batchapiv1beta1 "k8s.io/api/batch/v1beta1"
certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1"
apiv1 "k8s.io/api/core/v1"
eventsv1beta1 "k8s.io/api/events/v1beta1"
extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1"
networkingapiv1 "k8s.io/api/networking/v1"
policyapiv1beta1 "k8s.io/api/policy/v1beta1"
@@ -77,6 +78,7 @@ import (
batchrest "k8s.io/kubernetes/pkg/registry/batch/rest"
certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest"
corerest "k8s.io/kubernetes/pkg/registry/core/rest"
eventsrest "k8s.io/kubernetes/pkg/registry/events/rest"
extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest"
networkingrest "k8s.io/kubernetes/pkg/registry/networking/rest"
policyrest "k8s.io/kubernetes/pkg/registry/policy/rest"
@@ -350,6 +352,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
// See https://github.com/kubernetes/kubernetes/issues/42392
appsrest.RESTStorageProvider{},
admissionregistrationrest.RESTStorageProvider{},
eventsrest.RESTStorageProvider{TTL: c.ExtraConfig.EventTTL},
}
m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...)
@@ -479,6 +482,7 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig {
authorizationapiv1.SchemeGroupVersion,
authorizationapiv1beta1.SchemeGroupVersion,
networkingapiv1.SchemeGroupVersion,
eventsv1beta1.SchemeGroupVersion,
)
// all extensions resources except these are disabled by default

View File

@@ -63,6 +63,8 @@ filegroup(
"//pkg/registry/core/secret:all-srcs",
"//pkg/registry/core/service:all-srcs",
"//pkg/registry/core/serviceaccount:all-srcs",
"//pkg/registry/events/event:all-srcs",
"//pkg/registry/events/rest:all-srcs",
"//pkg/registry/extensions/controller/storage:all-srcs",
"//pkg/registry/extensions/daemonset:all-srcs",
"//pkg/registry/extensions/deployment:all-srcs",

View File

@@ -19,11 +19,14 @@ go_library(
"//pkg/api/pod:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/apps/validation:go_default_library",
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",

View File

@@ -17,8 +17,11 @@ limitations under the License.
package statefulset
import (
appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
@@ -38,9 +41,18 @@ type statefulSetStrategy struct {
// Strategy is the default logic that applies when creating and updating Replication StatefulSet objects.
var Strategy = statefulSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
// DefaultGarbageCollectionPolicy returns Orphan because that was the default
// behavior before the server-side garbage collection was implemented.
func (statefulSetStrategy) DefaultGarbageCollectionPolicy() rest.GarbageCollectionPolicy {
// DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents.
func (statefulSetStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy {
if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found {
groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion}
switch groupVersion {
case appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion:
// for back compatibility
return rest.OrphanDependents
default:
return rest.DeleteDependents
}
}
return rest.OrphanDependents
}

View File

@@ -91,12 +91,59 @@ func TestStatefulSetStrategy(t *testing.T) {
if len(errs) == 0 {
t.Errorf("expected a validation error since updates are disallowed on statefulsets.")
}
}
func TestStatefulsetDefaultGarbageCollectionPolicy(t *testing.T) {
// Make sure we correctly implement the interface.
// Otherwise a typo could silently change the default.
var gcds rest.GarbageCollectionDeleteStrategy = Strategy
if got, want := gcds.DefaultGarbageCollectionPolicy(), rest.OrphanDependents; got != want {
t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want)
tests := []struct {
requestInfo genericapirequest.RequestInfo
expectedGCPolicy rest.GarbageCollectionPolicy
isNilRequestInfo bool
}{
{
genericapirequest.RequestInfo{
APIGroup: "apps",
APIVersion: "v1beta1",
Resource: "statefulsets",
},
rest.OrphanDependents,
false,
},
{
genericapirequest.RequestInfo{
APIGroup: "apps",
APIVersion: "v1beta2",
Resource: "statefulsets",
},
rest.OrphanDependents,
false,
},
{
genericapirequest.RequestInfo{
APIGroup: "apps",
APIVersion: "v1",
Resource: "statefulsets",
},
rest.DeleteDependents,
false,
},
{
expectedGCPolicy: rest.OrphanDependents,
isNilRequestInfo: true,
},
}
for _, test := range tests {
context := genericapirequest.NewContext()
if !test.isNilRequestInfo {
context = genericapirequest.WithRequestInfo(context, &test.requestInfo)
}
if got, want := gcds.DefaultGarbageCollectionPolicy(context), test.expectedGCPolicy; got != want {
t.Errorf("%s/%s: DefaultGarbageCollectionPolicy() = %#v, want %#v", test.requestInfo.APIGroup,
test.requestInfo.APIVersion, got, want)
}
}
}

View File

@@ -39,7 +39,7 @@ var Strategy = cronJobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
// DefaultGarbageCollectionPolicy returns Orphan because that was the default
// behavior before the server-side garbage collection was implemented.
func (cronJobStrategy) DefaultGarbageCollectionPolicy() rest.GarbageCollectionPolicy {
func (cronJobStrategy) DefaultGarbageCollectionPolicy(ctx genericapirequest.Context) rest.GarbageCollectionPolicy {
return rest.OrphanDependents
}

Some files were not shown because too many files have changed in this diff Show More