mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-28 14:41:10 +01:00
Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6af54ab30 | ||
|
|
e41ef8cca3 | ||
|
|
d26cd4b317 | ||
|
|
f7d0acb731 | ||
|
|
f1f8b2eaa7 | ||
|
|
0a7f14d75e | ||
|
|
de76f9b14c | ||
|
|
8b84bb26ff | ||
|
|
bb25192163 | ||
|
|
40bb490f4c | ||
|
|
08729f6ef9 | ||
|
|
3dd7de8132 | ||
|
|
471aeb5ea4 | ||
|
|
65e7093ee7 | ||
|
|
fc0cd4ba30 | ||
|
|
ba3eac6c57 | ||
|
|
11a95ce8fb | ||
|
|
29a9fc6b56 | ||
|
|
d3c2f25685 | ||
|
|
e858c9ee80 | ||
|
|
44752e5e83 | ||
|
|
7123f30783 | ||
|
|
a82cf7cea4 | ||
|
|
72318868b0 | ||
|
|
589fb95236 | ||
|
|
7df543d137 | ||
|
|
1d7f429ba1 | ||
|
|
bf29a6073f | ||
|
|
65635bdb2e | ||
|
|
fd961557d0 | ||
|
|
c29bdc1dbe | ||
|
|
ffecc54bf5 | ||
|
|
f6f6fbab10 | ||
|
|
12c217477c | ||
|
|
20a4798465 | ||
|
|
a201f222e5 | ||
|
|
6e705fde85 | ||
|
|
5763554be4 | ||
|
|
6f873d5e69 | ||
|
|
445ae92caa | ||
|
|
8f3c0cf4b8 | ||
|
|
2a280f9a20 | ||
|
|
0503f53904 | ||
|
|
e0a9dfcb76 | ||
|
|
5db49f2ce1 | ||
|
|
582bd67681 | ||
|
|
a63f815116 | ||
|
|
afc17a62ea | ||
|
|
6dbc8a1fcc | ||
|
|
d2bd16a12d | ||
|
|
955d0eb228 | ||
|
|
a490726245 | ||
|
|
16a504fb87 | ||
|
|
d54b73a6ba | ||
|
|
344dc0f3c2 | ||
|
|
9f38146bbf | ||
|
|
1473e1d024 | ||
|
|
7b4b9d9e7e | ||
|
|
7d079813e5 | ||
|
|
e02857e00a | ||
|
|
acfd4f8680 | ||
|
|
c29c9db41e | ||
|
|
5d3f987dde | ||
|
|
97732cf62d | ||
|
|
4afc4dfb16 | ||
|
|
023ccd99f5 | ||
|
|
dd831d0d03 | ||
|
|
04dd7a5902 | ||
|
|
d395332793 | ||
|
|
73d9803a46 | ||
|
|
40a19396d0 | ||
|
|
10593fa427 | ||
|
|
257312929e | ||
|
|
6aa10f2169 | ||
|
|
9e536da99e | ||
|
|
b272dbec29 | ||
|
|
70e45297bc | ||
|
|
8007f4af20 | ||
|
|
32c8898ec7 |
@@ -2,5 +2,6 @@ language: go
|
|||||||
go:
|
go:
|
||||||
- 1.8.3
|
- 1.8.3
|
||||||
script:
|
script:
|
||||||
|
- hack/verify-gofmt.sh
|
||||||
- make build
|
- make build
|
||||||
- make test
|
- make test-unit
|
||||||
|
|||||||
12
Dockerfile
12
Dockerfile
@@ -11,10 +11,16 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
FROM golang:1.9.2
|
||||||
|
|
||||||
FROM fedora
|
WORKDIR /go/src/github.com/kubernetes-incubator/descheduler
|
||||||
|
COPY . .
|
||||||
|
RUN make
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
MAINTAINER Avesh Agarwal <avagarwa@redhat.com>
|
MAINTAINER Avesh Agarwal <avagarwa@redhat.com>
|
||||||
|
|
||||||
COPY _output/bin/descheduler /bin/descheduler
|
COPY --from=0 /go/src/github.com/kubernetes-incubator/descheduler/_output/bin/descheduler /bin/descheduler
|
||||||
CMD ["/bin/descheduler --help"]
|
|
||||||
|
CMD ["/bin/descheduler", "--help"]
|
||||||
|
|||||||
20
Dockerfile.dev
Normal file
20
Dockerfile.dev
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# 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.
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
MAINTAINER Avesh Agarwal <avagarwa@redhat.com>
|
||||||
|
|
||||||
|
COPY _output/bin/descheduler /bin/descheduler
|
||||||
|
|
||||||
|
CMD ["/bin/descheduler", "--help"]
|
||||||
27
Makefile
27
Makefile
@@ -15,21 +15,40 @@
|
|||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
||||||
# VERSION is currently based on the last commit
|
# VERSION is currently based on the last commit
|
||||||
VERSION:=$(shell git rev-parse --short HEAD)
|
VERSION=`git describe --tags`
|
||||||
|
COMMIT=`git rev-parse HEAD`
|
||||||
|
BUILD=`date +%FT%T%z`
|
||||||
|
LDFLAG_LOCATION=github.com/kubernetes-incubator/descheduler/cmd/descheduler/app
|
||||||
|
|
||||||
|
LDFLAGS=-ldflags "-X ${LDFLAG_LOCATION}.version=${VERSION} -X ${LDFLAG_LOCATION}.buildDate=${BUILD} -X ${LDFLAG_LOCATION}.gitCommit=${COMMIT}"
|
||||||
|
|
||||||
|
|
||||||
# IMAGE is the image name of descheduler
|
# IMAGE is the image name of descheduler
|
||||||
|
# Should this be changed?
|
||||||
IMAGE:=descheduler:$(VERSION)
|
IMAGE:=descheduler:$(VERSION)
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -o _output/bin/descheduler github.com/kubernetes-incubator/descheduler/cmd/descheduler
|
CGO_ENABLED=0 go build ${LDFLAGS} -o _output/bin/descheduler github.com/kubernetes-incubator/descheduler/cmd/descheduler
|
||||||
|
|
||||||
image: build
|
dev-image: build
|
||||||
|
docker build -f Dockerfile.dev -t $(IMAGE) .
|
||||||
|
|
||||||
|
image:
|
||||||
docker build -t $(IMAGE) .
|
docker build -t $(IMAGE) .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf _output
|
rm -rf _output
|
||||||
|
|
||||||
test:
|
test-unit:
|
||||||
./test/run-unit-tests.sh
|
./test/run-unit-tests.sh
|
||||||
|
|
||||||
|
test-e2e:
|
||||||
|
./test/run-e2e-tests.sh
|
||||||
|
|
||||||
|
gen:
|
||||||
|
./hack/update-codecgen.sh
|
||||||
|
./hack/update-generated-conversions.sh
|
||||||
|
./hack/update-generated-deep-copies.sh
|
||||||
|
./hack/update-generated-defaulters.sh
|
||||||
|
|||||||
8
OWNERS
Normal file
8
OWNERS
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
approvers:
|
||||||
|
- aveshagarwal
|
||||||
|
- ravisantoshgudimetla
|
||||||
|
- jayunit100
|
||||||
|
reviewers:
|
||||||
|
- aveshagarwal
|
||||||
|
- ravisantoshgudimetla
|
||||||
|
- jayunit100
|
||||||
161
README.md
161
README.md
@@ -1,3 +1,6 @@
|
|||||||
|
[](https://travis-ci.org/kubernetes-incubator/descheduler)
|
||||||
|
[](https://goreportcard.com/report/github.com/kubernetes-incubator/descheduler)
|
||||||
|
|
||||||
# Descheduler for Kubernetes
|
# Descheduler for Kubernetes
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
@@ -40,10 +43,126 @@ For more information about available options run:
|
|||||||
$ ./_output/bin/descheduler --help
|
$ ./_output/bin/descheduler --help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Running Descheduler as a Job Inside of a Pod
|
||||||
|
|
||||||
|
Descheduler can be run as a job inside of a pod. It has the advantage of
|
||||||
|
being able to be run multiple times without needing user intervention.
|
||||||
|
Descheduler pod is run as a critical pod to avoid being evicted by itself,
|
||||||
|
or by kubelet due to an eviction event. Since critical pods are created in
|
||||||
|
`kube-system` namespace, descheduler job and its pod will also be created
|
||||||
|
in `kube-system` namespace.
|
||||||
|
|
||||||
|
### Create a container image
|
||||||
|
|
||||||
|
First we create a simple Docker image utilizing the Dockerfile found in the root directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make dev-image
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates an image based off the binary we've built before. To build both the
|
||||||
|
binary and image in one step you can run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make image
|
||||||
|
```
|
||||||
|
|
||||||
|
This eliminates the need to have Go installed locally and builds the binary
|
||||||
|
within it's own container.
|
||||||
|
|
||||||
|
### Create a cluster role
|
||||||
|
|
||||||
|
To give necessary permissions for the descheduler to work in a pod, create a cluster role:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat << EOF| kubectl create -f -
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: descheduler-cluster-role
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["nodes"]
|
||||||
|
verbs: ["get", "watch", "list"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "watch", "list", "delete"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods/eviction"]
|
||||||
|
verbs: ["create"]
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create the service account which will be used to run the job:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ kubectl create sa descheduler-sa -n kube-system
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bind the cluster role to the service account:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ kubectl create clusterrolebinding descheduler-cluster-role-binding \
|
||||||
|
--clusterrole=descheduler-cluster-role \
|
||||||
|
--serviceaccount=kube-system:descheduler-sa
|
||||||
|
```
|
||||||
|
### Create a configmap to store descheduler policy
|
||||||
|
|
||||||
|
Descheduler policy is created as a ConfigMap in `kube-system` namespace
|
||||||
|
so that it can be mounted as a volume inside pod.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ kubectl create configmap descheduler-policy-configmap \
|
||||||
|
-n kube-system --from-file=<path-to-policy-dir/policy.yaml>
|
||||||
|
```
|
||||||
|
### Create the job specification (descheduler-job.yaml)
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: descheduler-job
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
parallelism: 1
|
||||||
|
completions: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: descheduler-pod
|
||||||
|
annotations:
|
||||||
|
scheduler.alpha.kubernetes.io/critical-pod: "true"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: descheduler
|
||||||
|
image: descheduler
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /policy-dir
|
||||||
|
name: policy-volume
|
||||||
|
command:
|
||||||
|
- "/bin/sh"
|
||||||
|
- "-ec"
|
||||||
|
- |
|
||||||
|
/bin/descheduler --policy-config-file /policy-dir/policy.yaml
|
||||||
|
restartPolicy: "Never"
|
||||||
|
serviceAccountName: descheduler-sa
|
||||||
|
volumes:
|
||||||
|
- name: policy-volume
|
||||||
|
configMap:
|
||||||
|
name: descheduler-policy-configmap
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that the pod template is configured with critical pod annotation, and
|
||||||
|
the policy `policy-file` is mounted as a volume from the config map.
|
||||||
|
|
||||||
|
### Run the descheduler as a job in a pod:
|
||||||
|
```
|
||||||
|
$ kubectl create -f descheduler-job.yaml
|
||||||
|
```
|
||||||
|
|
||||||
## Policy and Strategies
|
## Policy and Strategies
|
||||||
|
|
||||||
Descheduler's policy is configurable and includes strategies to be enabled or disabled.
|
Descheduler's policy is configurable and includes strategies to be enabled or disabled.
|
||||||
Two strategies, `RemoveDuplicates` and `LowNodeUtilization` are currently implemented.
|
Four strategies, `RemoveDuplicates`, `LowNodeUtilization`, `RemovePodsViolatingInterPodAntiAffinity`, `RemovePodsViolatingNodeAffinity` are currently implemented.
|
||||||
As part of the policy, the parameters associated with the strategies can be configured too.
|
As part of the policy, the parameters associated with the strategies can be configured too.
|
||||||
By default, all strategies are enabled.
|
By default, all strategies are enabled.
|
||||||
|
|
||||||
@@ -55,7 +174,7 @@ those duplicate pods are evicted for better spreading of pods in a cluster. This
|
|||||||
if some nodes went down due to whatever reasons, and pods on them were moved to other nodes leading to
|
if some nodes went down due to whatever reasons, and pods on them were moved to other nodes leading to
|
||||||
more than one pod associated with RS or RC, for example, running on same node. Once the failed nodes
|
more than one pod associated with RS or RC, for example, running on same node. Once the failed nodes
|
||||||
are ready again, this strategy could be enabled to evict those duplicate pods. Currently, there are no
|
are ready again, this strategy could be enabled to evict those duplicate pods. Currently, there are no
|
||||||
parameters associated with this strategy. To disable this strategy, the policy would look like:
|
parameters associated with this strategy. To disable this strategy, the policy should look like:
|
||||||
|
|
||||||
```
|
```
|
||||||
apiVersion: "descheduler/v1alpha1"
|
apiVersion: "descheduler/v1alpha1"
|
||||||
@@ -107,6 +226,33 @@ This parameter can be configured to activate the strategy only when number of un
|
|||||||
are above the configured value. This could be helpful in large clusters where a few nodes could go
|
are above the configured value. This could be helpful in large clusters where a few nodes could go
|
||||||
under utilized frequently or for a short period of time. By default, `numberOfNodes` is set to zero.
|
under utilized frequently or for a short period of time. By default, `numberOfNodes` is set to zero.
|
||||||
|
|
||||||
|
### RemovePodsViolatingInterPodAntiAffinity
|
||||||
|
|
||||||
|
This strategy makes sure that pods violating interpod anti-affinity are removed from nodes. For example, if there is podA on node and podB and podC(running on same node) have antiaffinity rules which prohibit them to run on the same node, then podA will be evicted from the node so that podB and podC could run. This issue could happen, when the anti-affinity rules for pods B,C are created when they are already running on node. Currently, there are no parameters associated with this strategy. To disable this strategy, the policy should look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: "descheduler/v1alpha1"
|
||||||
|
kind: "DeschedulerPolicy"
|
||||||
|
strategies:
|
||||||
|
"RemovePodsViolatingInterPodAntiAffinity":
|
||||||
|
enabled: false
|
||||||
|
```
|
||||||
|
|
||||||
|
### RemovePodsViolatingNodeAffinity
|
||||||
|
|
||||||
|
This strategy makes sure that pods violating node affinity are removed from nodes. For example, there is podA that was scheduled on nodeA which satisfied the node affinity rule `requiredDuringSchedulingIgnoredDuringExecution` at the time of scheduling, but over time nodeA no longer satisfies the rule, then if another node nodeB is available that satisfies the node affinity rule, then podA will be evicted from nodeA. The policy file should like this -
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: "descheduler/v1alpha1"
|
||||||
|
kind: "DeschedulerPolicy"
|
||||||
|
strategies:
|
||||||
|
"RemovePodsViolatingNodeAffinity":
|
||||||
|
enabled: true
|
||||||
|
params:
|
||||||
|
nodeAffinityType:
|
||||||
|
- "requiredDuringSchedulingIgnoredDuringExecution"
|
||||||
|
```
|
||||||
|
|
||||||
## Pod Evictions
|
## Pod Evictions
|
||||||
|
|
||||||
When the descheduler decides to evict pods from a node, it employs following general mechanism:
|
When the descheduler decides to evict pods from a node, it employs following general mechanism:
|
||||||
@@ -126,10 +272,8 @@ disruption budget (PDB). The pods are evicted by using eviction subresource to h
|
|||||||
|
|
||||||
This roadmap is not in any particular order.
|
This roadmap is not in any particular order.
|
||||||
|
|
||||||
* Addition of test cases (unit and end-to-end)
|
|
||||||
* Ability to run inside a pod as a job
|
|
||||||
* Strategy to consider taints and tolerations
|
* Strategy to consider taints and tolerations
|
||||||
* Consideration of pod affinity and anti-affinity
|
* Consideration of pod affinity
|
||||||
* Strategy to consider pod life time
|
* Strategy to consider pod life time
|
||||||
* Strategy to consider number of pending pods
|
* Strategy to consider number of pending pods
|
||||||
* Integration with cluster autoscaler
|
* Integration with cluster autoscaler
|
||||||
@@ -137,6 +281,13 @@ This roadmap is not in any particular order.
|
|||||||
* Consideration of Kubernetes's scheduler's predicates
|
* Consideration of Kubernetes's scheduler's predicates
|
||||||
|
|
||||||
|
|
||||||
|
## Compatibility matrix
|
||||||
|
|
||||||
|
Descheduler | supported Kubernetes version
|
||||||
|
-------------|-----------------------------
|
||||||
|
0.4 | 1.9+
|
||||||
|
0.1-0.3 | 1.7-1.8
|
||||||
|
|
||||||
## Note
|
## Note
|
||||||
|
|
||||||
This project is under active development, and is not intended for production use.
|
This project is under active development, and is not intended for production use.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ limitations under the License.
|
|||||||
package options
|
package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
// install the componentconfig api so we get its defaulting and conversion functions
|
// install the componentconfig api so we get its defaulting and conversion functions
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/apis/componentconfig"
|
"github.com/kubernetes-incubator/descheduler/pkg/apis/componentconfig"
|
||||||
@@ -50,7 +50,11 @@ func NewDeschedulerServer() *DeschedulerServer {
|
|||||||
// AddFlags adds flags for a specific SchedulerServer to the specified FlagSet
|
// AddFlags adds flags for a specific SchedulerServer to the specified FlagSet
|
||||||
func (rs *DeschedulerServer) AddFlags(fs *pflag.FlagSet) {
|
func (rs *DeschedulerServer) AddFlags(fs *pflag.FlagSet) {
|
||||||
fs.DurationVar(&rs.DeschedulingInterval, "descheduling-interval", rs.DeschedulingInterval, "time interval between two consecutive descheduler executions")
|
fs.DurationVar(&rs.DeschedulingInterval, "descheduling-interval", rs.DeschedulingInterval, "time interval between two consecutive descheduler executions")
|
||||||
fs.StringVar(&rs.KubeconfigFile, "kubeconfig-file", rs.KubeconfigFile, "File with kube configuration.")
|
fs.StringVar(&rs.KubeconfigFile, "kubeconfig", rs.KubeconfigFile, "File with kube configuration.")
|
||||||
fs.StringVar(&rs.PolicyConfigFile, "policy-config-file", rs.PolicyConfigFile, "File with descheduler policy configuration.")
|
fs.StringVar(&rs.PolicyConfigFile, "policy-config-file", rs.PolicyConfigFile, "File with descheduler policy configuration.")
|
||||||
fs.BoolVar(&rs.DryRun, "dry-run", rs.DryRun, "execute descheduler in dry run mode.")
|
fs.BoolVar(&rs.DryRun, "dry-run", rs.DryRun, "execute descheduler in dry run mode.")
|
||||||
|
// node-selector query causes descheduler to run only on nodes that matches the node labels in the query
|
||||||
|
fs.StringVar(&rs.NodeSelector, "node-selector", rs.NodeSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||||
|
// max-no-pods-to-evict limits the maximum number of pods to be evicted per node by descheduler.
|
||||||
|
fs.IntVar(&rs.MaxNoOfPodsToEvictPerNode, "max-pods-to-evict-per-node", rs.MaxNoOfPodsToEvictPerNode, "Limits the maximum number of pods to be evicted per node by descheduler")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,32 +18,41 @@ limitations under the License.
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"flag"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/descheduler"
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
|
||||||
|
aflag "k8s.io/apiserver/pkg/util/flag"
|
||||||
|
"k8s.io/apiserver/pkg/util/logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDeschedulerCommand creates a *cobra.Command object with default parameters
|
// NewDeschedulerCommand creates a *cobra.Command object with default parameters
|
||||||
func NewDeschedulerCommand() *cobra.Command {
|
func NewDeschedulerCommand(out io.Writer) *cobra.Command {
|
||||||
s := options.NewDeschedulerServer()
|
s := options.NewDeschedulerServer()
|
||||||
s.AddFlags(pflag.CommandLine)
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "descheduler",
|
Use: "descheduler",
|
||||||
Short: "descheduler",
|
Short: "descheduler",
|
||||||
Long: `The descheduler evicts pods which may be bound to less desired nodes`,
|
Long: `The descheduler evicts pods which may be bound to less desired nodes`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
logs.InitLogs()
|
||||||
|
defer logs.FlushLogs()
|
||||||
err := Run(s)
|
err := Run(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
glog.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
cmd.SetOutput(out)
|
||||||
|
|
||||||
|
flags := cmd.Flags()
|
||||||
|
flags.SetNormalizeFunc(aflag.WordSepNormalizeFunc)
|
||||||
|
flags.AddGoFlagSet(flag.CommandLine)
|
||||||
|
s.AddFlags(flags)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
86
cmd/descheduler/app/version.go
Normal file
86
cmd/descheduler/app/version.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
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 app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// gitCommit is a constant representing the source version that
|
||||||
|
// generated this build. It should be set during build via -ldflags.
|
||||||
|
gitCommit string
|
||||||
|
// version is a constant representing the version tag that
|
||||||
|
// generated this build. It should be set during build via -ldflags.
|
||||||
|
version string
|
||||||
|
// buildDate in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
//It should be set during build via -ldflags.
|
||||||
|
buildDate string
|
||||||
|
)
|
||||||
|
|
||||||
|
// Info holds the information related to descheduler app version.
|
||||||
|
type Info struct {
|
||||||
|
Major string `json:"major"`
|
||||||
|
Minor string `json:"minor"`
|
||||||
|
GitCommit string `json:"gitCommit"`
|
||||||
|
GitVersion string `json:"gitVersion"`
|
||||||
|
BuildDate string `json:"buildDate"`
|
||||||
|
GoVersion string `json:"goVersion"`
|
||||||
|
Compiler string `json:"compiler"`
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the overall codebase version. It's for detecting
|
||||||
|
// what code a binary was built from.
|
||||||
|
func Get() Info {
|
||||||
|
majorVersion, minorVersion := splitVersion(version)
|
||||||
|
return Info{
|
||||||
|
Major: majorVersion,
|
||||||
|
Minor: minorVersion,
|
||||||
|
GitCommit: gitCommit,
|
||||||
|
GitVersion: version,
|
||||||
|
BuildDate: buildDate,
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVersionCommand() *cobra.Command {
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Version of descheduler",
|
||||||
|
Long: `Prints the version of descheduler.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Descheduler version %+v\n", Get())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return versionCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitVersion splits the git version to generate major and minor versions needed.
|
||||||
|
func splitVersion(version string) (string, string) {
|
||||||
|
if version == "" {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
// A sample version would be of form v0.1.0-7-ge884046, so split at first '.' and
|
||||||
|
// then return 0 and 1+(+ appended to follow semver convention) for major and minor versions.
|
||||||
|
return strings.Trim(strings.Split(version, ".")[0], "v"), strings.Split(version, ".")[1] + "+"
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@@ -24,7 +25,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd := app.NewDeschedulerCommand()
|
out := os.Stdout
|
||||||
|
cmd := app.NewDeschedulerCommand(out)
|
||||||
|
cmd.AddCommand(app.NewVersionCommand())
|
||||||
|
flag.CommandLine.Parse([]string{})
|
||||||
if err := cmd.Execute(); err != nil {
|
if err := cmd.Execute(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -1,58 +1,3 @@
|
|||||||
## Kubernetes Community Code of Conduct
|
# Kubernetes Community Code of Conduct
|
||||||
|
|
||||||
### Contributor Code of Conduct
|
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
||||||
|
|
||||||
As contributors and maintainers of this project, and in the interest of fostering
|
|
||||||
an open and welcoming community, we pledge to respect all people who contribute
|
|
||||||
through reporting issues, posting feature requests, updating documentation,
|
|
||||||
submitting pull requests or patches, and other activities.
|
|
||||||
|
|
||||||
We are committed to making participation in this project a harassment-free experience for
|
|
||||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
|
||||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
|
||||||
religion, or nationality.
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery
|
|
||||||
* Personal attacks
|
|
||||||
* Trolling or insulting/derogatory comments
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing other's private information, such as physical or electronic addresses,
|
|
||||||
without explicit permission
|
|
||||||
* Other unethical or unprofessional conduct.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are not
|
|
||||||
aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers
|
|
||||||
commit themselves to fairly and consistently applying these principles to every aspect
|
|
||||||
of managing this project. Project maintainers who do not follow or enforce the Code of
|
|
||||||
Conduct may be permanently removed from the project team.
|
|
||||||
|
|
||||||
This code of conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community.
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a Kubernetes maintainer, Sarah Novotny <sarahnovotny@google.com>, and/or Dan Kohn <dan@linuxfoundation.org>.
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the Contributor Covenant
|
|
||||||
(http://contributor-covenant.org), version 1.2.0, available at
|
|
||||||
http://contributor-covenant.org/version/1/2/0/
|
|
||||||
|
|
||||||
### Kubernetes Events Code of Conduct
|
|
||||||
|
|
||||||
Kubernetes events are working conferences intended for professional networking and collaboration in the
|
|
||||||
Kubernetes community. Attendees are expected to behave according to professional standards and in accordance
|
|
||||||
with their employer's policies on appropriate workplace behavior.
|
|
||||||
|
|
||||||
While at Kubernetes events or related social networking opportunities, attendees should not engage in
|
|
||||||
discriminatory or offensive speech or actions regarding gender, sexuality, race, or religion. Speakers should
|
|
||||||
be especially aware of these concerns.
|
|
||||||
|
|
||||||
The Kubernetes team does not condone any statements by speakers contrary to these standards. The Kubernetes
|
|
||||||
team reserves the right to deny entrance and/or eject from an event (without refund) any individual found to
|
|
||||||
be engaging in discriminatory or offensive speech or actions.
|
|
||||||
|
|
||||||
Please bring any concerns to to the immediate attention of Kubernetes event staff
|
|
||||||
|
|
||||||
|
|
||||||
[]()
|
|
||||||
|
|||||||
8
examples/node-affinity.yml
Normal file
8
examples/node-affinity.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: "descheduler/v1alpha1"
|
||||||
|
kind: "DeschedulerPolicy"
|
||||||
|
strategies:
|
||||||
|
"RemovePodsViolatingNodeAffinity":
|
||||||
|
enabled: true
|
||||||
|
params:
|
||||||
|
nodeAffinityType:
|
||||||
|
- "requiredDuringSchedulingIgnoredDuringExecution"
|
||||||
@@ -3,6 +3,8 @@ kind: "DeschedulerPolicy"
|
|||||||
strategies:
|
strategies:
|
||||||
"RemoveDuplicates":
|
"RemoveDuplicates":
|
||||||
enabled: true
|
enabled: true
|
||||||
|
"RemovePodsViolatingInterPodAntiAffinity":
|
||||||
|
enabled: true
|
||||||
"LowNodeUtilization":
|
"LowNodeUtilization":
|
||||||
enabled: true
|
enabled: true
|
||||||
params:
|
params:
|
||||||
|
|||||||
370
glide.lock
generated
370
glide.lock
generated
@@ -1,67 +1,60 @@
|
|||||||
hash: bf18ba8a038a73e8f11f808c8babdd34734279b050e0223f704eaabbd13830fd
|
hash: 374e925e75f6b711fd89523308d62c744e1a1846bc5923b36b864c19809eef8b
|
||||||
updated: 2017-08-05T10:03:09.300557448-04:00
|
updated: 2018-01-09T00:39:38.149357059-05:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/davecgh/go-spew
|
- name: github.com/davecgh/go-spew
|
||||||
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
version: 782f4967f2dc4564575ca782fe2d04090b5faca8
|
||||||
subpackages:
|
subpackages:
|
||||||
- spew
|
- spew
|
||||||
- name: github.com/docker/distribution
|
- name: github.com/docker/distribution
|
||||||
version: cd27f179f2c10c5d300e6d09025b538c475b0d51
|
version: edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c
|
||||||
subpackages:
|
subpackages:
|
||||||
- digest
|
- digestset
|
||||||
- reference
|
- reference
|
||||||
- name: github.com/emicklei/go-restful
|
- name: github.com/emicklei/go-restful
|
||||||
version: ff4f55a206334ef123e4f79bbf348980da81ca46
|
version: ff4f55a206334ef123e4f79bbf348980da81ca46
|
||||||
subpackages:
|
subpackages:
|
||||||
- log
|
- log
|
||||||
- name: github.com/emicklei/go-restful-swagger12
|
|
||||||
version: dcef7f55730566d41eae5db10e7d6981829720f6
|
|
||||||
- name: github.com/ghodss/yaml
|
- name: github.com/ghodss/yaml
|
||||||
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
||||||
- name: github.com/go-openapi/analysis
|
|
||||||
version: b44dc874b601d9e4e2f6e19140e794ba24bead3b
|
|
||||||
- name: github.com/go-openapi/jsonpointer
|
- name: github.com/go-openapi/jsonpointer
|
||||||
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
|
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
|
||||||
- name: github.com/go-openapi/jsonreference
|
- name: github.com/go-openapi/jsonreference
|
||||||
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
|
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
|
||||||
- name: github.com/go-openapi/loads
|
|
||||||
version: 18441dfa706d924a39a030ee2c3b1d8d81917b38
|
|
||||||
- name: github.com/go-openapi/spec
|
- name: github.com/go-openapi/spec
|
||||||
version: 6aced65f8501fe1217321abf0749d354824ba2ff
|
version: 7abd5745472fff5eb3685386d5fb8bf38683154d
|
||||||
- name: github.com/go-openapi/swag
|
- name: github.com/go-openapi/swag
|
||||||
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
|
version: f3f9494671f93fcff853e3c6e9e948b3eb71e590
|
||||||
- name: github.com/gogo/protobuf
|
- name: github.com/gogo/protobuf
|
||||||
version: c0656edd0d9eab7c66d1eb0c568f9039345796f7
|
version: c0656edd0d9eab7c66d1eb0c568f9039345796f7
|
||||||
subpackages:
|
subpackages:
|
||||||
- gogoproto
|
|
||||||
- plugin/compare
|
|
||||||
- plugin/defaultcheck
|
|
||||||
- plugin/description
|
|
||||||
- plugin/embedcheck
|
|
||||||
- plugin/enumstringer
|
|
||||||
- plugin/equal
|
|
||||||
- plugin/face
|
|
||||||
- plugin/gostring
|
|
||||||
- plugin/marshalto
|
|
||||||
- plugin/oneofcheck
|
|
||||||
- plugin/populate
|
|
||||||
- plugin/size
|
|
||||||
- plugin/stringer
|
|
||||||
- plugin/testgen
|
|
||||||
- plugin/union
|
|
||||||
- plugin/unmarshal
|
|
||||||
- proto
|
- proto
|
||||||
- protoc-gen-gogo/descriptor
|
|
||||||
- protoc-gen-gogo/generator
|
|
||||||
- protoc-gen-gogo/grpc
|
|
||||||
- protoc-gen-gogo/plugin
|
|
||||||
- sortkeys
|
- sortkeys
|
||||||
- vanity
|
|
||||||
- vanity/command
|
|
||||||
- name: github.com/golang/glog
|
- name: github.com/golang/glog
|
||||||
version: 44145f04b68cf362d9c4df2182967c2275eaefed
|
version: 23def4e6c14b4da8ac2ed8007337bc5eb5007998
|
||||||
|
- name: github.com/golang/protobuf
|
||||||
|
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
|
||||||
|
subpackages:
|
||||||
|
- jsonpb
|
||||||
|
- proto
|
||||||
|
- ptypes
|
||||||
|
- ptypes/any
|
||||||
|
- ptypes/duration
|
||||||
|
- ptypes/struct
|
||||||
|
- ptypes/timestamp
|
||||||
|
- name: github.com/google/btree
|
||||||
|
version: 7d79101e329e5a3adf994758c578dab82b90c017
|
||||||
- name: github.com/google/gofuzz
|
- name: github.com/google/gofuzz
|
||||||
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
|
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
|
||||||
|
- name: github.com/googleapis/gnostic
|
||||||
|
version: 0c5108395e2debce0d731cf0287ddf7242066aba
|
||||||
|
subpackages:
|
||||||
|
- OpenAPIv2
|
||||||
|
- compiler
|
||||||
|
- extensions
|
||||||
|
- name: github.com/gregjones/httpcache
|
||||||
|
version: 787624de3eb7bd915c329cba748687a3b22666a6
|
||||||
|
subpackages:
|
||||||
|
- diskcache
|
||||||
- name: github.com/hashicorp/golang-lru
|
- name: github.com/hashicorp/golang-lru
|
||||||
version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
|
version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -72,16 +65,22 @@ imports:
|
|||||||
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
|
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
|
||||||
- name: github.com/inconshreveable/mousetrap
|
- name: github.com/inconshreveable/mousetrap
|
||||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||||
|
- name: github.com/json-iterator/go
|
||||||
|
version: 36b14963da70d11297d313183d7e6388c8510e1e
|
||||||
- name: github.com/juju/ratelimit
|
- name: github.com/juju/ratelimit
|
||||||
version: 5b9ff866471762aa2ab2dced63c9fb6f53921342
|
version: 5b9ff866471762aa2ab2dced63c9fb6f53921342
|
||||||
- name: github.com/kubernetes/repo-infra
|
- name: github.com/kubernetes/repo-infra
|
||||||
version: f521b5d472e00e05da5394994942064510a6e8bf
|
version: dbcbd7624d5e4eb29f33c48edf1b1651809827a3
|
||||||
- name: github.com/mailru/easyjson
|
- name: github.com/mailru/easyjson
|
||||||
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
|
version: 2f5df55504ebc322e4d52d34df6a1f5b503bf26d
|
||||||
subpackages:
|
subpackages:
|
||||||
- buffer
|
- buffer
|
||||||
- jlexer
|
- jlexer
|
||||||
- jwriter
|
- jwriter
|
||||||
|
- name: github.com/opencontainers/go-digest
|
||||||
|
version: a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
|
||||||
|
- name: github.com/peterbourgon/diskv
|
||||||
|
version: 5f041e8faa004a95c88a202771f4cc3e991971e6
|
||||||
- name: github.com/PuerkitoBio/purell
|
- name: github.com/PuerkitoBio/purell
|
||||||
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
||||||
- name: github.com/PuerkitoBio/urlesc
|
- name: github.com/PuerkitoBio/urlesc
|
||||||
@@ -89,32 +88,24 @@ imports:
|
|||||||
- name: github.com/spf13/cobra
|
- name: github.com/spf13/cobra
|
||||||
version: f62e98d28ab7ad31d707ba837a966378465c7b57
|
version: f62e98d28ab7ad31d707ba837a966378465c7b57
|
||||||
- name: github.com/spf13/pflag
|
- name: github.com/spf13/pflag
|
||||||
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
|
version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea
|
||||||
- name: github.com/ugorji/go
|
- name: github.com/ugorji/go
|
||||||
version: ded73eae5db7e7a0ef6f55aace87a2873c5d2b74
|
version: f57d8945648dbfe4c332cff9c50fb57548958e3f
|
||||||
subpackages:
|
subpackages:
|
||||||
- codec
|
- codec
|
||||||
- codec/codecgen
|
|
||||||
- name: golang.org/x/crypto
|
- name: golang.org/x/crypto
|
||||||
version: d172538b2cfce0c13cee31e647d0367aa8cd2486
|
version: 81e90905daefcd6fd217b62423c0908922eadb30
|
||||||
subpackages:
|
subpackages:
|
||||||
- bcrypt
|
- bcrypt
|
||||||
- blowfish
|
- blowfish
|
||||||
- curve25519
|
|
||||||
- ed25519
|
|
||||||
- ed25519/internal/edwards25519
|
|
||||||
- nacl/secretbox
|
- nacl/secretbox
|
||||||
- pkcs12
|
|
||||||
- pkcs12/internal/rc2
|
|
||||||
- poly1305
|
- poly1305
|
||||||
- salsa20/salsa
|
- salsa20/salsa
|
||||||
- ssh
|
|
||||||
- ssh/terminal
|
- ssh/terminal
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: f2499483f923065a842d38eb4c7f1927e6fc6e6d
|
version: 1c05540f6879653db88113bc4a2b70aec4bd491f
|
||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
- context/ctxhttp
|
|
||||||
- html
|
- html
|
||||||
- html/atom
|
- html/atom
|
||||||
- http2
|
- http2
|
||||||
@@ -122,24 +113,19 @@ imports:
|
|||||||
- idna
|
- idna
|
||||||
- internal/timeseries
|
- internal/timeseries
|
||||||
- lex/httplex
|
- lex/httplex
|
||||||
- proxy
|
|
||||||
- trace
|
- trace
|
||||||
- websocket
|
- websocket
|
||||||
- name: golang.org/x/sys
|
- name: golang.org/x/sys
|
||||||
version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
|
version: 95c6576299259db960f6c5b9b69ea52422860fce
|
||||||
subpackages:
|
subpackages:
|
||||||
- unix
|
- unix
|
||||||
- windows
|
- windows
|
||||||
- name: golang.org/x/text
|
- name: golang.org/x/text
|
||||||
version: 2910a502d2bf9e43193af9d68ca516529614eed3
|
version: b19bf474d317b857955b12035d2c5acb57ce8b01
|
||||||
subpackages:
|
subpackages:
|
||||||
- cases
|
- cases
|
||||||
- encoding
|
- internal
|
||||||
- encoding/internal
|
|
||||||
- encoding/internal/identifier
|
|
||||||
- encoding/unicode
|
|
||||||
- internal/tag
|
- internal/tag
|
||||||
- internal/utf8internal
|
|
||||||
- language
|
- language
|
||||||
- runes
|
- runes
|
||||||
- secure/bidirule
|
- secure/bidirule
|
||||||
@@ -148,29 +134,66 @@ imports:
|
|||||||
- unicode/bidi
|
- unicode/bidi
|
||||||
- unicode/norm
|
- unicode/norm
|
||||||
- width
|
- width
|
||||||
|
- name: golang.org/x/tools
|
||||||
|
version: 8cab8a1319f0be9798e7fe78b15da75e5f94b2e9
|
||||||
|
subpackages:
|
||||||
|
- imports
|
||||||
- name: gopkg.in/inf.v0
|
- name: gopkg.in/inf.v0
|
||||||
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
||||||
- name: gopkg.in/yaml.v2
|
- name: gopkg.in/yaml.v2
|
||||||
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
|
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
|
||||||
- name: k8s.io/apimachinery
|
- name: k8s.io/api
|
||||||
version: abe34e4f5b4413c282a83011892cbeea5b32223b
|
version: af4bc157c3a209798fc897f6d4aaaaeb6c2e0d6a
|
||||||
|
subpackages:
|
||||||
|
- admissionregistration/v1alpha1
|
||||||
|
- admissionregistration/v1beta1
|
||||||
|
- apps/v1
|
||||||
|
- apps/v1beta1
|
||||||
|
- apps/v1beta2
|
||||||
|
- authentication/v1
|
||||||
|
- authentication/v1beta1
|
||||||
|
- authorization/v1
|
||||||
|
- authorization/v1beta1
|
||||||
|
- autoscaling/v1
|
||||||
|
- autoscaling/v2beta1
|
||||||
|
- batch/v1
|
||||||
|
- batch/v1beta1
|
||||||
|
- batch/v2alpha1
|
||||||
|
- certificates/v1beta1
|
||||||
|
- core/v1
|
||||||
|
- events/v1beta1
|
||||||
|
- extensions/v1beta1
|
||||||
|
- networking/v1
|
||||||
|
- policy/v1beta1
|
||||||
|
- rbac/v1
|
||||||
|
- rbac/v1alpha1
|
||||||
|
- rbac/v1beta1
|
||||||
|
- scheduling/v1alpha1
|
||||||
|
- settings/v1alpha1
|
||||||
|
- storage/v1
|
||||||
|
- storage/v1alpha1
|
||||||
|
- storage/v1beta1
|
||||||
|
- name: k8s.io/apiextensions-apiserver
|
||||||
|
version: aaccab68c17a51ccdfd3c8559221cce9334d3394
|
||||||
|
subpackages:
|
||||||
|
- pkg/features
|
||||||
|
- name: k8s.io/apimachinery
|
||||||
|
version: 180eddb345a5be3a157cea1c624700ad5bd27b8f
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/api/equality
|
|
||||||
- pkg/api/errors
|
- pkg/api/errors
|
||||||
- pkg/api/meta
|
- pkg/api/meta
|
||||||
- pkg/api/resource
|
- pkg/api/resource
|
||||||
- pkg/apimachinery
|
- pkg/apimachinery
|
||||||
- pkg/apimachinery/announced
|
- pkg/apimachinery/announced
|
||||||
- pkg/apimachinery/registered
|
- pkg/apimachinery/registered
|
||||||
|
- pkg/apis/meta/internalversion
|
||||||
- pkg/apis/meta/v1
|
- pkg/apis/meta/v1
|
||||||
- pkg/apis/meta/v1/unstructured
|
- pkg/apis/meta/v1/unstructured
|
||||||
- pkg/apis/meta/v1alpha1
|
- pkg/apis/meta/v1alpha1
|
||||||
- pkg/conversion
|
- pkg/conversion
|
||||||
- pkg/conversion/queryparams
|
- pkg/conversion/queryparams
|
||||||
- pkg/conversion/unstructured
|
|
||||||
- pkg/fields
|
- pkg/fields
|
||||||
- pkg/labels
|
- pkg/labels
|
||||||
- pkg/openapi
|
|
||||||
- pkg/runtime
|
- pkg/runtime
|
||||||
- pkg/runtime/schema
|
- pkg/runtime/schema
|
||||||
- pkg/runtime/serializer
|
- pkg/runtime/serializer
|
||||||
@@ -189,7 +212,6 @@ imports:
|
|||||||
- pkg/util/intstr
|
- pkg/util/intstr
|
||||||
- pkg/util/json
|
- pkg/util/json
|
||||||
- pkg/util/net
|
- pkg/util/net
|
||||||
- pkg/util/rand
|
|
||||||
- pkg/util/runtime
|
- pkg/util/runtime
|
||||||
- pkg/util/sets
|
- pkg/util/sets
|
||||||
- pkg/util/validation
|
- pkg/util/validation
|
||||||
@@ -200,51 +222,81 @@ imports:
|
|||||||
- pkg/watch
|
- pkg/watch
|
||||||
- third_party/forked/golang/reflect
|
- third_party/forked/golang/reflect
|
||||||
- name: k8s.io/apiserver
|
- name: k8s.io/apiserver
|
||||||
version: ab57ed5a72c3b67058f665d660e23bae18339fc2
|
version: 91e14f394e4796abf5a994a349a222e7081d86b6
|
||||||
|
subpackages:
|
||||||
|
- pkg/features
|
||||||
|
- pkg/util/feature
|
||||||
|
- pkg/util/flag
|
||||||
|
- pkg/util/logs
|
||||||
- name: k8s.io/client-go
|
- name: k8s.io/client-go
|
||||||
version: e356aa2e77ab4a5914c216c12ba14cce25a25ab0
|
version: 78700dec6369ba22221b72770783300f143df150
|
||||||
subpackages:
|
subpackages:
|
||||||
- discovery
|
- discovery
|
||||||
|
- discovery/fake
|
||||||
|
- kubernetes
|
||||||
|
- kubernetes/fake
|
||||||
- kubernetes/scheme
|
- kubernetes/scheme
|
||||||
- pkg/api
|
- kubernetes/typed/admissionregistration/v1alpha1
|
||||||
- pkg/api/v1
|
- kubernetes/typed/admissionregistration/v1alpha1/fake
|
||||||
- pkg/apis/admissionregistration
|
- kubernetes/typed/admissionregistration/v1beta1
|
||||||
- pkg/apis/admissionregistration/v1alpha1
|
- kubernetes/typed/admissionregistration/v1beta1/fake
|
||||||
- pkg/apis/apps
|
- kubernetes/typed/apps/v1
|
||||||
- pkg/apis/apps/v1beta1
|
- kubernetes/typed/apps/v1/fake
|
||||||
- pkg/apis/authentication
|
- kubernetes/typed/apps/v1beta1
|
||||||
- pkg/apis/authentication/v1
|
- kubernetes/typed/apps/v1beta1/fake
|
||||||
- pkg/apis/authentication/v1beta1
|
- kubernetes/typed/apps/v1beta2
|
||||||
- pkg/apis/authorization
|
- kubernetes/typed/apps/v1beta2/fake
|
||||||
- pkg/apis/authorization/v1
|
- kubernetes/typed/authentication/v1
|
||||||
- pkg/apis/authorization/v1beta1
|
- kubernetes/typed/authentication/v1/fake
|
||||||
- pkg/apis/autoscaling
|
- kubernetes/typed/authentication/v1beta1
|
||||||
- pkg/apis/autoscaling/v1
|
- kubernetes/typed/authentication/v1beta1/fake
|
||||||
- pkg/apis/autoscaling/v2alpha1
|
- kubernetes/typed/authorization/v1
|
||||||
- pkg/apis/batch
|
- kubernetes/typed/authorization/v1/fake
|
||||||
- pkg/apis/batch/v1
|
- kubernetes/typed/authorization/v1beta1
|
||||||
- pkg/apis/batch/v2alpha1
|
- kubernetes/typed/authorization/v1beta1/fake
|
||||||
- pkg/apis/certificates
|
- kubernetes/typed/autoscaling/v1
|
||||||
- pkg/apis/certificates/v1beta1
|
- kubernetes/typed/autoscaling/v1/fake
|
||||||
- pkg/apis/extensions
|
- kubernetes/typed/autoscaling/v2beta1
|
||||||
- pkg/apis/extensions/v1beta1
|
- kubernetes/typed/autoscaling/v2beta1/fake
|
||||||
- pkg/apis/networking
|
- kubernetes/typed/batch/v1
|
||||||
- pkg/apis/networking/v1
|
- kubernetes/typed/batch/v1/fake
|
||||||
- pkg/apis/policy
|
- kubernetes/typed/batch/v1beta1
|
||||||
- pkg/apis/policy/v1beta1
|
- kubernetes/typed/batch/v1beta1/fake
|
||||||
- pkg/apis/rbac
|
- kubernetes/typed/batch/v2alpha1
|
||||||
- pkg/apis/rbac/v1alpha1
|
- kubernetes/typed/batch/v2alpha1/fake
|
||||||
- pkg/apis/rbac/v1beta1
|
- kubernetes/typed/certificates/v1beta1
|
||||||
- pkg/apis/settings
|
- kubernetes/typed/certificates/v1beta1/fake
|
||||||
- pkg/apis/settings/v1alpha1
|
- kubernetes/typed/core/v1
|
||||||
- pkg/apis/storage
|
- kubernetes/typed/core/v1/fake
|
||||||
- pkg/apis/storage/v1
|
- kubernetes/typed/events/v1beta1
|
||||||
- pkg/apis/storage/v1beta1
|
- kubernetes/typed/events/v1beta1/fake
|
||||||
- pkg/util
|
- kubernetes/typed/extensions/v1beta1
|
||||||
- pkg/util/parsers
|
- kubernetes/typed/extensions/v1beta1/fake
|
||||||
|
- kubernetes/typed/networking/v1
|
||||||
|
- kubernetes/typed/networking/v1/fake
|
||||||
|
- kubernetes/typed/policy/v1beta1
|
||||||
|
- kubernetes/typed/policy/v1beta1/fake
|
||||||
|
- kubernetes/typed/rbac/v1
|
||||||
|
- kubernetes/typed/rbac/v1/fake
|
||||||
|
- kubernetes/typed/rbac/v1alpha1
|
||||||
|
- kubernetes/typed/rbac/v1alpha1/fake
|
||||||
|
- kubernetes/typed/rbac/v1beta1
|
||||||
|
- kubernetes/typed/rbac/v1beta1/fake
|
||||||
|
- kubernetes/typed/scheduling/v1alpha1
|
||||||
|
- kubernetes/typed/scheduling/v1alpha1/fake
|
||||||
|
- kubernetes/typed/settings/v1alpha1
|
||||||
|
- kubernetes/typed/settings/v1alpha1/fake
|
||||||
|
- kubernetes/typed/storage/v1
|
||||||
|
- kubernetes/typed/storage/v1/fake
|
||||||
|
- kubernetes/typed/storage/v1alpha1
|
||||||
|
- kubernetes/typed/storage/v1alpha1/fake
|
||||||
|
- kubernetes/typed/storage/v1beta1
|
||||||
|
- kubernetes/typed/storage/v1beta1/fake
|
||||||
|
- listers/core/v1
|
||||||
- pkg/version
|
- pkg/version
|
||||||
- rest
|
- rest
|
||||||
- rest/watch
|
- rest/watch
|
||||||
|
- testing
|
||||||
- tools/auth
|
- tools/auth
|
||||||
- tools/cache
|
- tools/cache
|
||||||
- tools/clientcmd
|
- tools/clientcmd
|
||||||
@@ -252,89 +304,49 @@ imports:
|
|||||||
- tools/clientcmd/api/latest
|
- tools/clientcmd/api/latest
|
||||||
- tools/clientcmd/api/v1
|
- tools/clientcmd/api/v1
|
||||||
- tools/metrics
|
- tools/metrics
|
||||||
|
- tools/pager
|
||||||
|
- tools/reference
|
||||||
- transport
|
- transport
|
||||||
|
- util/buffer
|
||||||
- util/cert
|
- util/cert
|
||||||
- util/flowcontrol
|
- util/flowcontrol
|
||||||
- util/homedir
|
- util/homedir
|
||||||
- util/integer
|
- util/integer
|
||||||
|
- name: k8s.io/code-generator
|
||||||
|
version: fef8bcdbaf36ac6a1a18c9ef7d85200b249fad30
|
||||||
- name: k8s.io/gengo
|
- name: k8s.io/gengo
|
||||||
version: c79c13d131b0a8f42d05faa6491c12e94ccc6f30
|
version: 1ef560bbde5195c01629039ad3b337ce63e7b321
|
||||||
- name: k8s.io/kubernetes
|
- name: k8s.io/kube-openapi
|
||||||
version: ebb8d6e0fadfc95f3d64ccecc36c8ed2ac9224ef
|
version: 39a7bf85c140f972372c2a0d1ee40adbf0c8bfe1
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/api
|
- pkg/builder
|
||||||
- pkg/api/install
|
- pkg/common
|
||||||
- pkg/api/v1
|
- pkg/handler
|
||||||
- pkg/api/v1/helper/qos
|
|
||||||
- pkg/api/v1/ref
|
|
||||||
- pkg/api/v1/resource
|
|
||||||
- pkg/apis/admissionregistration
|
|
||||||
- pkg/apis/admissionregistration/v1alpha1
|
|
||||||
- pkg/apis/apps
|
|
||||||
- pkg/apis/apps/install
|
|
||||||
- pkg/apis/apps/v1beta1
|
|
||||||
- pkg/apis/authentication
|
|
||||||
- pkg/apis/authentication/install
|
|
||||||
- pkg/apis/authentication/v1
|
|
||||||
- pkg/apis/authentication/v1beta1
|
|
||||||
- pkg/apis/authorization
|
|
||||||
- pkg/apis/authorization/install
|
|
||||||
- pkg/apis/authorization/v1
|
|
||||||
- pkg/apis/authorization/v1beta1
|
|
||||||
- pkg/apis/autoscaling
|
|
||||||
- pkg/apis/autoscaling/install
|
|
||||||
- pkg/apis/autoscaling/v1
|
|
||||||
- pkg/apis/autoscaling/v2alpha1
|
|
||||||
- pkg/apis/batch
|
|
||||||
- pkg/apis/batch/install
|
|
||||||
- pkg/apis/batch/v1
|
|
||||||
- pkg/apis/batch/v2alpha1
|
|
||||||
- pkg/apis/certificates
|
|
||||||
- pkg/apis/certificates/install
|
|
||||||
- pkg/apis/certificates/v1beta1
|
|
||||||
- pkg/apis/extensions
|
|
||||||
- pkg/apis/extensions/install
|
|
||||||
- pkg/apis/extensions/v1beta1
|
|
||||||
- pkg/apis/networking
|
|
||||||
- pkg/apis/networking/v1
|
|
||||||
- pkg/apis/policy
|
|
||||||
- pkg/apis/policy/install
|
|
||||||
- pkg/apis/policy/v1beta1
|
|
||||||
- pkg/apis/rbac
|
|
||||||
- pkg/apis/rbac/install
|
|
||||||
- pkg/apis/rbac/v1alpha1
|
|
||||||
- pkg/apis/rbac/v1beta1
|
|
||||||
- pkg/apis/settings
|
|
||||||
- pkg/apis/settings/install
|
|
||||||
- pkg/apis/settings/v1alpha1
|
|
||||||
- pkg/apis/storage
|
|
||||||
- pkg/apis/storage/install
|
|
||||||
- pkg/apis/storage/v1
|
|
||||||
- pkg/apis/storage/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset
|
|
||||||
- pkg/client/clientset_generated/clientset/scheme
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/admissionregistration/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/apps/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authentication/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authentication/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authorization/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authorization/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/autoscaling/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/autoscaling/v2alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/batch/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/batch/v2alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/certificates/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/core/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/extensions/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/networking/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/policy/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/rbac/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/settings/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/storage/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/storage/v1beta1
|
|
||||||
- pkg/client/listers/core/v1
|
|
||||||
- pkg/kubelet/types
|
|
||||||
- pkg/util
|
- pkg/util
|
||||||
|
- pkg/util/proto
|
||||||
|
- name: k8s.io/kubernetes
|
||||||
|
version: 925c127ec6b946659ad0fd596fa959be43f0cc05
|
||||||
|
subpackages:
|
||||||
|
- pkg/api/legacyscheme
|
||||||
|
- pkg/api/v1
|
||||||
|
- pkg/api/v1/resource
|
||||||
|
- pkg/apis/autoscaling
|
||||||
|
- pkg/apis/core
|
||||||
|
- pkg/apis/core/helper
|
||||||
|
- pkg/apis/core/helper/qos
|
||||||
|
- pkg/apis/core/install
|
||||||
|
- pkg/apis/core/v1
|
||||||
|
- pkg/apis/core/v1/helper
|
||||||
|
- pkg/apis/extensions
|
||||||
|
- pkg/apis/networking
|
||||||
|
- pkg/apis/policy
|
||||||
|
- pkg/apis/policy/v1beta1
|
||||||
|
- pkg/apis/scheduling
|
||||||
|
- pkg/features
|
||||||
|
- pkg/kubelet/types
|
||||||
- pkg/util/parsers
|
- pkg/util/parsers
|
||||||
|
- pkg/util/pointer
|
||||||
|
- plugin/pkg/scheduler/algorithm/priorities/util
|
||||||
|
- plugin/pkg/scheduler/schedulercache
|
||||||
|
- plugin/pkg/scheduler/util
|
||||||
testImports: []
|
testImports: []
|
||||||
|
|||||||
18
glide.yaml
18
glide.yaml
@@ -1,15 +1,23 @@
|
|||||||
package: github.com/kubernetes-incubator/descheduler
|
package: github.com/kubernetes-incubator/descheduler
|
||||||
import:
|
import:
|
||||||
- package: k8s.io/client-go
|
- package: k8s.io/client-go
|
||||||
version: e356aa2e77ab4a5914c216c12ba14cce25a25ab0 # kube 1.7.0
|
version: 78700dec6369ba22221b72770783300f143df150
|
||||||
|
- package: k8s.io/api
|
||||||
|
version: af4bc157c3a209798fc897f6d4aaaaeb6c2e0d6a
|
||||||
- package: k8s.io/apiserver
|
- package: k8s.io/apiserver
|
||||||
version: ab57ed5a72c3b67058f665d660e23bae18339fc2
|
version: 91e14f394e4796abf5a994a349a222e7081d86b6
|
||||||
- package: k8s.io/apimachinery
|
- package: k8s.io/apimachinery
|
||||||
version: abe34e4f5b4413c282a83011892cbeea5b32223b # kube 1.7.0
|
version: 180eddb345a5be3a157cea1c624700ad5bd27b8f
|
||||||
- package: k8s.io/kubernetes
|
- package: k8s.io/kubernetes
|
||||||
version: ebb8d6e0fadfc95f3d64ccecc36c8ed2ac9224ef # kube 1.7.0
|
version: v1.9.0
|
||||||
|
- package: k8s.io/code-generator
|
||||||
|
version: kubernetes-1.9.0
|
||||||
- package: github.com/kubernetes/repo-infra
|
- package: github.com/kubernetes/repo-infra
|
||||||
- package: github.com/spf13/cobra
|
- package: github.com/spf13/cobra
|
||||||
version: f62e98d28ab7ad31d707ba837a966378465c7b57
|
version: f62e98d28ab7ad31d707ba837a966378465c7b57
|
||||||
- package: k8s.io/gengo
|
- package: k8s.io/gengo
|
||||||
version: c79c13d131b0a8f42d05faa6491c12e94ccc6f30
|
- package: github.com/ugorji/go
|
||||||
|
version: v.1.1-beta
|
||||||
|
- package: golang.org/x/tools
|
||||||
|
subpackages:
|
||||||
|
- imports
|
||||||
|
|||||||
95
hack/e2e-gce/gcloud_create_cluster.sh
Executable file
95
hack/e2e-gce/gcloud_create_cluster.sh
Executable file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
echo "Make sure that uuid package is installed"
|
||||||
|
|
||||||
|
master_uuid=$(uuid)
|
||||||
|
node1_uuid=$(uuid)
|
||||||
|
node2_uuid=$(uuid)
|
||||||
|
kube_apiserver_port=6443
|
||||||
|
kube_version=1.9.4
|
||||||
|
|
||||||
|
DESCHEDULER_ROOT=$(dirname "${BASH_SOURCE}")/../../
|
||||||
|
E2E_GCE_HOME=$DESCHEDULER_ROOT/hack/e2e-gce
|
||||||
|
|
||||||
|
|
||||||
|
create_cluster() {
|
||||||
|
echo "#################### Creating instances ##########################"
|
||||||
|
gcloud compute instances create descheduler-$master_uuid --image="ubuntu-1604-xenial-v20180306" --image-project="ubuntu-os-cloud" --zone=us-east1-b
|
||||||
|
# Keeping the --zone here so as to make sure that e2e's can run locally.
|
||||||
|
echo "gcloud compute instances delete descheduler-$master_uuid --zone=us-east1-b --quiet" > $E2E_GCE_HOME/delete_cluster.sh
|
||||||
|
|
||||||
|
gcloud compute instances create descheduler-$node1_uuid --image="ubuntu-1604-xenial-v20180306" --image-project="ubuntu-os-cloud" --zone=us-east1-b
|
||||||
|
echo "gcloud compute instances delete descheduler-$node1_uuid --zone=us-east1-b --quiet" >> $E2E_GCE_HOME/delete_cluster.sh
|
||||||
|
|
||||||
|
gcloud compute instances create descheduler-$node2_uuid --image="ubuntu-1604-xenial-v20180306" --image-project="ubuntu-os-cloud" --zone=us-east1-b
|
||||||
|
echo "gcloud compute instances delete descheduler-$node2_uuid --zone=us-east1-b --quiet" >> $E2E_GCE_HOME/delete_cluster.sh
|
||||||
|
|
||||||
|
# Delete the firewall port created for master.
|
||||||
|
echo "gcloud compute firewall-rules delete kubeapiserver-$master_uuid --quiet" >> $E2E_GCE_HOME/delete_cluster.sh
|
||||||
|
chmod 755 $E2E_GCE_HOME/delete_cluster.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
generate_kubeadm_instance_files() {
|
||||||
|
# TODO: Check if they have come up. awk $6 contains the state(RUNNING or not).
|
||||||
|
master_public_ip=$(gcloud compute instances list | grep $master_uuid|awk '{print $5}')
|
||||||
|
node1_public_ip=$(gcloud compute instances list | grep $node1_uuid|awk '{print $5}')
|
||||||
|
node2_public_ip=$(gcloud compute instances list | grep $node2_uuid|awk '{print $5}')
|
||||||
|
echo "kubeadm init --kubernetes-version=${kube_version} --apiserver-advertise-address=${master_public_ip}" --skip-preflight-checks --pod-network-cidr=10.96.0.0/12 > $E2E_GCE_HOME/kubeadm_install.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
transfer_install_files() {
|
||||||
|
gcloud compute scp $E2E_GCE_HOME/kubeadm_preinstall.sh descheduler-$master_uuid:/tmp --zone=us-east1-b
|
||||||
|
gcloud compute scp $E2E_GCE_HOME/kubeadm_install.sh descheduler-$master_uuid:/tmp --zone=us-east1-b
|
||||||
|
gcloud compute scp $E2E_GCE_HOME/kubeadm_preinstall.sh descheduler-$node1_uuid:/tmp --zone=us-east1-b
|
||||||
|
gcloud compute scp $E2E_GCE_HOME/kubeadm_preinstall.sh descheduler-$node2_uuid:/tmp --zone=us-east1-b
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
install_kube() {
|
||||||
|
# Docker installation.
|
||||||
|
gcloud compute ssh descheduler-$master_uuid --command "sudo apt-get update; sudo apt-get install -y docker.io" --zone=us-east1-b
|
||||||
|
gcloud compute ssh descheduler-$node1_uuid --command "sudo apt-get update; sudo apt-get install -y docker.io" --zone=us-east1-b
|
||||||
|
gcloud compute ssh descheduler-$node2_uuid --command "sudo apt-get update; sudo apt-get install -y docker.io" --zone=us-east1-b
|
||||||
|
# kubeadm installation.
|
||||||
|
# 1. Transfer files to master, nodes.
|
||||||
|
transfer_install_files
|
||||||
|
# 2. Install kubeadm.
|
||||||
|
#TODO: Add rm /tmp/kubeadm_install.sh
|
||||||
|
# Open port for kube API server
|
||||||
|
gcloud compute firewall-rules create kubeapiserver-$master_uuid --allow tcp:6443 --source-tags=descheduler-$master_uuid --source-ranges=0.0.0.0/0 --description="Opening api server port"
|
||||||
|
|
||||||
|
gcloud compute ssh descheduler-$master_uuid --command "sudo chmod 755 /tmp/kubeadm_preinstall.sh; sudo /tmp/kubeadm_preinstall.sh" --zone=us-east1-b
|
||||||
|
kubeadm_join_command=$(gcloud compute ssh descheduler-$master_uuid --command "sudo chmod 755 /tmp/kubeadm_install.sh; sudo /tmp/kubeadm_install.sh" --zone=us-east1-b|grep 'kubeadm join')
|
||||||
|
|
||||||
|
# Copy the kubeconfig file onto /tmp for e2e tests.
|
||||||
|
gcloud compute ssh descheduler-$master_uuid --command "sudo cp /etc/kubernetes/admin.conf /tmp; sudo chmod 777 /tmp/admin.conf" --zone=us-east1-b
|
||||||
|
gcloud compute scp descheduler-$master_uuid:/tmp/admin.conf /tmp/admin.conf --zone=us-east1-b
|
||||||
|
|
||||||
|
# Postinstall on master, need to add a network plugin for kube-dns to come to running state.
|
||||||
|
gcloud compute ssh descheduler-$master_uuid --command "sudo kubectl apply -f https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter.yaml --kubeconfig /etc/kubernetes/admin.conf" --zone=us-east1-b
|
||||||
|
echo $kubeadm_join_command > $E2E_GCE_HOME/kubeadm_join.sh
|
||||||
|
|
||||||
|
# Copy kubeadm_join to every node.
|
||||||
|
#TODO: Put these in a loop, so that extension becomes possible.
|
||||||
|
gcloud compute ssh descheduler-$node1_uuid --command "sudo chmod 755 /tmp/kubeadm_preinstall.sh; sudo /tmp/kubeadm_preinstall.sh" --zone=us-east1-b
|
||||||
|
gcloud compute scp $E2E_GCE_HOME/kubeadm_join.sh descheduler-$node1_uuid:/tmp --zone=us-east1-b
|
||||||
|
gcloud compute ssh descheduler-$node1_uuid --command "sudo chmod 755 /tmp/kubeadm_join.sh; sudo /tmp/kubeadm_join.sh" --zone=us-east1-b
|
||||||
|
|
||||||
|
gcloud compute ssh descheduler-$node2_uuid --command "sudo chmod 755 /tmp/kubeadm_preinstall.sh; sudo /tmp/kubeadm_preinstall.sh" --zone=us-east1-b
|
||||||
|
gcloud compute scp $E2E_GCE_HOME/kubeadm_join.sh descheduler-$node2_uuid:/tmp --zone=us-east1-b
|
||||||
|
gcloud compute ssh descheduler-$node2_uuid --command "sudo chmod 755 /tmp/kubeadm_join.sh; sudo /tmp/kubeadm_join.sh" --zone=us-east1-b
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
create_cluster
|
||||||
|
|
||||||
|
generate_kubeadm_instance_files
|
||||||
|
|
||||||
|
install_kube
|
||||||
8
hack/e2e-gce/gcloud_sdk_configure.sh
Executable file
8
hack/e2e-gce/gcloud_sdk_configure.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
|
||||||
|
gcloud auth activate-service-account --key-file "${GCE_SA_CREDS}"
|
||||||
|
gcloud config set project $GCE_PROJECT_ID
|
||||||
|
gcloud config set compute/zone $GCE_ZONE
|
||||||
9
hack/e2e-gce/install_gcloud.sh
Executable file
9
hack/e2e-gce/install_gcloud.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-176.0.0-linux-x86_64.tar.gz
|
||||||
|
|
||||||
|
tar -xvzf google-cloud-sdk-176.0.0-linux-x86_64.tar.gz
|
||||||
|
|
||||||
|
./google-cloud-sdk/install.sh -q
|
||||||
11
hack/e2e-gce/kubeadm_preinstall.sh
Normal file
11
hack/e2e-gce/kubeadm_preinstall.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apt-get update
|
||||||
|
apt-get install -y docker.io
|
||||||
|
|
||||||
|
apt-get update && apt-get install -y apt-transport-https
|
||||||
|
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
|
||||||
|
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
|
||||||
|
deb http://apt.kubernetes.io/ kubernetes-xenial main
|
||||||
|
EOF
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y kubelet kubeadm kubectl
|
||||||
|
exit 0
|
||||||
@@ -43,5 +43,5 @@ OS_ROOT="$( os::util::absolute_path "${init_source}" )"
|
|||||||
export OS_ROOT
|
export OS_ROOT
|
||||||
cd "${OS_ROOT}"
|
cd "${OS_ROOT}"
|
||||||
|
|
||||||
PRJ_PREFIX="github.com/kubernetes-incubator/descheduler"
|
PRJ_PREFIX="github.com/${REPO_ORG:-kubernetes-incubator}/descheduler"
|
||||||
OS_OUTPUT_BINPATH="${OS_ROOT}/_output/bin"
|
OS_OUTPUT_BINPATH="${OS_ROOT}/_output/bin"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ generated_files=($(
|
|||||||
|
|
||||||
# We only work for deps within this prefix.
|
# We only work for deps within this prefix.
|
||||||
#my_prefix="k8s.io/kubernetes"
|
#my_prefix="k8s.io/kubernetes"
|
||||||
my_prefix="github.com/kubernetes-incubator/descheduler"
|
my_prefix="github.com/${REPO_ORG:-kubernetes-incubator}/descheduler"
|
||||||
|
|
||||||
# Register function to be called on EXIT to remove codecgen
|
# Register function to be called on EXIT to remove codecgen
|
||||||
# binary and also to touch the files that should be regenerated
|
# binary and also to touch the files that should be regenerated
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
|
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
|
||||||
|
|
||||||
go build -o "${OS_OUTPUT_BINPATH}/conversion-gen" "${PRJ_PREFIX}/vendor/k8s.io/kubernetes/cmd/libs/go2idl/conversion-gen"
|
go build -o "${OS_OUTPUT_BINPATH}/conversion-gen" "${PRJ_PREFIX}/vendor/k8s.io/code-generator/cmd/conversion-gen"
|
||||||
|
|
||||||
${OS_OUTPUT_BINPATH}/conversion-gen \
|
${OS_OUTPUT_BINPATH}/conversion-gen \
|
||||||
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
|
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
|
||||||
|
|
||||||
go build -o "${OS_OUTPUT_BINPATH}/deepcopy-gen" "${PRJ_PREFIX}/vendor/k8s.io/kubernetes/cmd/libs/go2idl/deepcopy-gen"
|
go build -o "${OS_OUTPUT_BINPATH}/deepcopy-gen" "${PRJ_PREFIX}/vendor/k8s.io/code-generator/cmd/deepcopy-gen"
|
||||||
|
|
||||||
${OS_OUTPUT_BINPATH}/deepcopy-gen \
|
${OS_OUTPUT_BINPATH}/deepcopy-gen \
|
||||||
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
|
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
|
||||||
|
|
||||||
go build -o "${OS_OUTPUT_BINPATH}/defaulter-gen" "${PRJ_PREFIX}/vendor/k8s.io/kubernetes/cmd/libs/go2idl/defaulter-gen"
|
go build -o "${OS_OUTPUT_BINPATH}/defaulter-gen" "${PRJ_PREFIX}/vendor/k8s.io/code-generator/cmd/defaulter-gen"
|
||||||
|
|
||||||
${OS_OUTPUT_BINPATH}/defaulter-gen \
|
${OS_OUTPUT_BINPATH}/defaulter-gen \
|
||||||
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
--go-header-file "hack/boilerplate/boilerplate.go.txt" \
|
||||||
|
|||||||
54
hack/verify-gofmt.sh
Executable file
54
hack/verify-gofmt.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
DESCHEDULER_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
|
|
||||||
|
GO_VERSION=($(go version))
|
||||||
|
|
||||||
|
if [[ -z $(echo "${GO_VERSION[2]}" | grep -E 'go1.2|go1.3|go1.4|go1.5|go1.6|go1.7|go1.8|go1.9') ]]; then
|
||||||
|
echo "Unknown go version '${GO_VERSION}', skipping gofmt."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "${DESCHEDULER_ROOT}"
|
||||||
|
|
||||||
|
find_files() {
|
||||||
|
find . -not \( \
|
||||||
|
\( \
|
||||||
|
-wholename './output' \
|
||||||
|
-o -wholename './_output' \
|
||||||
|
-o -wholename './release' \
|
||||||
|
-o -wholename './target' \
|
||||||
|
-o -wholename './.git' \
|
||||||
|
-o -wholename '*/third_party/*' \
|
||||||
|
-o -wholename '*/Godeps/*' \
|
||||||
|
-o -wholename '*/vendor/*' \
|
||||||
|
\) -prune \
|
||||||
|
\) -name '*.go'
|
||||||
|
}
|
||||||
|
|
||||||
|
GOFMT="gofmt -s"
|
||||||
|
bad_files=$(find_files | xargs $GOFMT -l)
|
||||||
|
if [[ -n "${bad_files}" ]]; then
|
||||||
|
echo "!!! '$GOFMT' needs to be run on the following files: "
|
||||||
|
echo "${bad_files}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -37,7 +37,6 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r
|
|||||||
&announced.GroupMetaFactoryArgs{
|
&announced.GroupMetaFactoryArgs{
|
||||||
GroupName: deschedulerapi.GroupName,
|
GroupName: deschedulerapi.GroupName,
|
||||||
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
||||||
ImportPrefix: "github.com/kubernetes-incubator/descheduler/pkg/api",
|
|
||||||
AddInternalObjectsToScheme: deschedulerapi.AddToScheme,
|
AddInternalObjectsToScheme: deschedulerapi.AddToScheme,
|
||||||
},
|
},
|
||||||
announced.VersionToSchemeFunc{
|
announced.VersionToSchemeFunc{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,10 +17,12 @@ limitations under the License.
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
type DeschedulerPolicy struct {
|
type DeschedulerPolicy struct {
|
||||||
metav1.TypeMeta
|
metav1.TypeMeta
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ type DeschedulerStrategy struct {
|
|||||||
// Only one of its members may be specified
|
// Only one of its members may be specified
|
||||||
type StrategyParameters struct {
|
type StrategyParameters struct {
|
||||||
NodeResourceUtilizationThresholds NodeResourceUtilizationThresholds
|
NodeResourceUtilizationThresholds NodeResourceUtilizationThresholds
|
||||||
|
NodeAffinityType []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Percentage float64
|
type Percentage float64
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,10 +17,12 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
type DeschedulerPolicy struct {
|
type DeschedulerPolicy struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ type DeschedulerStrategy struct {
|
|||||||
// Only one of its members may be specified
|
// Only one of its members may be specified
|
||||||
type StrategyParameters struct {
|
type StrategyParameters struct {
|
||||||
NodeResourceUtilizationThresholds NodeResourceUtilizationThresholds `json:"nodeResourceUtilizationThresholds,omitempty"`
|
NodeResourceUtilizationThresholds NodeResourceUtilizationThresholds `json:"nodeResourceUtilizationThresholds,omitempty"`
|
||||||
|
NodeAffinityType []string `json:"nodeAffinityType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Percentage float64
|
type Percentage float64
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,14 +21,15 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
unsafe "unsafe"
|
||||||
|
|
||||||
api "github.com/kubernetes-incubator/descheduler/pkg/api"
|
api "github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
unsafe "unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
SchemeBuilder.Register(RegisterConversions)
|
localSchemeBuilder.Register(RegisterConversions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterConversions adds conversion functions to the given scheme.
|
// RegisterConversions adds conversion functions to the given scheme.
|
||||||
@@ -122,6 +123,7 @@ func autoConvert_v1alpha1_StrategyParameters_To_api_StrategyParameters(in *Strat
|
|||||||
if err := Convert_v1alpha1_NodeResourceUtilizationThresholds_To_api_NodeResourceUtilizationThresholds(&in.NodeResourceUtilizationThresholds, &out.NodeResourceUtilizationThresholds, s); err != nil {
|
if err := Convert_v1alpha1_NodeResourceUtilizationThresholds_To_api_NodeResourceUtilizationThresholds(&in.NodeResourceUtilizationThresholds, &out.NodeResourceUtilizationThresholds, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
out.NodeAffinityType = *(*[]string)(unsafe.Pointer(&in.NodeAffinityType))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +136,7 @@ func autoConvert_api_StrategyParameters_To_v1alpha1_StrategyParameters(in *api.S
|
|||||||
if err := Convert_api_NodeResourceUtilizationThresholds_To_v1alpha1_NodeResourceUtilizationThresholds(&in.NodeResourceUtilizationThresholds, &out.NodeResourceUtilizationThresholds, s); err != nil {
|
if err := Convert_api_NodeResourceUtilizationThresholds_To_v1alpha1_NodeResourceUtilizationThresholds(&in.NodeResourceUtilizationThresholds, &out.NodeResourceUtilizationThresholds, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
out.NodeAffinityType = *(*[]string)(unsafe.Pointer(&in.NodeAffinityType))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,93 +21,109 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
SchemeBuilder.Register(RegisterDeepCopies)
|
func (in *DeschedulerPolicy) DeepCopyInto(out *DeschedulerPolicy) {
|
||||||
}
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
|
if in.Strategies != nil {
|
||||||
// to allow building arbitrary schemes.
|
in, out := &in.Strategies, &out.Strategies
|
||||||
func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
*out = make(StrategyList, len(*in))
|
||||||
return scheme.AddGeneratedDeepCopyFuncs(
|
for key, val := range *in {
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_DeschedulerPolicy, InType: reflect.TypeOf(&DeschedulerPolicy{})},
|
newVal := new(DeschedulerStrategy)
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_DeschedulerStrategy, InType: reflect.TypeOf(&DeschedulerStrategy{})},
|
val.DeepCopyInto(newVal)
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_NodeResourceUtilizationThresholds, InType: reflect.TypeOf(&NodeResourceUtilizationThresholds{})},
|
(*out)[key] = *newVal
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_StrategyParameters, InType: reflect.TypeOf(&StrategyParameters{})},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy_v1alpha1_DeschedulerPolicy is an autogenerated deepcopy function.
|
|
||||||
func DeepCopy_v1alpha1_DeschedulerPolicy(in interface{}, out interface{}, c *conversion.Cloner) error {
|
|
||||||
{
|
|
||||||
in := in.(*DeschedulerPolicy)
|
|
||||||
out := out.(*DeschedulerPolicy)
|
|
||||||
*out = *in
|
|
||||||
if in.Strategies != nil {
|
|
||||||
in, out := &in.Strategies, &out.Strategies
|
|
||||||
*out = make(StrategyList)
|
|
||||||
for key, val := range *in {
|
|
||||||
newVal := new(DeschedulerStrategy)
|
|
||||||
if err := DeepCopy_v1alpha1_DeschedulerStrategy(&val, newVal, c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
(*out)[key] = *newVal
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerPolicy.
|
||||||
|
func (in *DeschedulerPolicy) DeepCopy() *DeschedulerPolicy {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DeschedulerPolicy)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *DeschedulerPolicy) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_v1alpha1_DeschedulerStrategy is an autogenerated deepcopy function.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func DeepCopy_v1alpha1_DeschedulerStrategy(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *DeschedulerStrategy) DeepCopyInto(out *DeschedulerStrategy) {
|
||||||
{
|
*out = *in
|
||||||
in := in.(*DeschedulerStrategy)
|
in.Params.DeepCopyInto(&out.Params)
|
||||||
out := out.(*DeschedulerStrategy)
|
return
|
||||||
*out = *in
|
|
||||||
if err := DeepCopy_v1alpha1_StrategyParameters(&in.Params, &out.Params, c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_v1alpha1_NodeResourceUtilizationThresholds is an autogenerated deepcopy function.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerStrategy.
|
||||||
func DeepCopy_v1alpha1_NodeResourceUtilizationThresholds(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *DeschedulerStrategy) DeepCopy() *DeschedulerStrategy {
|
||||||
{
|
if in == nil {
|
||||||
in := in.(*NodeResourceUtilizationThresholds)
|
|
||||||
out := out.(*NodeResourceUtilizationThresholds)
|
|
||||||
*out = *in
|
|
||||||
if in.Thresholds != nil {
|
|
||||||
in, out := &in.Thresholds, &out.Thresholds
|
|
||||||
*out = make(ResourceThresholds)
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if in.TargetThresholds != nil {
|
|
||||||
in, out := &in.TargetThresholds, &out.TargetThresholds
|
|
||||||
*out = make(ResourceThresholds)
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
out := new(DeschedulerStrategy)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_v1alpha1_StrategyParameters is an autogenerated deepcopy function.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func DeepCopy_v1alpha1_StrategyParameters(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *NodeResourceUtilizationThresholds) DeepCopyInto(out *NodeResourceUtilizationThresholds) {
|
||||||
{
|
*out = *in
|
||||||
in := in.(*StrategyParameters)
|
if in.Thresholds != nil {
|
||||||
out := out.(*StrategyParameters)
|
in, out := &in.Thresholds, &out.Thresholds
|
||||||
*out = *in
|
*out = make(ResourceThresholds, len(*in))
|
||||||
if err := DeepCopy_v1alpha1_NodeResourceUtilizationThresholds(&in.NodeResourceUtilizationThresholds, &out.NodeResourceUtilizationThresholds, c); err != nil {
|
for key, val := range *in {
|
||||||
return err
|
(*out)[key] = val
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if in.TargetThresholds != nil {
|
||||||
|
in, out := &in.TargetThresholds, &out.TargetThresholds
|
||||||
|
*out = make(ResourceThresholds, len(*in))
|
||||||
|
for key, val := range *in {
|
||||||
|
(*out)[key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResourceUtilizationThresholds.
|
||||||
|
func (in *NodeResourceUtilizationThresholds) DeepCopy() *NodeResourceUtilizationThresholds {
|
||||||
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
out := new(NodeResourceUtilizationThresholds)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *StrategyParameters) DeepCopyInto(out *StrategyParameters) {
|
||||||
|
*out = *in
|
||||||
|
in.NodeResourceUtilizationThresholds.DeepCopyInto(&out.NodeResourceUtilizationThresholds)
|
||||||
|
if in.NodeAffinityType != nil {
|
||||||
|
in, out := &in.NodeAffinityType, &out.NodeAffinityType
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyParameters.
|
||||||
|
func (in *StrategyParameters) DeepCopy() *StrategyParameters {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(StrategyParameters)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,93 +21,109 @@ limitations under the License.
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
SchemeBuilder.Register(RegisterDeepCopies)
|
func (in *DeschedulerPolicy) DeepCopyInto(out *DeschedulerPolicy) {
|
||||||
}
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
|
if in.Strategies != nil {
|
||||||
// to allow building arbitrary schemes.
|
in, out := &in.Strategies, &out.Strategies
|
||||||
func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
*out = make(StrategyList, len(*in))
|
||||||
return scheme.AddGeneratedDeepCopyFuncs(
|
for key, val := range *in {
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeschedulerPolicy, InType: reflect.TypeOf(&DeschedulerPolicy{})},
|
newVal := new(DeschedulerStrategy)
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeschedulerStrategy, InType: reflect.TypeOf(&DeschedulerStrategy{})},
|
val.DeepCopyInto(newVal)
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_NodeResourceUtilizationThresholds, InType: reflect.TypeOf(&NodeResourceUtilizationThresholds{})},
|
(*out)[key] = *newVal
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_StrategyParameters, InType: reflect.TypeOf(&StrategyParameters{})},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy_api_DeschedulerPolicy is an autogenerated deepcopy function.
|
|
||||||
func DeepCopy_api_DeschedulerPolicy(in interface{}, out interface{}, c *conversion.Cloner) error {
|
|
||||||
{
|
|
||||||
in := in.(*DeschedulerPolicy)
|
|
||||||
out := out.(*DeschedulerPolicy)
|
|
||||||
*out = *in
|
|
||||||
if in.Strategies != nil {
|
|
||||||
in, out := &in.Strategies, &out.Strategies
|
|
||||||
*out = make(StrategyList)
|
|
||||||
for key, val := range *in {
|
|
||||||
newVal := new(DeschedulerStrategy)
|
|
||||||
if err := DeepCopy_api_DeschedulerStrategy(&val, newVal, c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
(*out)[key] = *newVal
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerPolicy.
|
||||||
|
func (in *DeschedulerPolicy) DeepCopy() *DeschedulerPolicy {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DeschedulerPolicy)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *DeschedulerPolicy) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_api_DeschedulerStrategy is an autogenerated deepcopy function.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func DeepCopy_api_DeschedulerStrategy(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *DeschedulerStrategy) DeepCopyInto(out *DeschedulerStrategy) {
|
||||||
{
|
*out = *in
|
||||||
in := in.(*DeschedulerStrategy)
|
in.Params.DeepCopyInto(&out.Params)
|
||||||
out := out.(*DeschedulerStrategy)
|
return
|
||||||
*out = *in
|
|
||||||
if err := DeepCopy_api_StrategyParameters(&in.Params, &out.Params, c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_api_NodeResourceUtilizationThresholds is an autogenerated deepcopy function.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerStrategy.
|
||||||
func DeepCopy_api_NodeResourceUtilizationThresholds(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *DeschedulerStrategy) DeepCopy() *DeschedulerStrategy {
|
||||||
{
|
if in == nil {
|
||||||
in := in.(*NodeResourceUtilizationThresholds)
|
|
||||||
out := out.(*NodeResourceUtilizationThresholds)
|
|
||||||
*out = *in
|
|
||||||
if in.Thresholds != nil {
|
|
||||||
in, out := &in.Thresholds, &out.Thresholds
|
|
||||||
*out = make(ResourceThresholds)
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if in.TargetThresholds != nil {
|
|
||||||
in, out := &in.TargetThresholds, &out.TargetThresholds
|
|
||||||
*out = make(ResourceThresholds)
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
out := new(DeschedulerStrategy)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_api_StrategyParameters is an autogenerated deepcopy function.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func DeepCopy_api_StrategyParameters(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *NodeResourceUtilizationThresholds) DeepCopyInto(out *NodeResourceUtilizationThresholds) {
|
||||||
{
|
*out = *in
|
||||||
in := in.(*StrategyParameters)
|
if in.Thresholds != nil {
|
||||||
out := out.(*StrategyParameters)
|
in, out := &in.Thresholds, &out.Thresholds
|
||||||
*out = *in
|
*out = make(ResourceThresholds, len(*in))
|
||||||
if err := DeepCopy_api_NodeResourceUtilizationThresholds(&in.NodeResourceUtilizationThresholds, &out.NodeResourceUtilizationThresholds, c); err != nil {
|
for key, val := range *in {
|
||||||
return err
|
(*out)[key] = val
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if in.TargetThresholds != nil {
|
||||||
|
in, out := &in.TargetThresholds, &out.TargetThresholds
|
||||||
|
*out = make(ResourceThresholds, len(*in))
|
||||||
|
for key, val := range *in {
|
||||||
|
(*out)[key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResourceUtilizationThresholds.
|
||||||
|
func (in *NodeResourceUtilizationThresholds) DeepCopy() *NodeResourceUtilizationThresholds {
|
||||||
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
out := new(NodeResourceUtilizationThresholds)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *StrategyParameters) DeepCopyInto(out *StrategyParameters) {
|
||||||
|
*out = *in
|
||||||
|
in.NodeResourceUtilizationThresholds.DeepCopyInto(&out.NodeResourceUtilizationThresholds)
|
||||||
|
if in.NodeAffinityType != nil {
|
||||||
|
in, out := &in.NodeAffinityType, &out.NodeAffinityType
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyParameters.
|
||||||
|
func (in *StrategyParameters) DeepCopy() *StrategyParameters {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(StrategyParameters)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r
|
|||||||
&announced.GroupMetaFactoryArgs{
|
&announced.GroupMetaFactoryArgs{
|
||||||
GroupName: componentconfig.GroupName,
|
GroupName: componentconfig.GroupName,
|
||||||
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
||||||
ImportPrefix: "github.com/kubernetes-incubator/descheduler/pkg/apis/componentconfig",
|
|
||||||
AddInternalObjectsToScheme: componentconfig.AddToScheme,
|
AddInternalObjectsToScheme: componentconfig.AddToScheme,
|
||||||
},
|
},
|
||||||
announced.VersionToSchemeFunc{
|
announced.VersionToSchemeFunc{
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ************************************************************
|
// Code generated by codecgen - DO NOT EDIT.
|
||||||
// DO NOT EDIT.
|
|
||||||
// THIS FILE IS AUTO-GENERATED BY codecgen.
|
|
||||||
// ************************************************************
|
|
||||||
|
|
||||||
package componentconfig
|
package componentconfig
|
||||||
|
|
||||||
@@ -33,31 +30,29 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// ----- content types ----
|
// ----- content types ----
|
||||||
codecSelferC_UTF81234 = 1
|
codecSelferCcUTF81234 = 1
|
||||||
codecSelferC_RAW1234 = 0
|
codecSelferCcRAW1234 = 0
|
||||||
// ----- value types used ----
|
// ----- value types used ----
|
||||||
codecSelferValueTypeArray1234 = 10
|
codecSelferValueTypeArray1234 = 10
|
||||||
codecSelferValueTypeMap1234 = 9
|
codecSelferValueTypeMap1234 = 9
|
||||||
// ----- containerStateValues ----
|
codecSelferValueTypeString1234 = 6
|
||||||
codecSelfer_containerMapKey1234 = 2
|
codecSelferValueTypeInt1234 = 2
|
||||||
codecSelfer_containerMapValue1234 = 3
|
codecSelferValueTypeUint1234 = 3
|
||||||
codecSelfer_containerMapEnd1234 = 4
|
codecSelferValueTypeFloat1234 = 4
|
||||||
codecSelfer_containerArrayElem1234 = 6
|
|
||||||
codecSelfer_containerArrayEnd1234 = 7
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
codecSelferBitsize1234 = uint8(reflect.TypeOf(uint(0)).Bits())
|
codecSelferBitsize1234 = uint8(reflect.TypeOf(uint(0)).Bits())
|
||||||
codecSelferOnlyMapOrArrayEncodeToStructErr1234 = errors.New(`only encoded map or array can be decoded into a struct`)
|
errCodecSelferOnlyMapOrArrayEncodeToStruct1234 = errors.New(`only encoded map or array can be decoded into a struct`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type codecSelfer1234 struct{}
|
type codecSelfer1234 struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if codec1978.GenVersion != 5 {
|
if codec1978.GenVersion != 8 {
|
||||||
_, file, _, _ := runtime.Caller(0)
|
_, file, _, _ := runtime.Caller(0)
|
||||||
err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v",
|
err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v",
|
||||||
5, codec1978.GenVersion, file)
|
8, codec1978.GenVersion, file)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if false { // reference the types, but skip this branch at build/run time
|
if false { // reference the types, but skip this branch at build/run time
|
||||||
@@ -77,139 +72,142 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
yym1 := z.EncBinary()
|
yym1 := z.EncBinary()
|
||||||
_ = yym1
|
_ = yym1
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.EncExt(x) {
|
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||||
|
z.EncExtension(x, yyxt1)
|
||||||
} else {
|
} else {
|
||||||
yysep2 := !z.EncBinary()
|
yysep2 := !z.EncBinary()
|
||||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||||
var yyq2 [6]bool
|
var yyq2 [8]bool
|
||||||
_, _, _ = yysep2, yyq2, yy2arr2
|
_ = yyq2
|
||||||
|
_, _ = yysep2, yy2arr2
|
||||||
const yyr2 bool = false
|
const yyr2 bool = false
|
||||||
yyq2[0] = x.Kind != ""
|
yyq2[0] = x.Kind != ""
|
||||||
yyq2[1] = x.APIVersion != ""
|
yyq2[1] = x.APIVersion != ""
|
||||||
var yynn2 int
|
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
r.EncodeArrayStart(6)
|
r.WriteArrayStart(8)
|
||||||
} else {
|
} else {
|
||||||
yynn2 = 4
|
var yynn2 = 6
|
||||||
for _, b := range yyq2 {
|
for _, b := range yyq2 {
|
||||||
if b {
|
if b {
|
||||||
yynn2++
|
yynn2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.EncodeMapStart(yynn2)
|
r.WriteMapStart(yynn2)
|
||||||
yynn2 = 0
|
yynn2 = 0
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[0] {
|
if yyq2[0] {
|
||||||
yym4 := z.EncBinary()
|
yym4 := z.EncBinary()
|
||||||
_ = yym4
|
_ = yym4
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
|
r.EncodeString(codecSelferCcUTF81234, string(x.Kind))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, "")
|
r.EncodeString(codecSelferCcUTF81234, "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[0] {
|
if yyq2[0] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("kind"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `kind`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym5 := z.EncBinary()
|
yym5 := z.EncBinary()
|
||||||
_ = yym5
|
_ = yym5
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
|
r.EncodeString(codecSelferCcUTF81234, string(x.Kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[1] {
|
if yyq2[1] {
|
||||||
yym7 := z.EncBinary()
|
yym7 := z.EncBinary()
|
||||||
_ = yym7
|
_ = yym7
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
|
r.EncodeString(codecSelferCcUTF81234, string(x.APIVersion))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, "")
|
r.EncodeString(codecSelferCcUTF81234, "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[1] {
|
if yyq2[1] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("apiVersion"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `apiVersion`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym8 := z.EncBinary()
|
yym8 := z.EncBinary()
|
||||||
_ = yym8
|
_ = yym8
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
|
r.EncodeString(codecSelferCcUTF81234, string(x.APIVersion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
yym10 := z.EncBinary()
|
yym10 := z.EncBinary()
|
||||||
_ = yym10
|
_ = yym10
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.EncExt(x.DeschedulingInterval) {
|
} else if yyxt10 := z.Extension(z.I2Rtid(x.DeschedulingInterval)); yyxt10 != nil {
|
||||||
|
z.EncExtension(x.DeschedulingInterval, yyxt10)
|
||||||
} else {
|
} else {
|
||||||
r.EncodeInt(int64(x.DeschedulingInterval))
|
r.EncodeInt(int64(x.DeschedulingInterval))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("DeschedulingInterval"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `DeschedulingInterval`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym11 := z.EncBinary()
|
yym11 := z.EncBinary()
|
||||||
_ = yym11
|
_ = yym11
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.EncExt(x.DeschedulingInterval) {
|
} else if yyxt11 := z.Extension(z.I2Rtid(x.DeschedulingInterval)); yyxt11 != nil {
|
||||||
|
z.EncExtension(x.DeschedulingInterval, yyxt11)
|
||||||
} else {
|
} else {
|
||||||
r.EncodeInt(int64(x.DeschedulingInterval))
|
r.EncodeInt(int64(x.DeschedulingInterval))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
yym13 := z.EncBinary()
|
yym13 := z.EncBinary()
|
||||||
_ = yym13
|
_ = yym13
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.KubeconfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.KubeconfigFile))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("KubeconfigFile"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `KubeconfigFile`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym14 := z.EncBinary()
|
yym14 := z.EncBinary()
|
||||||
_ = yym14
|
_ = yym14
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.KubeconfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.KubeconfigFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
yym16 := z.EncBinary()
|
yym16 := z.EncBinary()
|
||||||
_ = yym16
|
_ = yym16
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.PolicyConfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.PolicyConfigFile))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("PolicyConfigFile"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `PolicyConfigFile`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym17 := z.EncBinary()
|
yym17 := z.EncBinary()
|
||||||
_ = yym17
|
_ = yym17
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.PolicyConfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.PolicyConfigFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
yym19 := z.EncBinary()
|
yym19 := z.EncBinary()
|
||||||
_ = yym19
|
_ = yym19
|
||||||
if false {
|
if false {
|
||||||
@@ -217,9 +215,9 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
r.EncodeBool(bool(x.DryRun))
|
r.EncodeBool(bool(x.DryRun))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("DryRun"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `DryRun`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym20 := z.EncBinary()
|
yym20 := z.EncBinary()
|
||||||
_ = yym20
|
_ = yym20
|
||||||
if false {
|
if false {
|
||||||
@@ -228,9 +226,47 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.WriteArrayElem()
|
||||||
|
yym22 := z.EncBinary()
|
||||||
|
_ = yym22
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferCcUTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
|
r.WriteMapElemKey()
|
||||||
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `NodeSelector`)
|
||||||
|
r.WriteMapElemValue()
|
||||||
|
yym23 := z.EncBinary()
|
||||||
|
_ = yym23
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferCcUTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if yyr2 || yy2arr2 {
|
||||||
|
r.WriteArrayElem()
|
||||||
|
yym25 := z.EncBinary()
|
||||||
|
_ = yym25
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeInt(int64(x.MaxNoOfPodsToEvictPerNode))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.WriteMapElemKey()
|
||||||
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `MaxNoOfPodsToEvictPerNode`)
|
||||||
|
r.WriteMapElemValue()
|
||||||
|
yym26 := z.EncBinary()
|
||||||
|
_ = yym26
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeInt(int64(x.MaxNoOfPodsToEvictPerNode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if yyr2 || yy2arr2 {
|
||||||
|
r.WriteArrayEnd()
|
||||||
|
} else {
|
||||||
|
r.WriteMapEnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,25 +279,26 @@ func (x *DeschedulerConfiguration) CodecDecodeSelf(d *codec1978.Decoder) {
|
|||||||
yym1 := z.DecBinary()
|
yym1 := z.DecBinary()
|
||||||
_ = yym1
|
_ = yym1
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(x) {
|
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||||
|
z.DecExtension(x, yyxt1)
|
||||||
} else {
|
} else {
|
||||||
yyct2 := r.ContainerType()
|
yyct2 := r.ContainerType()
|
||||||
if yyct2 == codecSelferValueTypeMap1234 {
|
if yyct2 == codecSelferValueTypeMap1234 {
|
||||||
yyl2 := r.ReadMapStart()
|
yyl2 := r.ReadMapStart()
|
||||||
if yyl2 == 0 {
|
if yyl2 == 0 {
|
||||||
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
|
r.ReadMapEnd()
|
||||||
} else {
|
} else {
|
||||||
x.codecDecodeSelfFromMap(yyl2, d)
|
x.codecDecodeSelfFromMap(yyl2, d)
|
||||||
}
|
}
|
||||||
} else if yyct2 == codecSelferValueTypeArray1234 {
|
} else if yyct2 == codecSelferValueTypeArray1234 {
|
||||||
yyl2 := r.ReadArrayStart()
|
yyl2 := r.ReadArrayStart()
|
||||||
if yyl2 == 0 {
|
if yyl2 == 0 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
} else {
|
} else {
|
||||||
x.codecDecodeSelfFromArray(yyl2, d)
|
x.codecDecodeSelfFromArray(yyl2, d)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
|
panic(errCodecSelferOnlyMapOrArrayEncodeToStruct1234)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,8 +307,6 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
var h codecSelfer1234
|
var h codecSelfer1234
|
||||||
z, r := codec1978.GenHelperDecoder(d)
|
z, r := codec1978.GenHelperDecoder(d)
|
||||||
_, _, _ = h, z, r
|
_, _, _ = h, z, r
|
||||||
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
|
|
||||||
_ = yys3Slc
|
|
||||||
var yyhl3 bool = l >= 0
|
var yyhl3 bool = l >= 0
|
||||||
for yyj3 := 0; ; yyj3++ {
|
for yyj3 := 0; ; yyj3++ {
|
||||||
if yyhl3 {
|
if yyhl3 {
|
||||||
@@ -283,10 +318,9 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerMapKey1234)
|
r.ReadMapElemKey()
|
||||||
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
|
yys3 := z.StringView(r.DecStructFieldKey(codecSelferValueTypeString1234, z.DecScratchArrayBuffer()))
|
||||||
yys3 := string(yys3Slc)
|
r.ReadMapElemValue()
|
||||||
z.DecSendContainerState(codecSelfer_containerMapValue1234)
|
|
||||||
switch yys3 {
|
switch yys3 {
|
||||||
case "kind":
|
case "kind":
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
@@ -320,7 +354,8 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
yym9 := z.DecBinary()
|
yym9 := z.DecBinary()
|
||||||
_ = yym9
|
_ = yym9
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(yyv8) {
|
} else if yyxt9 := z.Extension(z.I2Rtid(yyv8)); yyxt9 != nil {
|
||||||
|
z.DecExtension(yyv8, yyxt9)
|
||||||
} else {
|
} else {
|
||||||
*((*int64)(yyv8)) = int64(r.DecodeInt(64))
|
*((*int64)(yyv8)) = int64(r.DecodeInt(64))
|
||||||
}
|
}
|
||||||
@@ -361,102 +396,81 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
*((*bool)(yyv14)) = r.DecodeBool()
|
*((*bool)(yyv14)) = r.DecodeBool()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "NodeSelector":
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv16 := &x.NodeSelector
|
||||||
|
yym17 := z.DecBinary()
|
||||||
|
_ = yym17
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv16)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "MaxNoOfPodsToEvictPerNode":
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.MaxNoOfPodsToEvictPerNode = 0
|
||||||
|
} else {
|
||||||
|
yyv18 := &x.MaxNoOfPodsToEvictPerNode
|
||||||
|
yym19 := z.DecBinary()
|
||||||
|
_ = yym19
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*int)(yyv18)) = int(r.DecodeInt(codecSelferBitsize1234))
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
z.DecStructFieldNotFound(-1, yys3)
|
z.DecStructFieldNotFound(-1, yys3)
|
||||||
} // end switch yys3
|
} // end switch yys3
|
||||||
} // end for yyj3
|
} // end for yyj3
|
||||||
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
|
r.ReadMapEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||||
var h codecSelfer1234
|
var h codecSelfer1234
|
||||||
z, r := codec1978.GenHelperDecoder(d)
|
z, r := codec1978.GenHelperDecoder(d)
|
||||||
_, _, _ = h, z, r
|
_, _, _ = h, z, r
|
||||||
var yyj16 int
|
var yyj20 int
|
||||||
var yyb16 bool
|
var yyb20 bool
|
||||||
var yyhl16 bool = l >= 0
|
var yyhl20 bool = l >= 0
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.Kind = ""
|
x.Kind = ""
|
||||||
} else {
|
} else {
|
||||||
yyv17 := &x.Kind
|
yyv21 := &x.Kind
|
||||||
yym18 := z.DecBinary()
|
|
||||||
_ = yym18
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv17)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.APIVersion = ""
|
|
||||||
} else {
|
|
||||||
yyv19 := &x.APIVersion
|
|
||||||
yym20 := z.DecBinary()
|
|
||||||
_ = yym20
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv19)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.DeschedulingInterval = 0
|
|
||||||
} else {
|
|
||||||
yyv21 := &x.DeschedulingInterval
|
|
||||||
yym22 := z.DecBinary()
|
yym22 := z.DecBinary()
|
||||||
_ = yym22
|
_ = yym22
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(yyv21) {
|
|
||||||
} else {
|
} else {
|
||||||
*((*int64)(yyv21)) = int64(r.DecodeInt(64))
|
*((*string)(yyv21)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.KubeconfigFile = ""
|
x.APIVersion = ""
|
||||||
} else {
|
} else {
|
||||||
yyv23 := &x.KubeconfigFile
|
yyv23 := &x.APIVersion
|
||||||
yym24 := z.DecBinary()
|
yym24 := z.DecBinary()
|
||||||
_ = yym24
|
_ = yym24
|
||||||
if false {
|
if false {
|
||||||
@@ -464,62 +478,152 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
*((*string)(yyv23)) = r.DecodeString()
|
*((*string)(yyv23)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.PolicyConfigFile = ""
|
x.DeschedulingInterval = 0
|
||||||
} else {
|
} else {
|
||||||
yyv25 := &x.PolicyConfigFile
|
yyv25 := &x.DeschedulingInterval
|
||||||
yym26 := z.DecBinary()
|
yym26 := z.DecBinary()
|
||||||
_ = yym26
|
_ = yym26
|
||||||
if false {
|
if false {
|
||||||
|
} else if yyxt26 := z.Extension(z.I2Rtid(yyv25)); yyxt26 != nil {
|
||||||
|
z.DecExtension(yyv25, yyxt26)
|
||||||
} else {
|
} else {
|
||||||
*((*string)(yyv25)) = r.DecodeString()
|
*((*int64)(yyv25)) = int64(r.DecodeInt(64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.DryRun = false
|
x.KubeconfigFile = ""
|
||||||
} else {
|
} else {
|
||||||
yyv27 := &x.DryRun
|
yyv27 := &x.KubeconfigFile
|
||||||
yym28 := z.DecBinary()
|
yym28 := z.DecBinary()
|
||||||
_ = yym28
|
_ = yym28
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
*((*bool)(yyv27)) = r.DecodeBool()
|
*((*string)(yyv27)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.PolicyConfigFile = ""
|
||||||
|
} else {
|
||||||
|
yyv29 := &x.PolicyConfigFile
|
||||||
|
yym30 := z.DecBinary()
|
||||||
|
_ = yym30
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv29)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.DryRun = false
|
||||||
|
} else {
|
||||||
|
yyv31 := &x.DryRun
|
||||||
|
yym32 := z.DecBinary()
|
||||||
|
_ = yym32
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*bool)(yyv31)) = r.DecodeBool()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv33 := &x.NodeSelector
|
||||||
|
yym34 := z.DecBinary()
|
||||||
|
_ = yym34
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv33)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.MaxNoOfPodsToEvictPerNode = 0
|
||||||
|
} else {
|
||||||
|
yyv35 := &x.MaxNoOfPodsToEvictPerNode
|
||||||
|
yym36 := z.DecBinary()
|
||||||
|
_ = yym36
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*int)(yyv35)) = int(r.DecodeInt(codecSelferBitsize1234))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
z.DecStructFieldNotFound(yyj16-1, "")
|
z.DecStructFieldNotFound(yyj20-1, "")
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
type DeschedulerConfiguration struct {
|
type DeschedulerConfiguration struct {
|
||||||
metav1.TypeMeta
|
metav1.TypeMeta
|
||||||
|
|
||||||
@@ -37,4 +39,10 @@ type DeschedulerConfiguration struct {
|
|||||||
|
|
||||||
// Dry run
|
// Dry run
|
||||||
DryRun bool
|
DryRun bool
|
||||||
|
|
||||||
|
// Node selectors
|
||||||
|
NodeSelector string
|
||||||
|
|
||||||
|
// MaxNoOfPodsToEvictPerNode restricts maximum of pods to be evicted per node.
|
||||||
|
MaxNoOfPodsToEvictPerNode int
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ************************************************************
|
// Code generated by codecgen - DO NOT EDIT.
|
||||||
// DO NOT EDIT.
|
|
||||||
// THIS FILE IS AUTO-GENERATED BY codecgen.
|
|
||||||
// ************************************************************
|
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
@@ -33,31 +30,29 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// ----- content types ----
|
// ----- content types ----
|
||||||
codecSelferC_UTF81234 = 1
|
codecSelferCcUTF81234 = 1
|
||||||
codecSelferC_RAW1234 = 0
|
codecSelferCcRAW1234 = 0
|
||||||
// ----- value types used ----
|
// ----- value types used ----
|
||||||
codecSelferValueTypeArray1234 = 10
|
codecSelferValueTypeArray1234 = 10
|
||||||
codecSelferValueTypeMap1234 = 9
|
codecSelferValueTypeMap1234 = 9
|
||||||
// ----- containerStateValues ----
|
codecSelferValueTypeString1234 = 6
|
||||||
codecSelfer_containerMapKey1234 = 2
|
codecSelferValueTypeInt1234 = 2
|
||||||
codecSelfer_containerMapValue1234 = 3
|
codecSelferValueTypeUint1234 = 3
|
||||||
codecSelfer_containerMapEnd1234 = 4
|
codecSelferValueTypeFloat1234 = 4
|
||||||
codecSelfer_containerArrayElem1234 = 6
|
|
||||||
codecSelfer_containerArrayEnd1234 = 7
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
codecSelferBitsize1234 = uint8(reflect.TypeOf(uint(0)).Bits())
|
codecSelferBitsize1234 = uint8(reflect.TypeOf(uint(0)).Bits())
|
||||||
codecSelferOnlyMapOrArrayEncodeToStructErr1234 = errors.New(`only encoded map or array can be decoded into a struct`)
|
errCodecSelferOnlyMapOrArrayEncodeToStruct1234 = errors.New(`only encoded map or array can be decoded into a struct`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type codecSelfer1234 struct{}
|
type codecSelfer1234 struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if codec1978.GenVersion != 5 {
|
if codec1978.GenVersion != 8 {
|
||||||
_, file, _, _ := runtime.Caller(0)
|
_, file, _, _ := runtime.Caller(0)
|
||||||
err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v",
|
err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v",
|
||||||
5, codec1978.GenVersion, file)
|
8, codec1978.GenVersion, file)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if false { // reference the types, but skip this branch at build/run time
|
if false { // reference the types, but skip this branch at build/run time
|
||||||
@@ -77,88 +72,92 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
yym1 := z.EncBinary()
|
yym1 := z.EncBinary()
|
||||||
_ = yym1
|
_ = yym1
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.EncExt(x) {
|
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||||
|
z.EncExtension(x, yyxt1)
|
||||||
} else {
|
} else {
|
||||||
yysep2 := !z.EncBinary()
|
yysep2 := !z.EncBinary()
|
||||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||||
var yyq2 [6]bool
|
var yyq2 [8]bool
|
||||||
_, _, _ = yysep2, yyq2, yy2arr2
|
_ = yyq2
|
||||||
|
_, _ = yysep2, yy2arr2
|
||||||
const yyr2 bool = false
|
const yyr2 bool = false
|
||||||
yyq2[0] = x.Kind != ""
|
yyq2[0] = x.Kind != ""
|
||||||
yyq2[1] = x.APIVersion != ""
|
yyq2[1] = x.APIVersion != ""
|
||||||
yyq2[2] = x.DeschedulingInterval != 0
|
yyq2[2] = x.DeschedulingInterval != 0
|
||||||
yyq2[4] = x.PolicyConfigFile != ""
|
yyq2[4] = x.PolicyConfigFile != ""
|
||||||
yyq2[5] = x.DryRun != false
|
yyq2[5] = x.DryRun != false
|
||||||
var yynn2 int
|
yyq2[6] = x.NodeSelector != ""
|
||||||
|
yyq2[7] = x.MaxNoOfPodsToEvictPerNode != 0
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
r.EncodeArrayStart(6)
|
r.WriteArrayStart(8)
|
||||||
} else {
|
} else {
|
||||||
yynn2 = 1
|
var yynn2 = 1
|
||||||
for _, b := range yyq2 {
|
for _, b := range yyq2 {
|
||||||
if b {
|
if b {
|
||||||
yynn2++
|
yynn2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.EncodeMapStart(yynn2)
|
r.WriteMapStart(yynn2)
|
||||||
yynn2 = 0
|
yynn2 = 0
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[0] {
|
if yyq2[0] {
|
||||||
yym4 := z.EncBinary()
|
yym4 := z.EncBinary()
|
||||||
_ = yym4
|
_ = yym4
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
|
r.EncodeString(codecSelferCcUTF81234, string(x.Kind))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, "")
|
r.EncodeString(codecSelferCcUTF81234, "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[0] {
|
if yyq2[0] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("kind"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `kind`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym5 := z.EncBinary()
|
yym5 := z.EncBinary()
|
||||||
_ = yym5
|
_ = yym5
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
|
r.EncodeString(codecSelferCcUTF81234, string(x.Kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[1] {
|
if yyq2[1] {
|
||||||
yym7 := z.EncBinary()
|
yym7 := z.EncBinary()
|
||||||
_ = yym7
|
_ = yym7
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
|
r.EncodeString(codecSelferCcUTF81234, string(x.APIVersion))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, "")
|
r.EncodeString(codecSelferCcUTF81234, "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[1] {
|
if yyq2[1] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("apiVersion"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `apiVersion`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym8 := z.EncBinary()
|
yym8 := z.EncBinary()
|
||||||
_ = yym8
|
_ = yym8
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
|
r.EncodeString(codecSelferCcUTF81234, string(x.APIVersion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[2] {
|
if yyq2[2] {
|
||||||
yym10 := z.EncBinary()
|
yym10 := z.EncBinary()
|
||||||
_ = yym10
|
_ = yym10
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.EncExt(x.DeschedulingInterval) {
|
} else if yyxt10 := z.Extension(z.I2Rtid(x.DeschedulingInterval)); yyxt10 != nil {
|
||||||
|
z.EncExtension(x.DeschedulingInterval, yyxt10)
|
||||||
} else {
|
} else {
|
||||||
r.EncodeInt(int64(x.DeschedulingInterval))
|
r.EncodeInt(int64(x.DeschedulingInterval))
|
||||||
}
|
}
|
||||||
@@ -167,64 +166,65 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[2] {
|
if yyq2[2] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("deschedulingInterval"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `deschedulingInterval`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym11 := z.EncBinary()
|
yym11 := z.EncBinary()
|
||||||
_ = yym11
|
_ = yym11
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.EncExt(x.DeschedulingInterval) {
|
} else if yyxt11 := z.Extension(z.I2Rtid(x.DeschedulingInterval)); yyxt11 != nil {
|
||||||
|
z.EncExtension(x.DeschedulingInterval, yyxt11)
|
||||||
} else {
|
} else {
|
||||||
r.EncodeInt(int64(x.DeschedulingInterval))
|
r.EncodeInt(int64(x.DeschedulingInterval))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
yym13 := z.EncBinary()
|
yym13 := z.EncBinary()
|
||||||
_ = yym13
|
_ = yym13
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.KubeconfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.KubeconfigFile))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("kubeconfigFile"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `kubeconfigFile`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym14 := z.EncBinary()
|
yym14 := z.EncBinary()
|
||||||
_ = yym14
|
_ = yym14
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.KubeconfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.KubeconfigFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[4] {
|
if yyq2[4] {
|
||||||
yym16 := z.EncBinary()
|
yym16 := z.EncBinary()
|
||||||
_ = yym16
|
_ = yym16
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.PolicyConfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.PolicyConfigFile))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, "")
|
r.EncodeString(codecSelferCcUTF81234, "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[4] {
|
if yyq2[4] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("policyConfigFile"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `policyConfigFile`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym17 := z.EncBinary()
|
yym17 := z.EncBinary()
|
||||||
_ = yym17
|
_ = yym17
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
r.EncodeString(codecSelferC_UTF81234, string(x.PolicyConfigFile))
|
r.EncodeString(codecSelferCcUTF81234, string(x.PolicyConfigFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
r.WriteArrayElem()
|
||||||
if yyq2[5] {
|
if yyq2[5] {
|
||||||
yym19 := z.EncBinary()
|
yym19 := z.EncBinary()
|
||||||
_ = yym19
|
_ = yym19
|
||||||
@@ -237,9 +237,9 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if yyq2[5] {
|
if yyq2[5] {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
r.WriteMapElemKey()
|
||||||
r.EncodeString(codecSelferC_UTF81234, string("dryRun"))
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `dryRun`)
|
||||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
r.WriteMapElemValue()
|
||||||
yym20 := z.EncBinary()
|
yym20 := z.EncBinary()
|
||||||
_ = yym20
|
_ = yym20
|
||||||
if false {
|
if false {
|
||||||
@@ -249,9 +249,59 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.WriteArrayElem()
|
||||||
|
if yyq2[6] {
|
||||||
|
yym22 := z.EncBinary()
|
||||||
|
_ = yym22
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferCcUTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferCcUTF81234, "")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
|
if yyq2[6] {
|
||||||
|
r.WriteMapElemKey()
|
||||||
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `nodeSelector`)
|
||||||
|
r.WriteMapElemValue()
|
||||||
|
yym23 := z.EncBinary()
|
||||||
|
_ = yym23
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferCcUTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if yyr2 || yy2arr2 {
|
||||||
|
r.WriteArrayElem()
|
||||||
|
if yyq2[7] {
|
||||||
|
yym25 := z.EncBinary()
|
||||||
|
_ = yym25
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeInt(int64(x.MaxNoOfPodsToEvictPerNode))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.EncodeInt(0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if yyq2[7] {
|
||||||
|
r.WriteMapElemKey()
|
||||||
|
r.EncStructFieldKey(codecSelferValueTypeString1234, `maxNoOfPodsToEvictPerNode`)
|
||||||
|
r.WriteMapElemValue()
|
||||||
|
yym26 := z.EncBinary()
|
||||||
|
_ = yym26
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeInt(int64(x.MaxNoOfPodsToEvictPerNode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if yyr2 || yy2arr2 {
|
||||||
|
r.WriteArrayEnd()
|
||||||
|
} else {
|
||||||
|
r.WriteMapEnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,25 +314,26 @@ func (x *DeschedulerConfiguration) CodecDecodeSelf(d *codec1978.Decoder) {
|
|||||||
yym1 := z.DecBinary()
|
yym1 := z.DecBinary()
|
||||||
_ = yym1
|
_ = yym1
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(x) {
|
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||||
|
z.DecExtension(x, yyxt1)
|
||||||
} else {
|
} else {
|
||||||
yyct2 := r.ContainerType()
|
yyct2 := r.ContainerType()
|
||||||
if yyct2 == codecSelferValueTypeMap1234 {
|
if yyct2 == codecSelferValueTypeMap1234 {
|
||||||
yyl2 := r.ReadMapStart()
|
yyl2 := r.ReadMapStart()
|
||||||
if yyl2 == 0 {
|
if yyl2 == 0 {
|
||||||
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
|
r.ReadMapEnd()
|
||||||
} else {
|
} else {
|
||||||
x.codecDecodeSelfFromMap(yyl2, d)
|
x.codecDecodeSelfFromMap(yyl2, d)
|
||||||
}
|
}
|
||||||
} else if yyct2 == codecSelferValueTypeArray1234 {
|
} else if yyct2 == codecSelferValueTypeArray1234 {
|
||||||
yyl2 := r.ReadArrayStart()
|
yyl2 := r.ReadArrayStart()
|
||||||
if yyl2 == 0 {
|
if yyl2 == 0 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
} else {
|
} else {
|
||||||
x.codecDecodeSelfFromArray(yyl2, d)
|
x.codecDecodeSelfFromArray(yyl2, d)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
|
panic(errCodecSelferOnlyMapOrArrayEncodeToStruct1234)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,8 +342,6 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
var h codecSelfer1234
|
var h codecSelfer1234
|
||||||
z, r := codec1978.GenHelperDecoder(d)
|
z, r := codec1978.GenHelperDecoder(d)
|
||||||
_, _, _ = h, z, r
|
_, _, _ = h, z, r
|
||||||
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
|
|
||||||
_ = yys3Slc
|
|
||||||
var yyhl3 bool = l >= 0
|
var yyhl3 bool = l >= 0
|
||||||
for yyj3 := 0; ; yyj3++ {
|
for yyj3 := 0; ; yyj3++ {
|
||||||
if yyhl3 {
|
if yyhl3 {
|
||||||
@@ -304,10 +353,9 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerMapKey1234)
|
r.ReadMapElemKey()
|
||||||
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
|
yys3 := z.StringView(r.DecStructFieldKey(codecSelferValueTypeString1234, z.DecScratchArrayBuffer()))
|
||||||
yys3 := string(yys3Slc)
|
r.ReadMapElemValue()
|
||||||
z.DecSendContainerState(codecSelfer_containerMapValue1234)
|
|
||||||
switch yys3 {
|
switch yys3 {
|
||||||
case "kind":
|
case "kind":
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
@@ -341,7 +389,8 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
yym9 := z.DecBinary()
|
yym9 := z.DecBinary()
|
||||||
_ = yym9
|
_ = yym9
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(yyv8) {
|
} else if yyxt9 := z.Extension(z.I2Rtid(yyv8)); yyxt9 != nil {
|
||||||
|
z.DecExtension(yyv8, yyxt9)
|
||||||
} else {
|
} else {
|
||||||
*((*int64)(yyv8)) = int64(r.DecodeInt(64))
|
*((*int64)(yyv8)) = int64(r.DecodeInt(64))
|
||||||
}
|
}
|
||||||
@@ -382,102 +431,81 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
*((*bool)(yyv14)) = r.DecodeBool()
|
*((*bool)(yyv14)) = r.DecodeBool()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "nodeSelector":
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv16 := &x.NodeSelector
|
||||||
|
yym17 := z.DecBinary()
|
||||||
|
_ = yym17
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv16)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "maxNoOfPodsToEvictPerNode":
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.MaxNoOfPodsToEvictPerNode = 0
|
||||||
|
} else {
|
||||||
|
yyv18 := &x.MaxNoOfPodsToEvictPerNode
|
||||||
|
yym19 := z.DecBinary()
|
||||||
|
_ = yym19
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*int)(yyv18)) = int(r.DecodeInt(codecSelferBitsize1234))
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
z.DecStructFieldNotFound(-1, yys3)
|
z.DecStructFieldNotFound(-1, yys3)
|
||||||
} // end switch yys3
|
} // end switch yys3
|
||||||
} // end for yyj3
|
} // end for yyj3
|
||||||
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
|
r.ReadMapEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||||
var h codecSelfer1234
|
var h codecSelfer1234
|
||||||
z, r := codec1978.GenHelperDecoder(d)
|
z, r := codec1978.GenHelperDecoder(d)
|
||||||
_, _, _ = h, z, r
|
_, _, _ = h, z, r
|
||||||
var yyj16 int
|
var yyj20 int
|
||||||
var yyb16 bool
|
var yyb20 bool
|
||||||
var yyhl16 bool = l >= 0
|
var yyhl20 bool = l >= 0
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.Kind = ""
|
x.Kind = ""
|
||||||
} else {
|
} else {
|
||||||
yyv17 := &x.Kind
|
yyv21 := &x.Kind
|
||||||
yym18 := z.DecBinary()
|
|
||||||
_ = yym18
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv17)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.APIVersion = ""
|
|
||||||
} else {
|
|
||||||
yyv19 := &x.APIVersion
|
|
||||||
yym20 := z.DecBinary()
|
|
||||||
_ = yym20
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv19)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.DeschedulingInterval = 0
|
|
||||||
} else {
|
|
||||||
yyv21 := &x.DeschedulingInterval
|
|
||||||
yym22 := z.DecBinary()
|
yym22 := z.DecBinary()
|
||||||
_ = yym22
|
_ = yym22
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(yyv21) {
|
|
||||||
} else {
|
} else {
|
||||||
*((*int64)(yyv21)) = int64(r.DecodeInt(64))
|
*((*string)(yyv21)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.KubeconfigFile = ""
|
x.APIVersion = ""
|
||||||
} else {
|
} else {
|
||||||
yyv23 := &x.KubeconfigFile
|
yyv23 := &x.APIVersion
|
||||||
yym24 := z.DecBinary()
|
yym24 := z.DecBinary()
|
||||||
_ = yym24
|
_ = yym24
|
||||||
if false {
|
if false {
|
||||||
@@ -485,62 +513,152 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
*((*string)(yyv23)) = r.DecodeString()
|
*((*string)(yyv23)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.PolicyConfigFile = ""
|
x.DeschedulingInterval = 0
|
||||||
} else {
|
} else {
|
||||||
yyv25 := &x.PolicyConfigFile
|
yyv25 := &x.DeschedulingInterval
|
||||||
yym26 := z.DecBinary()
|
yym26 := z.DecBinary()
|
||||||
_ = yym26
|
_ = yym26
|
||||||
if false {
|
if false {
|
||||||
|
} else if yyxt26 := z.Extension(z.I2Rtid(yyv25)); yyxt26 != nil {
|
||||||
|
z.DecExtension(yyv25, yyxt26)
|
||||||
} else {
|
} else {
|
||||||
*((*string)(yyv25)) = r.DecodeString()
|
*((*int64)(yyv25)) = int64(r.DecodeInt(64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.DryRun = false
|
x.KubeconfigFile = ""
|
||||||
} else {
|
} else {
|
||||||
yyv27 := &x.DryRun
|
yyv27 := &x.KubeconfigFile
|
||||||
yym28 := z.DecBinary()
|
yym28 := z.DecBinary()
|
||||||
_ = yym28
|
_ = yym28
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
*((*bool)(yyv27)) = r.DecodeBool()
|
*((*string)(yyv27)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.PolicyConfigFile = ""
|
||||||
|
} else {
|
||||||
|
yyv29 := &x.PolicyConfigFile
|
||||||
|
yym30 := z.DecBinary()
|
||||||
|
_ = yym30
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv29)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.DryRun = false
|
||||||
|
} else {
|
||||||
|
yyv31 := &x.DryRun
|
||||||
|
yym32 := z.DecBinary()
|
||||||
|
_ = yym32
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*bool)(yyv31)) = r.DecodeBool()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv33 := &x.NodeSelector
|
||||||
|
yym34 := z.DecBinary()
|
||||||
|
_ = yym34
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv33)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj20++
|
||||||
|
if yyhl20 {
|
||||||
|
yyb20 = yyj20 > l
|
||||||
|
} else {
|
||||||
|
yyb20 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb20 {
|
||||||
|
r.ReadArrayEnd()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.ReadArrayElem()
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.MaxNoOfPodsToEvictPerNode = 0
|
||||||
|
} else {
|
||||||
|
yyv35 := &x.MaxNoOfPodsToEvictPerNode
|
||||||
|
yym36 := z.DecBinary()
|
||||||
|
_ = yym36
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*int)(yyv35)) = int(r.DecodeInt(codecSelferBitsize1234))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
yyj16++
|
yyj20++
|
||||||
if yyhl16 {
|
if yyhl20 {
|
||||||
yyb16 = yyj16 > l
|
yyb20 = yyj20 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb20 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb20 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
r.ReadArrayElem()
|
||||||
z.DecStructFieldNotFound(yyj16-1, "")
|
z.DecStructFieldNotFound(yyj20-1, "")
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
r.ReadArrayEnd()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
type DeschedulerConfiguration struct {
|
type DeschedulerConfiguration struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
@@ -37,4 +39,10 @@ type DeschedulerConfiguration struct {
|
|||||||
|
|
||||||
// Dry run
|
// Dry run
|
||||||
DryRun bool `json:"dryRun,omitempty"`
|
DryRun bool `json:"dryRun,omitempty"`
|
||||||
|
|
||||||
|
// Node selectors
|
||||||
|
NodeSelector string `json:"nodeSelector,omitempty"`
|
||||||
|
|
||||||
|
// MaxNoOfPodsToEvictPerNode restricts maximum of pods to be evicted per node.
|
||||||
|
MaxNoOfPodsToEvictPerNode int `json:"maxNoOfPodsToEvictPerNode,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,14 +21,15 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
time "time"
|
||||||
|
|
||||||
componentconfig "github.com/kubernetes-incubator/descheduler/pkg/apis/componentconfig"
|
componentconfig "github.com/kubernetes-incubator/descheduler/pkg/apis/componentconfig"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
time "time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
SchemeBuilder.Register(RegisterConversions)
|
localSchemeBuilder.Register(RegisterConversions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterConversions adds conversion functions to the given scheme.
|
// RegisterConversions adds conversion functions to the given scheme.
|
||||||
@@ -45,6 +46,8 @@ func autoConvert_v1alpha1_DeschedulerConfiguration_To_componentconfig_Deschedule
|
|||||||
out.KubeconfigFile = in.KubeconfigFile
|
out.KubeconfigFile = in.KubeconfigFile
|
||||||
out.PolicyConfigFile = in.PolicyConfigFile
|
out.PolicyConfigFile = in.PolicyConfigFile
|
||||||
out.DryRun = in.DryRun
|
out.DryRun = in.DryRun
|
||||||
|
out.NodeSelector = in.NodeSelector
|
||||||
|
out.MaxNoOfPodsToEvictPerNode = in.MaxNoOfPodsToEvictPerNode
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +61,8 @@ func autoConvert_componentconfig_DeschedulerConfiguration_To_v1alpha1_Deschedule
|
|||||||
out.KubeconfigFile = in.KubeconfigFile
|
out.KubeconfigFile = in.KubeconfigFile
|
||||||
out.PolicyConfigFile = in.PolicyConfigFile
|
out.PolicyConfigFile = in.PolicyConfigFile
|
||||||
out.DryRun = in.DryRun
|
out.DryRun = in.DryRun
|
||||||
|
out.NodeSelector = in.NodeSelector
|
||||||
|
out.MaxNoOfPodsToEvictPerNode = in.MaxNoOfPodsToEvictPerNode
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,29 +21,31 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
SchemeBuilder.Register(RegisterDeepCopies)
|
func (in *DeschedulerConfiguration) DeepCopyInto(out *DeschedulerConfiguration) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerConfiguration.
|
||||||
// to allow building arbitrary schemes.
|
func (in *DeschedulerConfiguration) DeepCopy() *DeschedulerConfiguration {
|
||||||
func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
if in == nil {
|
||||||
return scheme.AddGeneratedDeepCopyFuncs(
|
return nil
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_DeschedulerConfiguration, InType: reflect.TypeOf(&DeschedulerConfiguration{})},
|
}
|
||||||
)
|
out := new(DeschedulerConfiguration)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_v1alpha1_DeschedulerConfiguration is an autogenerated deepcopy function.
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
func DeepCopy_v1alpha1_DeschedulerConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *DeschedulerConfiguration) DeepCopyObject() runtime.Object {
|
||||||
{
|
if c := in.DeepCopy(); c != nil {
|
||||||
in := in.(*DeschedulerConfiguration)
|
return c
|
||||||
out := out.(*DeschedulerConfiguration)
|
} else {
|
||||||
*out = *in
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,29 +21,31 @@ limitations under the License.
|
|||||||
package componentconfig
|
package componentconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
SchemeBuilder.Register(RegisterDeepCopies)
|
func (in *DeschedulerConfiguration) DeepCopyInto(out *DeschedulerConfiguration) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerConfiguration.
|
||||||
// to allow building arbitrary schemes.
|
func (in *DeschedulerConfiguration) DeepCopy() *DeschedulerConfiguration {
|
||||||
func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
if in == nil {
|
||||||
return scheme.AddGeneratedDeepCopyFuncs(
|
return nil
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_DeschedulerConfiguration, InType: reflect.TypeOf(&DeschedulerConfiguration{})},
|
}
|
||||||
)
|
out := new(DeschedulerConfiguration)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy_componentconfig_DeschedulerConfiguration is an autogenerated deepcopy function.
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
func DeepCopy_componentconfig_DeschedulerConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
|
func (in *DeschedulerConfiguration) DeepCopyObject() runtime.Object {
|
||||||
{
|
if c := in.DeepCopy(); c != nil {
|
||||||
in := in.(*DeschedulerConfiguration)
|
return c
|
||||||
out := out.(*DeschedulerConfiguration)
|
} else {
|
||||||
*out = *in
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ package client
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateClient(kubeconfig string) (clientset.Interface, error) {
|
func CreateClient(kubeconfig string) (clientset.Interface, error) {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package descheduler
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/client"
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/client"
|
||||||
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
||||||
@@ -39,22 +41,30 @@ func Run(rs *options.DeschedulerServer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if deschedulerPolicy == nil {
|
if deschedulerPolicy == nil {
|
||||||
return fmt.Errorf("\ndeschedulerPolicy is nil\n")
|
return fmt.Errorf("deschedulerPolicy is nil")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
evictionPolicyGroupVersion, err := eutils.SupportEviction(rs.Client)
|
evictionPolicyGroupVersion, err := eutils.SupportEviction(rs.Client)
|
||||||
if err != nil || len(evictionPolicyGroupVersion) == 0 {
|
if err != nil || len(evictionPolicyGroupVersion) == 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
stopChannel := make(chan struct{})
|
stopChannel := make(chan struct{})
|
||||||
nodes, err := nodeutil.ReadyNodes(rs.Client, stopChannel)
|
nodes, err := nodeutil.ReadyNodes(rs.Client, rs.NodeSelector, stopChannel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
strategies.RemoveDuplicatePods(rs, deschedulerPolicy.Strategies["RemoveDuplicates"], evictionPolicyGroupVersion, nodes)
|
if len(nodes) <= 1 {
|
||||||
strategies.LowNodeUtilization(rs, deschedulerPolicy.Strategies["LowNodeUtilization"], evictionPolicyGroupVersion, nodes)
|
glog.V(1).Infof("The cluster size is 0 or 1 meaning eviction causes service disruption or degradation. So aborting..")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nodePodCount := strategies.InitializeNodePodCount(nodes)
|
||||||
|
strategies.RemoveDuplicatePods(rs, deschedulerPolicy.Strategies["RemoveDuplicates"], evictionPolicyGroupVersion, nodes, nodePodCount)
|
||||||
|
strategies.LowNodeUtilization(rs, deschedulerPolicy.Strategies["LowNodeUtilization"], evictionPolicyGroupVersion, nodes, nodePodCount)
|
||||||
|
strategies.RemovePodsViolatingInterPodAntiAffinity(rs, deschedulerPolicy.Strategies["RemovePodsViolatingInterPodAntiAffinity"], evictionPolicyGroupVersion, nodes, nodePodCount)
|
||||||
|
strategies.RemovePodsViolatingNodeAffinity(rs, deschedulerPolicy.Strategies["RemovePodsViolatingNodeAffinity"], evictionPolicyGroupVersion, nodes, nodePodCount)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ package evictions
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
policy "k8s.io/api/policy/v1beta1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
policy "k8s.io/kubernetes/pkg/apis/policy/v1beta1"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
|
||||||
|
|
||||||
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ package evictions
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kubernetes-incubator/descheduler/test"
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -17,35 +17,49 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/utils"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
|
||||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReadyNodes returns ready nodes irrespective of whether they are
|
// ReadyNodes returns ready nodes irrespective of whether they are
|
||||||
// schedulable or not.
|
// schedulable or not.
|
||||||
func ReadyNodes(client clientset.Interface, stopChannel <-chan struct{}) ([]*v1.Node, error) {
|
func ReadyNodes(client clientset.Interface, nodeSelector string, stopChannel <-chan struct{}) ([]*v1.Node, error) {
|
||||||
nl := GetNodeLister(client, stopChannel)
|
ns, err := labels.Parse(nodeSelector)
|
||||||
nodes, err := nl.List(labels.Everything())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Node{}, err
|
return []*v1.Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nodes []*v1.Node
|
||||||
|
nl := GetNodeLister(client, stopChannel)
|
||||||
|
if nl != nil {
|
||||||
|
// err is defined above
|
||||||
|
if nodes, err = nl.List(ns); err != nil {
|
||||||
|
return []*v1.Node{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
var err error
|
glog.V(2).Infof("node lister returned empty list, now fetch directly")
|
||||||
nItems, err := client.Core().Nodes().List(metav1.ListOptions{})
|
|
||||||
|
nItems, err := client.Core().Nodes().List(metav1.ListOptions{LabelSelector: nodeSelector})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Node{}, err
|
return []*v1.Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, _ := range nItems.Items {
|
if nItems == nil || len(nItems.Items) == 0 {
|
||||||
|
return []*v1.Node{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range nItems.Items {
|
||||||
node := nItems.Items[i]
|
node := nItems.Items[i]
|
||||||
nodes = append(nodes, &node)
|
nodes = append(nodes, &node)
|
||||||
}
|
}
|
||||||
@@ -61,15 +75,22 @@ func ReadyNodes(client clientset.Interface, stopChannel <-chan struct{}) ([]*v1.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetNodeLister(client clientset.Interface, stopChannel <-chan struct{}) corelisters.NodeLister {
|
func GetNodeLister(client clientset.Interface, stopChannel <-chan struct{}) corelisters.NodeLister {
|
||||||
|
if stopChannel == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
listWatcher := cache.NewListWatchFromClient(client.Core().RESTClient(), "nodes", v1.NamespaceAll, fields.Everything())
|
listWatcher := cache.NewListWatchFromClient(client.Core().RESTClient(), "nodes", v1.NamespaceAll, fields.Everything())
|
||||||
store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||||
nodeLister := corelisters.NewNodeLister(store)
|
nodeLister := corelisters.NewNodeLister(store)
|
||||||
reflector := cache.NewReflector(listWatcher, &v1.Node{}, store, time.Hour)
|
reflector := cache.NewReflector(listWatcher, &v1.Node{}, store, time.Hour)
|
||||||
reflector.RunUntil(stopChannel)
|
go reflector.Run(stopChannel)
|
||||||
|
|
||||||
|
// To give some time so that listing works, chosen randomly
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
return nodeLister
|
return nodeLister
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsReady checks if the descheduler could run against given node.
|
||||||
func IsReady(node *v1.Node) bool {
|
func IsReady(node *v1.Node) bool {
|
||||||
for i := range node.Status.Conditions {
|
for i := range node.Status.Conditions {
|
||||||
cond := &node.Status.Conditions[i]
|
cond := &node.Status.Conditions[i]
|
||||||
@@ -78,7 +99,7 @@ func IsReady(node *v1.Node) bool {
|
|||||||
// - NodeOutOfDisk condition status is ConditionFalse,
|
// - NodeOutOfDisk condition status is ConditionFalse,
|
||||||
// - NodeNetworkUnavailable condition status is ConditionFalse.
|
// - NodeNetworkUnavailable condition status is ConditionFalse.
|
||||||
if cond.Type == v1.NodeReady && cond.Status != v1.ConditionTrue {
|
if cond.Type == v1.NodeReady && cond.Status != v1.ConditionTrue {
|
||||||
fmt.Printf("Ignoring node %v with %v condition status %v", node.Name, cond.Type, cond.Status)
|
glog.V(1).Infof("Ignoring node %v with %v condition status %v", node.Name, cond.Type, cond.Status)
|
||||||
return false
|
return false
|
||||||
} /*else if cond.Type == v1.NodeOutOfDisk && cond.Status != v1.ConditionFalse {
|
} /*else if cond.Type == v1.NodeOutOfDisk && cond.Status != v1.ConditionFalse {
|
||||||
glog.V(4).Infof("Ignoring node %v with %v condition status %v", node.Name, cond.Type, cond.Status)
|
glog.V(4).Infof("Ignoring node %v with %v condition status %v", node.Name, cond.Type, cond.Status)
|
||||||
@@ -95,3 +116,52 @@ func IsReady(node *v1.Node) bool {
|
|||||||
}*/
|
}*/
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNodeUschedulable checks if the node is unschedulable. This is helper function to check only in case of
|
||||||
|
// underutilized node so that they won't be accounted for.
|
||||||
|
func IsNodeUschedulable(node *v1.Node) bool {
|
||||||
|
if node.Spec.Unschedulable {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodFitsAnyNode checks if the given pod fits any of the given nodes, based on
|
||||||
|
// multiple criteria, like, pod node selector matching the node label, node
|
||||||
|
// being schedulable or not.
|
||||||
|
func PodFitsAnyNode(pod *v1.Pod, nodes []*v1.Node) bool {
|
||||||
|
for _, node := range nodes {
|
||||||
|
|
||||||
|
ok, err := utils.PodMatchNodeSelector(pod, node)
|
||||||
|
if err != nil || !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
if !IsNodeUschedulable(node) {
|
||||||
|
glog.V(2).Infof("Pod %v can possibly be scheduled on %v", pod.Name, node.Name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodFitsCurrentNode checks if the given pod fits on the given node if the pod
|
||||||
|
// node selector matches the node label.
|
||||||
|
func PodFitsCurrentNode(pod *v1.Pod, node *v1.Node) bool {
|
||||||
|
ok, err := utils.PodMatchNodeSelector(pod, node)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
glog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
glog.V(1).Infof("Pod %v does not fit on node %v", pod.Name, node.Name)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(3).Infof("Pod %v fits on node %v", pod.Name, node.Name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,18 +17,15 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/test"
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/api/core/v1"
|
||||||
core "k8s.io/client-go/testing"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadyNodes(t *testing.T) {
|
func TestReadyNodes(t *testing.T) {
|
||||||
fakeClient := &fake.Clientset{}
|
|
||||||
node1 := test.BuildTestNode("node1", 1000, 2000, 9)
|
node1 := test.BuildTestNode("node1", 1000, 2000, 9)
|
||||||
node1.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}
|
node1.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}
|
||||||
node2 := test.BuildTestNode("node2", 1000, 2000, 9)
|
node2 := test.BuildTestNode("node2", 1000, 2000, 9)
|
||||||
@@ -41,25 +38,6 @@ func TestReadyNodes(t *testing.T) {
|
|||||||
node6 := test.BuildTestNode("node6", 1000, 2000, 9)
|
node6 := test.BuildTestNode("node6", 1000, 2000, 9)
|
||||||
node6.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}}
|
node6.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}}
|
||||||
|
|
||||||
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
|
||||||
getAction := action.(core.GetAction)
|
|
||||||
switch getAction.GetName() {
|
|
||||||
case node1.Name:
|
|
||||||
return true, node1, nil
|
|
||||||
case node2.Name:
|
|
||||||
return true, node2, nil
|
|
||||||
case node3.Name:
|
|
||||||
return true, node3, nil
|
|
||||||
case node4.Name:
|
|
||||||
return true, node4, nil
|
|
||||||
case node5.Name:
|
|
||||||
return true, node5, nil
|
|
||||||
case node6.Name:
|
|
||||||
return true, node6, nil
|
|
||||||
}
|
|
||||||
return true, nil, fmt.Errorf("Wrong node: %v", getAction.GetName())
|
|
||||||
})
|
|
||||||
|
|
||||||
if !IsReady(node1) {
|
if !IsReady(node1) {
|
||||||
t.Errorf("Expected %v to be ready", node1.Name)
|
t.Errorf("Expected %v to be ready", node1.Name)
|
||||||
}
|
}
|
||||||
@@ -80,3 +58,290 @@ func TestReadyNodes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadyNodesWithNodeSelector(t *testing.T) {
|
||||||
|
node1 := test.BuildTestNode("node1", 1000, 2000, 9)
|
||||||
|
node1.Labels = map[string]string{"type": "compute"}
|
||||||
|
node2 := test.BuildTestNode("node2", 1000, 2000, 9)
|
||||||
|
node2.Labels = map[string]string{"type": "infra"}
|
||||||
|
|
||||||
|
fakeClient := fake.NewSimpleClientset(node1, node2)
|
||||||
|
nodeSelector := "type=compute"
|
||||||
|
nodes, _ := ReadyNodes(fakeClient, nodeSelector, nil)
|
||||||
|
|
||||||
|
if nodes[0].Name != "node1" {
|
||||||
|
t.Errorf("Expected node1, got %s", nodes[0].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsNodeUschedulable(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
node *v1.Node
|
||||||
|
IsUnSchedulable bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "Node is expected to be schedulable",
|
||||||
|
node: &v1.Node{
|
||||||
|
Spec: v1.NodeSpec{Unschedulable: false},
|
||||||
|
},
|
||||||
|
IsUnSchedulable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Node is not expected to be schedulable because of unschedulable field",
|
||||||
|
node: &v1.Node{
|
||||||
|
Spec: v1.NodeSpec{Unschedulable: true},
|
||||||
|
},
|
||||||
|
IsUnSchedulable: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
actualUnSchedulable := IsNodeUschedulable(test.node)
|
||||||
|
if actualUnSchedulable != test.IsUnSchedulable {
|
||||||
|
t.Errorf("Test %#v failed", test.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPodFitsCurrentNode(t *testing.T) {
|
||||||
|
|
||||||
|
nodeLabelKey := "kubernetes.io/desiredNode"
|
||||||
|
nodeLabelValue := "yes"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
pod *v1.Pod
|
||||||
|
node *v1.Node
|
||||||
|
success bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "Pod with nodeAffinity set, expected to fit the node",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Affinity: &v1.Affinity{
|
||||||
|
NodeAffinity: &v1.NodeAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||||
|
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: nodeLabelKey,
|
||||||
|
Operator: "In",
|
||||||
|
Values: []string{
|
||||||
|
nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
node: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Pod with nodeAffinity set, not expected to fit the node",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Affinity: &v1.Affinity{
|
||||||
|
NodeAffinity: &v1.NodeAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||||
|
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: nodeLabelKey,
|
||||||
|
Operator: "In",
|
||||||
|
Values: []string{
|
||||||
|
nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
node: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: "no",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
actual := PodFitsCurrentNode(tc.pod, tc.node)
|
||||||
|
if actual != tc.success {
|
||||||
|
t.Errorf("Test %#v failed", tc.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPodFitsAnyNode(t *testing.T) {
|
||||||
|
|
||||||
|
nodeLabelKey := "kubernetes.io/desiredNode"
|
||||||
|
nodeLabelValue := "yes"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
pod *v1.Pod
|
||||||
|
nodes []*v1.Node
|
||||||
|
success bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "Pod expected to fit one of the nodes",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Affinity: &v1.Affinity{
|
||||||
|
NodeAffinity: &v1.NodeAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||||
|
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: nodeLabelKey,
|
||||||
|
Operator: "In",
|
||||||
|
Values: []string{
|
||||||
|
nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nodes: []*v1.Node{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: "no",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Pod expected to fit none of the nodes",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Affinity: &v1.Affinity{
|
||||||
|
NodeAffinity: &v1.NodeAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||||
|
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: nodeLabelKey,
|
||||||
|
Operator: "In",
|
||||||
|
Values: []string{
|
||||||
|
nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nodes: []*v1.Node{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: "unfit1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: "unfit2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Nodes are unschedulable but labels match, should fail",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Affinity: &v1.Affinity{
|
||||||
|
NodeAffinity: &v1.NodeAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||||
|
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: nodeLabelKey,
|
||||||
|
Operator: "In",
|
||||||
|
Values: []string{
|
||||||
|
nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nodes: []*v1.Node{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: v1.NodeSpec{
|
||||||
|
Unschedulable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
nodeLabelKey: "no",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
actual := PodFitsAnyNode(tc.pod, tc.nodes)
|
||||||
|
if actual != tc.success {
|
||||||
|
t.Errorf("Test %#v failed", tc.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,19 +17,74 @@ limitations under the License.
|
|||||||
package pod
|
package pod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
|
||||||
"k8s.io/kubernetes/pkg/api/v1/helper/qos"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/types"
|
"k8s.io/kubernetes/pkg/kubelet/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// checkLatencySensitiveResourcesForAContainer checks if there are any latency sensitive resources like GPUs.
|
||||||
|
func checkLatencySensitiveResourcesForAContainer(rl v1.ResourceList) bool {
|
||||||
|
if rl == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for rName := range rl {
|
||||||
|
if rName == v1.ResourceNvidiaGPU {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// TODO: Add support for other high value resources like hugepages etc. once kube is rebased to 1.8.
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLatencySensitivePod checks if a pod consumes high value devices like GPUs, hugepages or when cpu pinning enabled.
|
||||||
|
func IsLatencySensitivePod(pod *v1.Pod) bool {
|
||||||
|
for _, container := range pod.Spec.Containers {
|
||||||
|
resourceList := container.Resources.Requests
|
||||||
|
if checkLatencySensitiveResourcesForAContainer(resourceList) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEvictable checks if a pod is evictable or not.
|
||||||
|
func IsEvictable(pod *v1.Pod) bool {
|
||||||
|
ownerRefList := OwnerRef(pod)
|
||||||
|
if IsMirrorPod(pod) || IsPodWithLocalStorage(pod) || len(ownerRefList) == 0 || IsDaemonsetPod(ownerRefList) || IsCriticalPod(pod) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEvictablePodsOnNode returns the list of evictable pods on node.
|
||||||
|
func ListEvictablePodsOnNode(client clientset.Interface, node *v1.Node) ([]*v1.Pod, error) {
|
||||||
|
pods, err := ListPodsOnANode(client, node)
|
||||||
|
if err != nil {
|
||||||
|
return []*v1.Pod{}, err
|
||||||
|
}
|
||||||
|
evictablePods := make([]*v1.Pod, 0)
|
||||||
|
for _, pod := range pods {
|
||||||
|
if !IsEvictable(pod) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
evictablePods = append(evictablePods, pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return evictablePods, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ListPodsOnANode(client clientset.Interface, node *v1.Node) ([]*v1.Pod, error) {
|
func ListPodsOnANode(client clientset.Interface, node *v1.Node) ([]*v1.Pod, error) {
|
||||||
|
fieldSelector, err := fields.ParseSelector("spec.nodeName=" + node.Name + ",status.phase!=" + string(api.PodSucceeded) + ",status.phase!=" + string(api.PodFailed))
|
||||||
|
if err != nil {
|
||||||
|
return []*v1.Pod{}, err
|
||||||
|
}
|
||||||
|
|
||||||
podList, err := client.CoreV1().Pods(v1.NamespaceAll).List(
|
podList, err := client.CoreV1().Pods(v1.NamespaceAll).List(
|
||||||
metav1.ListOptions{FieldSelector: fields.SelectorFromSet(fields.Set{"spec.nodeName": node.Name}).String()})
|
metav1.ListOptions{FieldSelector: fieldSelector.String()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Pod{}, err
|
return []*v1.Pod{}, err
|
||||||
}
|
}
|
||||||
@@ -38,7 +93,6 @@ func ListPodsOnANode(client clientset.Interface, node *v1.Node) ([]*v1.Pod, erro
|
|||||||
for i := range podList.Items {
|
for i := range podList.Items {
|
||||||
pods = append(pods, &podList.Items[i])
|
pods = append(pods, &podList.Items[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
return pods, nil
|
return pods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +112,11 @@ func IsGuaranteedPod(pod *v1.Pod) bool {
|
|||||||
return qos.GetPodQOS(pod) == v1.PodQOSGuaranteed
|
return qos.GetPodQOS(pod) == v1.PodQOSGuaranteed
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsDaemonsetPod(sr *v1.SerializedReference) bool {
|
func IsDaemonsetPod(ownerRefList []metav1.OwnerReference) bool {
|
||||||
if sr != nil {
|
for _, ownerRef := range ownerRefList {
|
||||||
return sr.Reference.Kind == "DaemonSet"
|
if ownerRef.Kind == "DaemonSet" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -81,15 +137,7 @@ func IsPodWithLocalStorage(pod *v1.Pod) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatorRef returns the kind of the creator reference of the pod.
|
// OwnerRef returns the ownerRefList for the pod.
|
||||||
func CreatorRef(pod *v1.Pod) (*v1.SerializedReference, error) {
|
func OwnerRef(pod *v1.Pod) []metav1.OwnerReference {
|
||||||
creatorRef, found := pod.ObjectMeta.Annotations[v1.CreatedByAnnotation]
|
return pod.ObjectMeta.GetOwnerReferences()
|
||||||
if !found {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
var sr v1.SerializedReference
|
|
||||||
if err := runtime.DecodeInto(api.Codecs.UniversalDecoder(), []byte(creatorRef), &sr); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &sr, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/test"
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPodTypes(t *testing.T) {
|
func TestPodTypes(t *testing.T) {
|
||||||
@@ -33,20 +33,25 @@ func TestPodTypes(t *testing.T) {
|
|||||||
p3 := test.BuildTestPod("p3", 400, 0, n1.Name)
|
p3 := test.BuildTestPod("p3", 400, 0, n1.Name)
|
||||||
p4 := test.BuildTestPod("p4", 400, 0, n1.Name)
|
p4 := test.BuildTestPod("p4", 400, 0, n1.Name)
|
||||||
p5 := test.BuildTestPod("p5", 400, 0, n1.Name)
|
p5 := test.BuildTestPod("p5", 400, 0, n1.Name)
|
||||||
|
p6 := test.BuildTestPod("p6", 400, 0, n1.Name)
|
||||||
|
p6.Spec.Containers[0].Resources.Requests[v1.ResourceNvidiaGPU] = *resource.NewMilliQuantity(3, resource.DecimalSI)
|
||||||
|
|
||||||
p1.Annotations = test.GetReplicaSetAnnotation()
|
p6.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
|
||||||
|
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
// The following 4 pods won't get evicted.
|
// The following 4 pods won't get evicted.
|
||||||
// A daemonset.
|
// A daemonset.
|
||||||
p2.Annotations = test.GetDaemonSetAnnotation()
|
//p2.Annotations = test.GetDaemonSetAnnotation()
|
||||||
|
p2.ObjectMeta.OwnerReferences = test.GetDaemonSetOwnerRefList()
|
||||||
// A pod with local storage.
|
// A pod with local storage.
|
||||||
p3.Annotations = test.GetNormalPodAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p3.Spec.Volumes = []v1.Volume{
|
p3.Spec.Volumes = []v1.Volume{
|
||||||
{
|
{
|
||||||
Name: "sample",
|
Name: "sample",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
HostPath: &v1.HostPathVolumeSource{Path: "somePath"},
|
HostPath: &v1.HostPathVolumeSource{Path: "somePath"},
|
||||||
EmptyDir: &v1.EmptyDirVolumeSource{
|
EmptyDir: &v1.EmptyDirVolumeSource{
|
||||||
SizeLimit: *resource.NewQuantity(int64(10), resource.BinarySI)},
|
SizeLimit: resource.NewQuantity(int64(10), resource.BinarySI)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -64,13 +69,16 @@ func TestPodTypes(t *testing.T) {
|
|||||||
if !IsPodWithLocalStorage(p3) {
|
if !IsPodWithLocalStorage(p3) {
|
||||||
t.Errorf("Expected p3 to be a pod with local storage.")
|
t.Errorf("Expected p3 to be a pod with local storage.")
|
||||||
}
|
}
|
||||||
sr, _ := CreatorRef(p2)
|
ownerRefList := OwnerRef(p2)
|
||||||
if !IsDaemonsetPod(sr) {
|
if !IsDaemonsetPod(ownerRefList) {
|
||||||
t.Errorf("Expected p2 to be a daemonset pod.")
|
t.Errorf("Expected p2 to be a daemonset pod.")
|
||||||
}
|
}
|
||||||
sr, _ = CreatorRef(p1)
|
ownerRefList = OwnerRef(p1)
|
||||||
if IsDaemonsetPod(sr) || IsPodWithLocalStorage(p1) || IsCriticalPod(p1) || IsMirrorPod(p1) {
|
if IsDaemonsetPod(ownerRefList) || IsPodWithLocalStorage(p1) || IsCriticalPod(p1) || IsMirrorPod(p1) {
|
||||||
t.Errorf("Expected p1 to be a normal pod.")
|
t.Errorf("Expected p1 to be a normal pod.")
|
||||||
}
|
}
|
||||||
|
if !IsLatencySensitivePod(p6) {
|
||||||
|
t.Errorf("Expected p6 to be latency sensitive pod")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
_ "github.com/kubernetes-incubator/descheduler/pkg/api/install"
|
_ "github.com/kubernetes-incubator/descheduler/pkg/api/install"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/api/v1alpha1"
|
"github.com/kubernetes-incubator/descheduler/pkg/api/v1alpha1"
|
||||||
@@ -30,7 +31,7 @@ import (
|
|||||||
|
|
||||||
func LoadPolicyConfig(policyConfigFile string) (*api.DeschedulerPolicy, error) {
|
func LoadPolicyConfig(policyConfigFile string) (*api.DeschedulerPolicy, error) {
|
||||||
if policyConfigFile == "" {
|
if policyConfigFile == "" {
|
||||||
fmt.Printf("policy config file not specified")
|
glog.V(1).Infof("policy config file not specified")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ limitations under the License.
|
|||||||
package strategies
|
package strategies
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"github.com/golang/glog"
|
||||||
//TODO: Change to client-go instead of generated clientset.
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/api/core/v1"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
@@ -36,43 +36,45 @@ type DuplicatePodsMap map[string][]*v1.Pod
|
|||||||
// RemoveDuplicatePods removes the duplicate pods on node. This strategy evicts all duplicate pods on node.
|
// RemoveDuplicatePods removes the duplicate pods on node. This strategy evicts all duplicate pods on node.
|
||||||
// A pod is said to be a duplicate of other if both of them are from same creator, kind and are within the same
|
// A pod is said to be a duplicate of other if both of them are from same creator, kind and are within the same
|
||||||
// namespace. As of now, this strategy won't evict daemonsets, mirror pods, critical pods and pods with local storages.
|
// namespace. As of now, this strategy won't evict daemonsets, mirror pods, critical pods and pods with local storages.
|
||||||
func RemoveDuplicatePods(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, policyGroupVersion string, nodes []*v1.Node) {
|
func RemoveDuplicatePods(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, policyGroupVersion string, nodes []*v1.Node, nodepodCount nodePodEvictedCount) {
|
||||||
if !strategy.Enabled {
|
if !strategy.Enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deleteDuplicatePods(ds.Client, policyGroupVersion, nodes, ds.DryRun)
|
deleteDuplicatePods(ds.Client, policyGroupVersion, nodes, ds.DryRun, nodepodCount, ds.MaxNoOfPodsToEvictPerNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteDuplicatePods evicts the pod from node and returns the count of evicted pods.
|
// deleteDuplicatePods evicts the pod from node and returns the count of evicted pods.
|
||||||
func deleteDuplicatePods(client clientset.Interface, policyGroupVersion string, nodes []*v1.Node, dryRun bool) int {
|
func deleteDuplicatePods(client clientset.Interface, policyGroupVersion string, nodes []*v1.Node, dryRun bool, nodepodCount nodePodEvictedCount, maxPodsToEvict int) int {
|
||||||
podsEvicted := 0
|
podsEvicted := 0
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
fmt.Printf("\nProcessing node: %#v\n", node.Name)
|
glog.V(1).Infof("Processing node: %#v", node.Name)
|
||||||
dpm := ListDuplicatePodsOnANode(client, node)
|
dpm := ListDuplicatePodsOnANode(client, node)
|
||||||
for creator, pods := range dpm {
|
for creator, pods := range dpm {
|
||||||
if len(pods) > 1 {
|
if len(pods) > 1 {
|
||||||
fmt.Printf("%#v\n", creator)
|
glog.V(1).Infof("%#v", creator)
|
||||||
// i = 0 does not evict the first pod
|
// i = 0 does not evict the first pod
|
||||||
for i := 1; i < len(pods); i++ {
|
for i := 1; i < len(pods); i++ {
|
||||||
//fmt.Printf("Removing duplicate pod %#v\n", k.Name)
|
if nodepodCount[node]+1 > maxPodsToEvict {
|
||||||
|
break
|
||||||
|
}
|
||||||
success, err := evictions.EvictPod(client, pods[i], policyGroupVersion, dryRun)
|
success, err := evictions.EvictPod(client, pods[i], policyGroupVersion, dryRun)
|
||||||
if !success {
|
if !success {
|
||||||
//TODO: change fmt.Printf as glogs.
|
glog.Infof("Error when evicting pod: %#v (%#v)", pods[i].Name, err)
|
||||||
fmt.Printf("Error when evicting pod: %#v (%#v)\n", pods[i].Name, err)
|
|
||||||
} else {
|
} else {
|
||||||
podsEvicted++
|
nodepodCount[node]++
|
||||||
fmt.Printf("Evicted pod: %#v (%#v)\n", pods[i].Name, err)
|
glog.V(1).Infof("Evicted pod: %#v (%#v)", pods[i].Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
podsEvicted += nodepodCount[node]
|
||||||
}
|
}
|
||||||
return podsEvicted
|
return podsEvicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListDuplicatePodsOnANode lists duplicate pods on a given node.
|
// ListDuplicatePodsOnANode lists duplicate pods on a given node.
|
||||||
func ListDuplicatePodsOnANode(client clientset.Interface, node *v1.Node) DuplicatePodsMap {
|
func ListDuplicatePodsOnANode(client clientset.Interface, node *v1.Node) DuplicatePodsMap {
|
||||||
pods, err := podutil.ListPodsOnANode(client, node)
|
pods, err := podutil.ListEvictablePodsOnNode(client, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -83,15 +85,14 @@ func ListDuplicatePodsOnANode(client clientset.Interface, node *v1.Node) Duplica
|
|||||||
func FindDuplicatePods(pods []*v1.Pod) DuplicatePodsMap {
|
func FindDuplicatePods(pods []*v1.Pod) DuplicatePodsMap {
|
||||||
dpm := DuplicatePodsMap{}
|
dpm := DuplicatePodsMap{}
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
sr, err := podutil.CreatorRef(pod)
|
// Ignoring the error here as in the ListDuplicatePodsOnNode function we call ListEvictablePodsOnNode
|
||||||
if err != nil || sr == nil {
|
// which checks for error.
|
||||||
continue
|
ownerRefList := podutil.OwnerRef(pod)
|
||||||
|
for _, ownerRef := range ownerRefList {
|
||||||
|
// ownerRef doesn't need namespace since the assumption is owner needs to be in the same namespace.
|
||||||
|
s := strings.Join([]string{ownerRef.Kind, ownerRef.Name}, "/")
|
||||||
|
dpm[s] = append(dpm[s], pod)
|
||||||
}
|
}
|
||||||
if podutil.IsMirrorPod(pod) || podutil.IsDaemonsetPod(sr) || podutil.IsPodWithLocalStorage(pod) || podutil.IsCriticalPod(pod) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s := strings.Join([]string{sr.Reference.Kind, sr.Reference.Namespace, sr.Reference.Name}, "/")
|
|
||||||
dpm[s] = append(dpm[s], pod)
|
|
||||||
}
|
}
|
||||||
return dpm
|
return dpm
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/test"
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//TODO:@ravisantoshgudimetla This could be made table driven.
|
//TODO:@ravisantoshgudimetla This could be made table driven.
|
||||||
@@ -37,24 +37,28 @@ func TestFindDuplicatePods(t *testing.T) {
|
|||||||
p5 := test.BuildTestPod("p5", 100, 0, node.Name)
|
p5 := test.BuildTestPod("p5", 100, 0, node.Name)
|
||||||
p6 := test.BuildTestPod("p6", 100, 0, node.Name)
|
p6 := test.BuildTestPod("p6", 100, 0, node.Name)
|
||||||
p7 := test.BuildTestPod("p7", 100, 0, node.Name)
|
p7 := test.BuildTestPod("p7", 100, 0, node.Name)
|
||||||
|
p8 := test.BuildTestPod("p8", 100, 0, node.Name)
|
||||||
|
p9 := test.BuildTestPod("p9", 100, 0, node.Name)
|
||||||
|
|
||||||
// All the following pods expect for one will be evicted.
|
// All the following pods expect for one will be evicted.
|
||||||
p1.Annotations = test.GetReplicaSetAnnotation()
|
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p2.Annotations = test.GetReplicaSetAnnotation()
|
p2.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p3.Annotations = test.GetReplicaSetAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
|
p8.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
|
p9.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
|
|
||||||
// The following 4 pods won't get evicted.
|
// The following 4 pods won't get evicted.
|
||||||
// A daemonset.
|
// A daemonset.
|
||||||
p4.Annotations = test.GetDaemonSetAnnotation()
|
p4.ObjectMeta.OwnerReferences = test.GetDaemonSetOwnerRefList()
|
||||||
// A pod with local storage.
|
// A pod with local storage.
|
||||||
p5.Annotations = test.GetNormalPodAnnotation()
|
p5.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p5.Spec.Volumes = []v1.Volume{
|
p5.Spec.Volumes = []v1.Volume{
|
||||||
{
|
{
|
||||||
Name: "sample",
|
Name: "sample",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
HostPath: &v1.HostPathVolumeSource{Path: "somePath"},
|
HostPath: &v1.HostPathVolumeSource{Path: "somePath"},
|
||||||
EmptyDir: &v1.EmptyDirVolumeSource{
|
EmptyDir: &v1.EmptyDirVolumeSource{
|
||||||
SizeLimit: *resource.NewQuantity(int64(10), resource.BinarySI)},
|
SizeLimit: resource.NewQuantity(int64(10), resource.BinarySI)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -66,12 +70,14 @@ func TestFindDuplicatePods(t *testing.T) {
|
|||||||
expectedEvictedPodCount := 2
|
expectedEvictedPodCount := 2
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3, *p4, *p5, *p6, *p7}}, nil
|
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9}}, nil
|
||||||
})
|
})
|
||||||
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
return true, node, nil
|
return true, node, nil
|
||||||
})
|
})
|
||||||
podsEvicted := deleteDuplicatePods(fakeClient, "v1", []*v1.Node{node}, false)
|
npe := nodePodEvictedCount{}
|
||||||
|
npe[node] = 0
|
||||||
|
podsEvicted := deleteDuplicatePods(fakeClient, "v1", []*v1.Node{node}, false, npe, 2)
|
||||||
if podsEvicted != expectedEvictedPodCount {
|
if podsEvicted != expectedEvictedPodCount {
|
||||||
t.Errorf("Unexpected no of pods evicted")
|
t.Errorf("Unexpected no of pods evicted")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,25 @@ limitations under the License.
|
|||||||
package strategies
|
package strategies
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
helper "k8s.io/kubernetes/pkg/api/v1/resource"
|
helper "k8s.io/kubernetes/pkg/api/v1/resource"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions"
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions"
|
||||||
|
nodeutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/node"
|
||||||
podutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/pod"
|
podutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/pod"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NodeUsageMap struct {
|
type NodeUsageMap struct {
|
||||||
node *v1.Node
|
node *v1.Node
|
||||||
usage api.ResourceThresholds
|
usage api.ResourceThresholds
|
||||||
|
allPods []*v1.Pod
|
||||||
nonRemovablePods []*v1.Pod
|
nonRemovablePods []*v1.Pod
|
||||||
bePods []*v1.Pod
|
bePods []*v1.Pod
|
||||||
bPods []*v1.Pod
|
bPods []*v1.Pod
|
||||||
@@ -41,7 +43,7 @@ type NodeUsageMap struct {
|
|||||||
}
|
}
|
||||||
type NodePodsMap map[*v1.Node][]*v1.Pod
|
type NodePodsMap map[*v1.Node][]*v1.Pod
|
||||||
|
|
||||||
func LowNodeUtilization(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, evictionPolicyGroupVersion string, nodes []*v1.Node) {
|
func LowNodeUtilization(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, evictionPolicyGroupVersion string, nodes []*v1.Node, nodepodCount nodePodEvictedCount) {
|
||||||
if !strategy.Enabled {
|
if !strategy.Enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -58,74 +60,98 @@ func LowNodeUtilization(ds *options.DeschedulerServer, strategy api.DeschedulerS
|
|||||||
}
|
}
|
||||||
|
|
||||||
npm := CreateNodePodsMap(ds.Client, nodes)
|
npm := CreateNodePodsMap(ds.Client, nodes)
|
||||||
lowNodes, targetNodes, _ := classifyNodes(npm, thresholds, targetThresholds)
|
lowNodes, targetNodes := classifyNodes(npm, thresholds, targetThresholds)
|
||||||
|
|
||||||
|
glog.V(1).Infof("Criteria for a node under utilization: CPU: %v, Mem: %v, Pods: %v",
|
||||||
|
thresholds[v1.ResourceCPU], thresholds[v1.ResourceMemory], thresholds[v1.ResourcePods])
|
||||||
|
|
||||||
if len(lowNodes) == 0 {
|
if len(lowNodes) == 0 {
|
||||||
fmt.Printf("No node is underutilized\n")
|
glog.V(1).Infof("No node is underutilized, nothing to do here, you might tune your thersholds further")
|
||||||
return
|
|
||||||
} else if len(lowNodes) < strategy.Params.NodeResourceUtilizationThresholds.NumberOfNodes {
|
|
||||||
fmt.Printf("number of nodes underutilized is less than NumberOfNodes\n")
|
|
||||||
return
|
|
||||||
} else if len(lowNodes) == len(nodes) {
|
|
||||||
fmt.Printf("all nodes are underutilized\n")
|
|
||||||
return
|
|
||||||
} else if len(targetNodes) == 0 {
|
|
||||||
fmt.Printf("no node is above target utilization\n")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
evictPodsFromTargetNodes(ds.Client, evictionPolicyGroupVersion, targetNodes, lowNodes, targetThresholds, ds.DryRun)
|
glog.V(1).Infof("Total number of underutilized nodes: %v", len(lowNodes))
|
||||||
|
|
||||||
|
if len(lowNodes) < strategy.Params.NodeResourceUtilizationThresholds.NumberOfNodes {
|
||||||
|
glog.V(1).Infof("number of nodes underutilized (%v) is less than NumberOfNodes (%v), nothing to do here", len(lowNodes), strategy.Params.NodeResourceUtilizationThresholds.NumberOfNodes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(lowNodes) == len(nodes) {
|
||||||
|
glog.V(1).Infof("all nodes are underutilized, nothing to do here")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(targetNodes) == 0 {
|
||||||
|
glog.V(1).Infof("all nodes are under target utilization, nothing to do here")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(1).Infof("Criteria for a node above target utilization: CPU: %v, Mem: %v, Pods: %v",
|
||||||
|
targetThresholds[v1.ResourceCPU], targetThresholds[v1.ResourceMemory], targetThresholds[v1.ResourcePods])
|
||||||
|
glog.V(1).Infof("Total number of nodes above target utilization: %v", len(targetNodes))
|
||||||
|
|
||||||
|
totalPodsEvicted := evictPodsFromTargetNodes(ds.Client, evictionPolicyGroupVersion, targetNodes, lowNodes, targetThresholds, ds.DryRun, ds.MaxNoOfPodsToEvictPerNode, nodepodCount)
|
||||||
|
glog.V(1).Infof("Total number of pods evicted: %v", totalPodsEvicted)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateThresholds(thresholds api.ResourceThresholds) bool {
|
func validateThresholds(thresholds api.ResourceThresholds) bool {
|
||||||
if thresholds == nil {
|
if thresholds == nil || len(thresholds) == 0 {
|
||||||
fmt.Printf("no resource threshold is configured\n")
|
glog.V(1).Infof("no resource threshold is configured")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
found := false
|
for name := range thresholds {
|
||||||
for name, _ := range thresholds {
|
switch name {
|
||||||
if name == v1.ResourceCPU || name == v1.ResourceMemory || name == v1.ResourcePods {
|
case v1.ResourceCPU:
|
||||||
found = true
|
continue
|
||||||
break
|
case v1.ResourceMemory:
|
||||||
|
continue
|
||||||
|
case v1.ResourcePods:
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
glog.Errorf("only cpu, memory, or pods thresholds can be specified")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
return true
|
||||||
fmt.Printf("one of cpu, memory, or pods resource threshold must be configured\n")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return found
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//This function could be merged into above once we are clear.
|
//This function could be merged into above once we are clear.
|
||||||
func validateTargetThresholds(targetThresholds api.ResourceThresholds) bool {
|
func validateTargetThresholds(targetThresholds api.ResourceThresholds) bool {
|
||||||
if targetThresholds == nil {
|
if targetThresholds == nil {
|
||||||
fmt.Printf("no target resource threshold is configured\n")
|
glog.V(1).Infof("no target resource threshold is configured")
|
||||||
return false
|
return false
|
||||||
} else if _, ok := targetThresholds[v1.ResourcePods]; !ok {
|
} else if _, ok := targetThresholds[v1.ResourcePods]; !ok {
|
||||||
fmt.Printf("no target resource threshold for pods is configured\n")
|
glog.V(1).Infof("no target resource threshold for pods is configured")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func classifyNodes(npm NodePodsMap, thresholds api.ResourceThresholds, targetThresholds api.ResourceThresholds) ([]NodeUsageMap, []NodeUsageMap, []NodeUsageMap) {
|
// classifyNodes classifies the nodes into low-utilization or high-utilization nodes. If a node lies between
|
||||||
lowNodes, targetNodes, otherNodes := []NodeUsageMap{}, []NodeUsageMap{}, []NodeUsageMap{}
|
// low and high thresholds, it is simply ignored.
|
||||||
|
func classifyNodes(npm NodePodsMap, thresholds api.ResourceThresholds, targetThresholds api.ResourceThresholds) ([]NodeUsageMap, []NodeUsageMap) {
|
||||||
|
lowNodes, targetNodes := []NodeUsageMap{}, []NodeUsageMap{}
|
||||||
for node, pods := range npm {
|
for node, pods := range npm {
|
||||||
usage, nonRemovablePods, bePods, bPods, gPods := NodeUtilization(node, pods)
|
usage, allPods, nonRemovablePods, bePods, bPods, gPods := NodeUtilization(node, pods)
|
||||||
nuMap := NodeUsageMap{node, usage, nonRemovablePods, bePods, bPods, gPods}
|
nuMap := NodeUsageMap{node, usage, allPods, nonRemovablePods, bePods, bPods, gPods}
|
||||||
fmt.Printf("Node %#v usage: %#v\n", node.Name, usage)
|
|
||||||
if IsNodeWithLowUtilization(usage, thresholds) {
|
// Check if node is underutilized and if we can schedule pods on it.
|
||||||
|
if !nodeutil.IsNodeUschedulable(node) && IsNodeWithLowUtilization(usage, thresholds) {
|
||||||
|
glog.V(2).Infof("Node %#v is under utilized with usage: %#v", node.Name, usage)
|
||||||
lowNodes = append(lowNodes, nuMap)
|
lowNodes = append(lowNodes, nuMap)
|
||||||
} else if IsNodeAboveTargetUtilization(usage, targetThresholds) {
|
} else if IsNodeAboveTargetUtilization(usage, targetThresholds) {
|
||||||
|
glog.V(2).Infof("Node %#v is over utilized with usage: %#v", node.Name, usage)
|
||||||
targetNodes = append(targetNodes, nuMap)
|
targetNodes = append(targetNodes, nuMap)
|
||||||
} else {
|
} else {
|
||||||
// Seems we don't need to collect them?
|
glog.V(2).Infof("Node %#v is appropriately utilized with usage: %#v", node.Name, usage)
|
||||||
otherNodes = append(otherNodes, nuMap)
|
|
||||||
}
|
}
|
||||||
|
glog.V(2).Infof("allPods:%v, nonRemovablePods:%v, bePods:%v, bPods:%v, gPods:%v", len(allPods), len(nonRemovablePods), len(bePods), len(bPods), len(gPods))
|
||||||
}
|
}
|
||||||
return lowNodes, targetNodes, otherNodes
|
return lowNodes, targetNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func evictPodsFromTargetNodes(client clientset.Interface, evictionPolicyGroupVersion string, targetNodes, lowNodes []NodeUsageMap, targetThresholds api.ResourceThresholds, dryRun bool) int {
|
func evictPodsFromTargetNodes(client clientset.Interface, evictionPolicyGroupVersion string, targetNodes, lowNodes []NodeUsageMap, targetThresholds api.ResourceThresholds, dryRun bool, maxPodsToEvict int, nodepodCount nodePodEvictedCount) int {
|
||||||
podsEvicted := 0
|
podsEvicted := 0
|
||||||
|
|
||||||
SortNodesByUsage(targetNodes)
|
SortNodesByUsage(targetNodes)
|
||||||
@@ -154,18 +180,26 @@ func evictPodsFromTargetNodes(client clientset.Interface, evictionPolicyGroupVer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glog.V(1).Infof("Total capacity to be moved: CPU:%v, Mem:%v, Pods:%v", totalCpu, totalMem, totalPods)
|
||||||
|
glog.V(1).Infof("********Number of pods evicted from each node:***********")
|
||||||
|
|
||||||
for _, node := range targetNodes {
|
for _, node := range targetNodes {
|
||||||
nodeCapacity := node.node.Status.Capacity
|
nodeCapacity := node.node.Status.Capacity
|
||||||
if len(node.node.Status.Allocatable) > 0 {
|
if len(node.node.Status.Allocatable) > 0 {
|
||||||
nodeCapacity = node.node.Status.Allocatable
|
nodeCapacity = node.node.Status.Allocatable
|
||||||
}
|
}
|
||||||
fmt.Printf("evicting pods from node %#v with usage: %#v\n", node.node.Name, node.usage)
|
glog.V(3).Infof("evicting pods from node %#v with usage: %#v", node.node.Name, node.usage)
|
||||||
|
currentPodsEvicted := nodepodCount[node.node]
|
||||||
|
|
||||||
// evict best effort pods
|
// evict best effort pods
|
||||||
evictPods(node.bePods, client, evictionPolicyGroupVersion, targetThresholds, nodeCapacity, node.usage, &totalPods, &totalCpu, &totalMem, &podsEvicted, dryRun)
|
evictPods(node.bePods, client, evictionPolicyGroupVersion, targetThresholds, nodeCapacity, node.usage, &totalPods, &totalCpu, &totalMem, ¤tPodsEvicted, dryRun, maxPodsToEvict)
|
||||||
// evict burstable pods
|
// evict burstable pods
|
||||||
evictPods(node.bPods, client, evictionPolicyGroupVersion, targetThresholds, nodeCapacity, node.usage, &totalPods, &totalCpu, &totalMem, &podsEvicted, dryRun)
|
evictPods(node.bPods, client, evictionPolicyGroupVersion, targetThresholds, nodeCapacity, node.usage, &totalPods, &totalCpu, &totalMem, ¤tPodsEvicted, dryRun, maxPodsToEvict)
|
||||||
// evict guaranteed pods
|
// evict guaranteed pods
|
||||||
evictPods(node.gPods, client, evictionPolicyGroupVersion, targetThresholds, nodeCapacity, node.usage, &totalPods, &totalCpu, &totalMem, &podsEvicted, dryRun)
|
evictPods(node.gPods, client, evictionPolicyGroupVersion, targetThresholds, nodeCapacity, node.usage, &totalPods, &totalCpu, &totalMem, ¤tPodsEvicted, dryRun, maxPodsToEvict)
|
||||||
|
nodepodCount[node.node] = currentPodsEvicted
|
||||||
|
podsEvicted = podsEvicted + nodepodCount[node.node]
|
||||||
|
glog.V(1).Infof("%v pods evicted from node %#v with usage %v", nodepodCount[node.node], node.node.Name, node.usage)
|
||||||
}
|
}
|
||||||
return podsEvicted
|
return podsEvicted
|
||||||
}
|
}
|
||||||
@@ -180,17 +214,20 @@ func evictPods(inputPods []*v1.Pod,
|
|||||||
totalCpu *float64,
|
totalCpu *float64,
|
||||||
totalMem *float64,
|
totalMem *float64,
|
||||||
podsEvicted *int,
|
podsEvicted *int,
|
||||||
dryRun bool) {
|
dryRun bool, maxPodsToEvict int) {
|
||||||
if IsNodeAboveTargetUtilization(nodeUsage, targetThresholds) && (*totalPods > 0 || *totalCpu > 0 || *totalMem > 0) {
|
if IsNodeAboveTargetUtilization(nodeUsage, targetThresholds) && (*totalPods > 0 || *totalCpu > 0 || *totalMem > 0) {
|
||||||
onePodPercentage := api.Percentage((float64(1) * 100) / float64(nodeCapacity.Pods().Value()))
|
onePodPercentage := api.Percentage((float64(1) * 100) / float64(nodeCapacity.Pods().Value()))
|
||||||
for _, pod := range inputPods {
|
for _, pod := range inputPods {
|
||||||
|
if *podsEvicted+1 > maxPodsToEvict {
|
||||||
|
break
|
||||||
|
}
|
||||||
cUsage := helper.GetResourceRequest(pod, v1.ResourceCPU)
|
cUsage := helper.GetResourceRequest(pod, v1.ResourceCPU)
|
||||||
mUsage := helper.GetResourceRequest(pod, v1.ResourceMemory)
|
mUsage := helper.GetResourceRequest(pod, v1.ResourceMemory)
|
||||||
success, err := evictions.EvictPod(client, pod, evictionPolicyGroupVersion, dryRun)
|
success, err := evictions.EvictPod(client, pod, evictionPolicyGroupVersion, dryRun)
|
||||||
if !success {
|
if !success {
|
||||||
fmt.Printf("Error when evicting pod: %#v (%#v)\n", pod.Name, err)
|
glog.Warningf("Error when evicting pod: %#v (%#v)", pod.Name, err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Evicted pod: %#v (%#v)\n", pod.Name, err)
|
glog.V(3).Infof("Evicted pod: %#v (%#v)", pod.Name, err)
|
||||||
// update remaining pods
|
// update remaining pods
|
||||||
*podsEvicted++
|
*podsEvicted++
|
||||||
nodeUsage[v1.ResourcePods] -= onePodPercentage
|
nodeUsage[v1.ResourcePods] -= onePodPercentage
|
||||||
@@ -204,7 +241,7 @@ func evictPods(inputPods []*v1.Pod,
|
|||||||
*totalMem -= float64(mUsage)
|
*totalMem -= float64(mUsage)
|
||||||
nodeUsage[v1.ResourceMemory] -= api.Percentage(float64(mUsage) / float64(nodeCapacity.Memory().Value()) * 100)
|
nodeUsage[v1.ResourceMemory] -= api.Percentage(float64(mUsage) / float64(nodeCapacity.Memory().Value()) * 100)
|
||||||
|
|
||||||
fmt.Printf("updated node usage: %#v\n", nodeUsage)
|
glog.V(3).Infof("updated node usage: %#v", nodeUsage)
|
||||||
// check if node utilization drops below target threshold or required capacity (cpu, memory, pods) is moved
|
// check if node utilization drops below target threshold or required capacity (cpu, memory, pods) is moved
|
||||||
if !IsNodeAboveTargetUtilization(nodeUsage, targetThresholds) || (*totalPods <= 0 && *totalCpu <= 0 && *totalMem <= 0) {
|
if !IsNodeAboveTargetUtilization(nodeUsage, targetThresholds) || (*totalPods <= 0 && *totalCpu <= 0 && *totalMem <= 0) {
|
||||||
break
|
break
|
||||||
@@ -237,7 +274,7 @@ func CreateNodePodsMap(client clientset.Interface, nodes []*v1.Node) NodePodsMap
|
|||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
pods, err := podutil.ListPodsOnANode(client, node)
|
pods, err := podutil.ListPodsOnANode(client, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("node %s will not be processed, error in accessing its pods (%#v)\n", node.Name, err)
|
glog.Warningf("node %s will not be processed, error in accessing its pods (%#v)", node.Name, err)
|
||||||
} else {
|
} else {
|
||||||
npm[node] = pods
|
npm[node] = pods
|
||||||
}
|
}
|
||||||
@@ -271,19 +308,15 @@ func IsNodeWithLowUtilization(nodeThresholds api.ResourceThresholds, thresholds
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func NodeUtilization(node *v1.Node, pods []*v1.Pod) (api.ResourceThresholds, []*v1.Pod, []*v1.Pod, []*v1.Pod, []*v1.Pod) {
|
func NodeUtilization(node *v1.Node, pods []*v1.Pod) (api.ResourceThresholds, []*v1.Pod, []*v1.Pod, []*v1.Pod, []*v1.Pod, []*v1.Pod) {
|
||||||
bePods := []*v1.Pod{}
|
bePods := []*v1.Pod{}
|
||||||
nonRemovablePods := []*v1.Pod{}
|
nonRemovablePods := []*v1.Pod{}
|
||||||
bPods := []*v1.Pod{}
|
bPods := []*v1.Pod{}
|
||||||
gPods := []*v1.Pod{}
|
gPods := []*v1.Pod{}
|
||||||
totalReqs := map[v1.ResourceName]resource.Quantity{}
|
totalReqs := map[v1.ResourceName]resource.Quantity{}
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
sr, err := podutil.CreatorRef(pod)
|
// We need to compute the usage of nonRemovablePods unless it is a best effort pod. So, cannot use podutil.ListEvictablePodsOnNode
|
||||||
if err != nil {
|
if !podutil.IsEvictable(pod) {
|
||||||
sr = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if podutil.IsMirrorPod(pod) || podutil.IsPodWithLocalStorage(pod) || sr == nil || podutil.IsDaemonsetPod(sr) || podutil.IsCriticalPod(pod) {
|
|
||||||
nonRemovablePods = append(nonRemovablePods, pod)
|
nonRemovablePods = append(nonRemovablePods, pod)
|
||||||
if podutil.IsBestEffortPod(pod) {
|
if podutil.IsBestEffortPod(pod) {
|
||||||
continue
|
continue
|
||||||
@@ -297,11 +330,7 @@ func NodeUtilization(node *v1.Node, pods []*v1.Pod) (api.ResourceThresholds, []*
|
|||||||
gPods = append(gPods, pod)
|
gPods = append(gPods, pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, _, err := helper.PodRequestsAndLimits(pod)
|
req, _ := helper.PodRequestsAndLimits(pod)
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error computing resource usage of pod, ignoring: %#v\n", pod.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for name, quantity := range req {
|
for name, quantity := range req {
|
||||||
if name == v1.ResourceCPU || name == v1.ResourceMemory {
|
if name == v1.ResourceCPU || name == v1.ResourceMemory {
|
||||||
if value, ok := totalReqs[name]; !ok {
|
if value, ok := totalReqs[name]; !ok {
|
||||||
@@ -326,5 +355,5 @@ func NodeUtilization(node *v1.Node, pods []*v1.Pod) (api.ResourceThresholds, []*
|
|||||||
usage[v1.ResourceCPU] = api.Percentage((float64(totalCPUReq.MilliValue()) * 100) / float64(nodeCapacity.Cpu().MilliValue()))
|
usage[v1.ResourceCPU] = api.Percentage((float64(totalCPUReq.MilliValue()) * 100) / float64(nodeCapacity.Cpu().MilliValue()))
|
||||||
usage[v1.ResourceMemory] = api.Percentage(float64(totalMemReq.Value()) / float64(nodeCapacity.Memory().Value()) * 100)
|
usage[v1.ResourceMemory] = api.Percentage(float64(totalMemReq.Value()) / float64(nodeCapacity.Memory().Value()) * 100)
|
||||||
usage[v1.ResourcePods] = api.Percentage((float64(totalPods) * 100) / float64(nodeCapacity.Pods().Value()))
|
usage[v1.ResourcePods] = api.Percentage((float64(totalPods) * 100) / float64(nodeCapacity.Pods().Value()))
|
||||||
return usage, nonRemovablePods, bePods, bPods, gPods
|
return usage, pods, nonRemovablePods, bePods, bPods, gPods
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,15 +18,16 @@ package strategies
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
|
||||||
"github.com/kubernetes-incubator/descheduler/test"
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
core "k8s.io/client-go/testing"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
core "k8s.io/client-go/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Make this table driven.
|
// TODO: Make this table driven.
|
||||||
@@ -40,6 +41,9 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
|
|
||||||
n1 := test.BuildTestNode("n1", 4000, 3000, 9)
|
n1 := test.BuildTestNode("n1", 4000, 3000, 9)
|
||||||
n2 := test.BuildTestNode("n2", 4000, 3000, 10)
|
n2 := test.BuildTestNode("n2", 4000, 3000, 10)
|
||||||
|
n3 := test.BuildTestNode("n3", 4000, 3000, 10)
|
||||||
|
// Making n3 node unschedulable so that it won't counted in lowUtilized nodes list.
|
||||||
|
n3.Spec.Unschedulable = true
|
||||||
p1 := test.BuildTestPod("p1", 400, 0, n1.Name)
|
p1 := test.BuildTestPod("p1", 400, 0, n1.Name)
|
||||||
p2 := test.BuildTestPod("p2", 400, 0, n1.Name)
|
p2 := test.BuildTestPod("p2", 400, 0, n1.Name)
|
||||||
p3 := test.BuildTestPod("p3", 400, 0, n1.Name)
|
p3 := test.BuildTestPod("p3", 400, 0, n1.Name)
|
||||||
@@ -51,23 +55,23 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
p7 := test.BuildTestPod("p7", 400, 0, n1.Name)
|
p7 := test.BuildTestPod("p7", 400, 0, n1.Name)
|
||||||
p8 := test.BuildTestPod("p8", 400, 0, n1.Name)
|
p8 := test.BuildTestPod("p8", 400, 0, n1.Name)
|
||||||
|
|
||||||
p1.Annotations = test.GetReplicaSetAnnotation()
|
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p2.Annotations = test.GetReplicaSetAnnotation()
|
p2.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p3.Annotations = test.GetReplicaSetAnnotation()
|
p3.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p4.Annotations = test.GetReplicaSetAnnotation()
|
p4.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
p5.Annotations = test.GetReplicaSetAnnotation()
|
p5.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
// The following 4 pods won't get evicted.
|
// The following 4 pods won't get evicted.
|
||||||
// A daemonset.
|
// A daemonset.
|
||||||
p6.Annotations = test.GetDaemonSetAnnotation()
|
p6.ObjectMeta.OwnerReferences = test.GetDaemonSetOwnerRefList()
|
||||||
// A pod with local storage.
|
// A pod with local storage.
|
||||||
p7.Annotations = test.GetNormalPodAnnotation()
|
p7.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
p7.Spec.Volumes = []v1.Volume{
|
p7.Spec.Volumes = []v1.Volume{
|
||||||
{
|
{
|
||||||
Name: "sample",
|
Name: "sample",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
HostPath: &v1.HostPathVolumeSource{Path: "somePath"},
|
HostPath: &v1.HostPathVolumeSource{Path: "somePath"},
|
||||||
EmptyDir: &v1.EmptyDirVolumeSource{
|
EmptyDir: &v1.EmptyDirVolumeSource{
|
||||||
SizeLimit: *resource.NewQuantity(int64(10), resource.BinarySI)},
|
SizeLimit: resource.NewQuantity(int64(10), resource.BinarySI)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -77,7 +81,7 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
p8.Namespace = "kube-system"
|
p8.Namespace = "kube-system"
|
||||||
p8.Annotations = test.GetCriticalPodAnnotation()
|
p8.Annotations = test.GetCriticalPodAnnotation()
|
||||||
p9 := test.BuildTestPod("p9", 400, 0, n1.Name)
|
p9 := test.BuildTestPod("p9", 400, 0, n1.Name)
|
||||||
p9.Annotations = test.GetReplicaSetAnnotation()
|
p9.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
list := action.(core.ListAction)
|
list := action.(core.ListAction)
|
||||||
@@ -88,6 +92,9 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
if strings.Contains(fieldString, "n2") {
|
if strings.Contains(fieldString, "n2") {
|
||||||
return true, &v1.PodList{Items: []v1.Pod{*p9}}, nil
|
return true, &v1.PodList{Items: []v1.Pod{*p9}}, nil
|
||||||
}
|
}
|
||||||
|
if strings.Contains(fieldString, "n3") {
|
||||||
|
return true, &v1.PodList{Items: []v1.Pod{}}, nil
|
||||||
|
}
|
||||||
return true, nil, fmt.Errorf("Failed to list: %v", list)
|
return true, nil, fmt.Errorf("Failed to list: %v", list)
|
||||||
})
|
})
|
||||||
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
@@ -97,15 +104,76 @@ func TestLowNodeUtilization(t *testing.T) {
|
|||||||
return true, n1, nil
|
return true, n1, nil
|
||||||
case n2.Name:
|
case n2.Name:
|
||||||
return true, n2, nil
|
return true, n2, nil
|
||||||
|
case n3.Name:
|
||||||
|
return true, n3, nil
|
||||||
}
|
}
|
||||||
return true, nil, fmt.Errorf("Wrong node: %v", getAction.GetName())
|
return true, nil, fmt.Errorf("Wrong node: %v", getAction.GetName())
|
||||||
})
|
})
|
||||||
expectedPodsEvicted := 4
|
expectedPodsEvicted := 3
|
||||||
npm := CreateNodePodsMap(fakeClient, []*v1.Node{n1, n2})
|
npm := CreateNodePodsMap(fakeClient, []*v1.Node{n1, n2, n3})
|
||||||
lowNodes, targetNodes, _ := classifyNodes(npm, thresholds, targetThresholds)
|
lowNodes, targetNodes := classifyNodes(npm, thresholds, targetThresholds)
|
||||||
podsEvicted := evictPodsFromTargetNodes(fakeClient, "v1", targetNodes, lowNodes, targetThresholds, false)
|
if len(lowNodes) != 1 {
|
||||||
|
t.Errorf("After ignoring unschedulable nodes, expected only one node to be under utilized.")
|
||||||
|
}
|
||||||
|
npe := nodePodEvictedCount{}
|
||||||
|
npe[n1] = 0
|
||||||
|
npe[n2] = 0
|
||||||
|
npe[n3] = 0
|
||||||
|
podsEvicted := evictPodsFromTargetNodes(fakeClient, "v1", targetNodes, lowNodes, targetThresholds, false, 3, npe)
|
||||||
if expectedPodsEvicted != podsEvicted {
|
if expectedPodsEvicted != podsEvicted {
|
||||||
t.Errorf("Expected %#v pods to be evicted but %#v got evicted", expectedPodsEvicted)
|
t.Errorf("Expected %#v pods to be evicted but %#v got evicted", expectedPodsEvicted, podsEvicted)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateThresholds(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input api.ResourceThresholds
|
||||||
|
succeed bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "passing nil map for threshold",
|
||||||
|
input: nil,
|
||||||
|
succeed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "passing no threshold",
|
||||||
|
input: api.ResourceThresholds{},
|
||||||
|
succeed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "passing unsupported resource name",
|
||||||
|
input: api.ResourceThresholds{
|
||||||
|
v1.ResourceCPU: 40,
|
||||||
|
v1.ResourceStorage: 25.5,
|
||||||
|
},
|
||||||
|
succeed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "passing invalid resource name",
|
||||||
|
input: api.ResourceThresholds{
|
||||||
|
v1.ResourceCPU: 40,
|
||||||
|
"coolResource": 42.0,
|
||||||
|
},
|
||||||
|
succeed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "passing a valid threshold with cpu, memory and pods",
|
||||||
|
input: api.ResourceThresholds{
|
||||||
|
v1.ResourceCPU: 20,
|
||||||
|
v1.ResourceMemory: 30,
|
||||||
|
v1.ResourcePods: 40,
|
||||||
|
},
|
||||||
|
succeed: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
isValid := validateThresholds(test.input)
|
||||||
|
|
||||||
|
if isValid != test.succeed {
|
||||||
|
t.Errorf("expected validity of threshold: %#v\nto be %v but got %v instead", test.input, test.succeed, isValid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
74
pkg/descheduler/strategies/node_affinity.go
Normal file
74
pkg/descheduler/strategies/node_affinity.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions"
|
||||||
|
nodeutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/node"
|
||||||
|
podutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/pod"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RemovePodsViolatingNodeAffinity(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, evictionPolicyGroupVersion string, nodes []*v1.Node, nodePodCount nodePodEvictedCount) {
|
||||||
|
evictionCount := removePodsViolatingNodeAffinityCount(ds, strategy, evictionPolicyGroupVersion, nodes, nodePodCount, ds.MaxNoOfPodsToEvictPerNode)
|
||||||
|
glog.V(1).Infof("Evicted %v pods", evictionCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePodsViolatingNodeAffinityCount(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, evictionPolicyGroupVersion string, nodes []*v1.Node, nodepodCount nodePodEvictedCount, maxPodsToEvict int) int {
|
||||||
|
evictedPodCount := 0
|
||||||
|
if !strategy.Enabled {
|
||||||
|
return evictedPodCount
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nodeAffinity := range strategy.Params.NodeAffinityType {
|
||||||
|
glog.V(2).Infof("Executing for nodeAffinityType: %v", nodeAffinity)
|
||||||
|
|
||||||
|
switch nodeAffinity {
|
||||||
|
case "requiredDuringSchedulingIgnoredDuringExecution":
|
||||||
|
for _, node := range nodes {
|
||||||
|
glog.V(1).Infof("Processing node: %#v\n", node.Name)
|
||||||
|
|
||||||
|
pods, err := podutil.ListEvictablePodsOnNode(ds.Client, node)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("failed to get pods from %v: %v", node.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pod := range pods {
|
||||||
|
if nodepodCount[node]+1 > maxPodsToEvict {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if pod.Spec.Affinity != nil && pod.Spec.Affinity.NodeAffinity != nil && pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
|
||||||
|
|
||||||
|
if !nodeutil.PodFitsCurrentNode(pod, node) && nodeutil.PodFitsAnyNode(pod, nodes) {
|
||||||
|
glog.V(1).Infof("Evicting pod: %v", pod.Name)
|
||||||
|
evictions.EvictPod(ds.Client, pod, evictionPolicyGroupVersion, false)
|
||||||
|
nodepodCount[node]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evictedPodCount += nodepodCount[node]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
glog.Errorf("invalid nodeAffinityType: %v", nodeAffinity)
|
||||||
|
return evictedPodCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return evictedPodCount
|
||||||
|
}
|
||||||
184
pkg/descheduler/strategies/node_affinity_test.go
Normal file
184
pkg/descheduler/strategies/node_affinity_test.go
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
core "k8s.io/client-go/testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRemovePodsViolatingNodeAffinity(t *testing.T) {
|
||||||
|
|
||||||
|
requiredDuringSchedulingIgnoredDuringExecutionStrategy := api.DeschedulerStrategy{
|
||||||
|
Enabled: true,
|
||||||
|
Params: api.StrategyParameters{
|
||||||
|
NodeAffinityType: []string{
|
||||||
|
"requiredDuringSchedulingIgnoredDuringExecution",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeLabelKey := "kubernetes.io/desiredNode"
|
||||||
|
nodeLabelValue := "yes"
|
||||||
|
nodeWithLabels := test.BuildTestNode("nodeWithLabels", 2000, 3000, 10)
|
||||||
|
nodeWithLabels.Labels[nodeLabelKey] = nodeLabelValue
|
||||||
|
|
||||||
|
nodeWithoutLabels := test.BuildTestNode("nodeWithoutLabels", 2000, 3000, 10)
|
||||||
|
|
||||||
|
unschedulableNodeWithLabels := test.BuildTestNode("unschedulableNodeWithLabels", 2000, 3000, 10)
|
||||||
|
nodeWithLabels.Labels[nodeLabelKey] = nodeLabelValue
|
||||||
|
unschedulableNodeWithLabels.Spec.Unschedulable = true
|
||||||
|
|
||||||
|
addPodsToNode := func(node *v1.Node) []v1.Pod {
|
||||||
|
podWithNodeAffinity := test.BuildTestPod("podWithNodeAffinity", 100, 0, node.Name)
|
||||||
|
podWithNodeAffinity.Spec.Affinity = &v1.Affinity{
|
||||||
|
NodeAffinity: &v1.NodeAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||||
|
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: nodeLabelKey,
|
||||||
|
Operator: "In",
|
||||||
|
Values: []string{
|
||||||
|
nodeLabelValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pod1 := test.BuildTestPod("pod1", 100, 0, node.Name)
|
||||||
|
pod2 := test.BuildTestPod("pod2", 100, 0, node.Name)
|
||||||
|
|
||||||
|
podWithNodeAffinity.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
pod1.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
pod2.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
|
||||||
|
return []v1.Pod{
|
||||||
|
*podWithNodeAffinity,
|
||||||
|
*pod1,
|
||||||
|
*pod2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
nodes []*v1.Node
|
||||||
|
pods []v1.Pod
|
||||||
|
strategy api.DeschedulerStrategy
|
||||||
|
expectedEvictedPodCount int
|
||||||
|
npe nodePodEvictedCount
|
||||||
|
maxPodsToEvict int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "Strategy disabled, should not evict any pods",
|
||||||
|
strategy: api.DeschedulerStrategy{
|
||||||
|
Enabled: false,
|
||||||
|
Params: api.StrategyParameters{
|
||||||
|
NodeAffinityType: []string{
|
||||||
|
"requiredDuringSchedulingIgnoredDuringExecution",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEvictedPodCount: 0,
|
||||||
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
|
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
||||||
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
||||||
|
maxPodsToEvict: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Invalid strategy type, should not evict any pods",
|
||||||
|
strategy: api.DeschedulerStrategy{
|
||||||
|
Enabled: true,
|
||||||
|
Params: api.StrategyParameters{
|
||||||
|
NodeAffinityType: []string{
|
||||||
|
"requiredDuringSchedulingRequiredDuringExecution",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEvictedPodCount: 0,
|
||||||
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
|
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
||||||
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
||||||
|
maxPodsToEvict: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Pod is correctly scheduled on node, no eviction expected",
|
||||||
|
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
|
||||||
|
expectedEvictedPodCount: 0,
|
||||||
|
pods: addPodsToNode(nodeWithLabels),
|
||||||
|
nodes: []*v1.Node{nodeWithLabels},
|
||||||
|
npe: nodePodEvictedCount{nodeWithLabels: 0},
|
||||||
|
maxPodsToEvict: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Pod is scheduled on node without matching labels, another schedulable node available, should be evicted",
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
|
||||||
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
|
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
||||||
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
||||||
|
maxPodsToEvict: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Pod is scheduled on node without matching labels, another schedulable node available, maxPodsToEvict set to 0, should not be evicted",
|
||||||
|
expectedEvictedPodCount: 0,
|
||||||
|
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
|
||||||
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
|
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
|
||||||
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
|
||||||
|
maxPodsToEvict: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Pod is scheduled on node without matching labels, but no node where pod fits is available, should not evict",
|
||||||
|
expectedEvictedPodCount: 0,
|
||||||
|
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
|
||||||
|
pods: addPodsToNode(nodeWithoutLabels),
|
||||||
|
nodes: []*v1.Node{nodeWithoutLabels, unschedulableNodeWithLabels},
|
||||||
|
npe: nodePodEvictedCount{nodeWithoutLabels: 0, unschedulableNodeWithLabels: 0},
|
||||||
|
maxPodsToEvict: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
|
||||||
|
fakeClient := &fake.Clientset{}
|
||||||
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
|
return true, &v1.PodList{Items: tc.pods}, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
ds := options.DeschedulerServer{
|
||||||
|
Client: fakeClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEvictedPodCount := removePodsViolatingNodeAffinityCount(&ds, tc.strategy, "v1", tc.nodes, tc.npe, tc.maxPodsToEvict)
|
||||||
|
if actualEvictedPodCount != tc.expectedEvictedPodCount {
|
||||||
|
t.Errorf("Test %#v failed, expected %v pod evictions, but got %v pod evictions\n", tc.description, tc.expectedEvictedPodCount, actualEvictedPodCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
pkg/descheduler/strategies/pod_antiaffinity.go
Normal file
105
pkg/descheduler/strategies/pod_antiaffinity.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions"
|
||||||
|
podutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/pod"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemovePodsViolatingInterPodAntiAffinity with elimination strategy
|
||||||
|
func RemovePodsViolatingInterPodAntiAffinity(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, policyGroupVersion string, nodes []*v1.Node, nodePodCount nodePodEvictedCount) {
|
||||||
|
if !strategy.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
removePodsWithAffinityRules(ds.Client, policyGroupVersion, nodes, ds.DryRun, nodePodCount, ds.MaxNoOfPodsToEvictPerNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// removePodsWithAffinityRules evicts pods on the node which are having a pod affinity rules.
|
||||||
|
func removePodsWithAffinityRules(client clientset.Interface, policyGroupVersion string, nodes []*v1.Node, dryRun bool, nodePodCount nodePodEvictedCount, maxPodsToEvict int) int {
|
||||||
|
podsEvicted := 0
|
||||||
|
for _, node := range nodes {
|
||||||
|
glog.V(1).Infof("Processing node: %#v\n", node.Name)
|
||||||
|
pods, err := podutil.ListEvictablePodsOnNode(client, node)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
totalPods := len(pods)
|
||||||
|
for i := 0; i < totalPods; i++ {
|
||||||
|
if nodePodCount[node]+1 > maxPodsToEvict {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if checkPodsWithAntiAffinityExist(pods[i], pods) {
|
||||||
|
success, err := evictions.EvictPod(client, pods[i], policyGroupVersion, dryRun)
|
||||||
|
if !success {
|
||||||
|
glog.Infof("Error when evicting pod: %#v (%#v)\n", pods[i].Name, err)
|
||||||
|
} else {
|
||||||
|
nodePodCount[node]++
|
||||||
|
glog.V(1).Infof("Evicted pod: %#v (%#v)\n because of existing anti-affinity", pods[i].Name, err)
|
||||||
|
// Since the current pod is evicted all other pods which have anti-affinity with this
|
||||||
|
// pod need not be evicted.
|
||||||
|
// Update pods.
|
||||||
|
pods = append(pods[:i], pods[i+1:]...)
|
||||||
|
i--
|
||||||
|
totalPods--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
podsEvicted += nodePodCount[node]
|
||||||
|
}
|
||||||
|
return podsEvicted
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkPodsWithAntiAffinityExist checks if there are other pods on the node that the current pod cannot tolerate.
|
||||||
|
func checkPodsWithAntiAffinityExist(pod *v1.Pod, pods []*v1.Pod) bool {
|
||||||
|
affinity := pod.Spec.Affinity
|
||||||
|
if affinity != nil && affinity.PodAntiAffinity != nil {
|
||||||
|
for _, term := range getPodAntiAffinityTerms(affinity.PodAntiAffinity) {
|
||||||
|
namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, &term)
|
||||||
|
selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector)
|
||||||
|
if err != nil {
|
||||||
|
glog.Infof("%v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, existingPod := range pods {
|
||||||
|
if existingPod.Name != pod.Name && priorityutil.PodMatchesTermsNamespaceAndSelector(existingPod, namespaces, selector) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPodAntiAffinityTerms gets the antiaffinity terms for the given pod.
|
||||||
|
func getPodAntiAffinityTerms(podAntiAffinity *v1.PodAntiAffinity) (terms []v1.PodAffinityTerm) {
|
||||||
|
if podAntiAffinity != nil {
|
||||||
|
if len(podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 {
|
||||||
|
terms = podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return terms
|
||||||
|
}
|
||||||
94
pkg/descheduler/strategies/pod_antiaffinity_test.go
Normal file
94
pkg/descheduler/strategies/pod_antiaffinity_test.go
Normal 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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
core "k8s.io/client-go/testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPodAntiAffinity(t *testing.T) {
|
||||||
|
node := test.BuildTestNode("n1", 2000, 3000, 10)
|
||||||
|
p1 := test.BuildTestPod("p1", 100, 0, node.Name)
|
||||||
|
p2 := test.BuildTestPod("p2", 100, 0, node.Name)
|
||||||
|
p3 := test.BuildTestPod("p3", 100, 0, node.Name)
|
||||||
|
p3.Labels = map[string]string{"foo": "bar"}
|
||||||
|
p1.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
p2.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
p3.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
p1.Spec.Affinity = &v1.Affinity{
|
||||||
|
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
||||||
|
{
|
||||||
|
LabelSelector: &metav1.LabelSelector{
|
||||||
|
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Operator: metav1.LabelSelectorOpIn,
|
||||||
|
Values: []string{"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TopologyKey: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p3.Spec.Affinity = &v1.Affinity{
|
||||||
|
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
||||||
|
{
|
||||||
|
LabelSelector: &metav1.LabelSelector{
|
||||||
|
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Operator: metav1.LabelSelectorOpIn,
|
||||||
|
Values: []string{"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TopologyKey: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fakeClient := &fake.Clientset{}
|
||||||
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
|
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3}}, nil
|
||||||
|
})
|
||||||
|
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
|
return true, node, nil
|
||||||
|
})
|
||||||
|
npe := nodePodEvictedCount{}
|
||||||
|
npe[node] = 0
|
||||||
|
expectedEvictedPodCount := 0
|
||||||
|
podsEvicted := removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false, npe, 0)
|
||||||
|
if podsEvicted != expectedEvictedPodCount {
|
||||||
|
t.Errorf("Unexpected no of pods evicted")
|
||||||
|
}
|
||||||
|
expectedEvictedPodCount = 1
|
||||||
|
podsEvicted = removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false, npe, 1)
|
||||||
|
if podsEvicted != expectedEvictedPodCount {
|
||||||
|
t.Errorf("Unexpected no of pods evicted")
|
||||||
|
}
|
||||||
|
}
|
||||||
37
pkg/descheduler/strategies/util.go
Normal file
37
pkg/descheduler/strategies/util.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file contains the datastructures, types & functions needed by all the strategies so that we don't have
|
||||||
|
// to compute them again in each strategy.
|
||||||
|
|
||||||
|
// nodePodEvictedCount keeps count of pods evicted on node. This is used in conjunction with strategies to
|
||||||
|
type nodePodEvictedCount map[*v1.Node]int
|
||||||
|
|
||||||
|
// InitializeNodePodCount initializes the nodePodCount.
|
||||||
|
func InitializeNodePodCount(nodeList []*v1.Node) nodePodEvictedCount {
|
||||||
|
var nodePodCount = make(nodePodEvictedCount)
|
||||||
|
for _, node := range nodeList {
|
||||||
|
// Initialize podsEvicted till now with 0.
|
||||||
|
nodePodCount[node] = 0
|
||||||
|
}
|
||||||
|
return nodePodCount
|
||||||
|
}
|
||||||
94
pkg/utils/predicates.go
Normal file
94
pkg/utils/predicates.go
Normal 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 utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The following code has been copied from predicates package to avoid the
|
||||||
|
// huge vendoring issues, mostly copied from
|
||||||
|
// k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates/
|
||||||
|
// Some minor changes have been made to ease the imports, but most of the code
|
||||||
|
// remains untouched
|
||||||
|
|
||||||
|
// PodMatchNodeSelector checks if a pod node selector matches the node label.
|
||||||
|
func PodMatchNodeSelector(pod *v1.Pod, node *v1.Node) (bool, error) {
|
||||||
|
if node == nil {
|
||||||
|
return false, fmt.Errorf("node not found")
|
||||||
|
}
|
||||||
|
if podMatchesNodeLabels(pod, node) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pod can only schedule onto nodes that satisfy requirements in both NodeAffinity and nodeSelector.
|
||||||
|
func podMatchesNodeLabels(pod *v1.Pod, node *v1.Node) bool {
|
||||||
|
// Check if node.Labels match pod.Spec.NodeSelector.
|
||||||
|
if len(pod.Spec.NodeSelector) > 0 {
|
||||||
|
selector := labels.SelectorFromSet(pod.Spec.NodeSelector)
|
||||||
|
if !selector.Matches(labels.Set(node.Labels)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. nil NodeSelector matches all nodes (i.e. does not filter out any nodes)
|
||||||
|
// 2. nil []NodeSelectorTerm (equivalent to non-nil empty NodeSelector) matches no nodes
|
||||||
|
// 3. zero-length non-nil []NodeSelectorTerm matches no nodes also, just for simplicity
|
||||||
|
// 4. nil []NodeSelectorRequirement (equivalent to non-nil empty NodeSelectorTerm) matches no nodes
|
||||||
|
// 5. zero-length non-nil []NodeSelectorRequirement matches no nodes also, just for simplicity
|
||||||
|
// 6. non-nil empty NodeSelectorRequirement is not allowed
|
||||||
|
|
||||||
|
affinity := pod.Spec.Affinity
|
||||||
|
if affinity != nil && affinity.NodeAffinity != nil {
|
||||||
|
nodeAffinity := affinity.NodeAffinity
|
||||||
|
// if no required NodeAffinity requirements, will do no-op, means select all nodes.
|
||||||
|
if nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match node selector for requiredDuringSchedulingIgnoredDuringExecution.
|
||||||
|
if nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
|
||||||
|
nodeSelectorTerms := nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms
|
||||||
|
glog.V(10).Infof("Match for RequiredDuringSchedulingIgnoredDuringExecution node selector terms %+v", nodeSelectorTerms)
|
||||||
|
return nodeMatchesNodeSelectorTerms(node, nodeSelectorTerms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodeMatchesNodeSelectorTerms checks if a node's labels satisfy a list of node selector terms,
|
||||||
|
// terms are ORed, and an empty list of terms will match nothing.
|
||||||
|
func nodeMatchesNodeSelectorTerms(node *v1.Node, nodeSelectorTerms []v1.NodeSelectorTerm) bool {
|
||||||
|
for _, req := range nodeSelectorTerms {
|
||||||
|
nodeSelector, err := v1helper.NodeSelectorRequirementsAsSelector(req.MatchExpressions)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(10).Infof("Failed to parse MatchExpressions: %+v, regarding as not match.", req.MatchExpressions)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if nodeSelector.Matches(labels.Set(node.Labels)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
156
test/e2e/e2e_test.go
Normal file
156
test/e2e/e2e_test.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
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 e2e
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
|
deschedulerapi "github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/client"
|
||||||
|
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
||||||
|
nodeutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/node"
|
||||||
|
podutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/pod"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/strategies"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakePodSpec() v1.PodSpec {
|
||||||
|
return v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "pause",
|
||||||
|
Image: "kubernetes/pause",
|
||||||
|
Ports: []v1.ContainerPort{{ContainerPort: 80}},
|
||||||
|
Resources: v1.ResourceRequirements{
|
||||||
|
Limits: v1.ResourceList{
|
||||||
|
v1.ResourceCPU: resource.MustParse("100m"),
|
||||||
|
v1.ResourceMemory: resource.MustParse("500Mi"),
|
||||||
|
},
|
||||||
|
Requests: v1.ResourceList{
|
||||||
|
v1.ResourceCPU: resource.MustParse("100m"),
|
||||||
|
v1.ResourceMemory: resource.MustParse("500Mi"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RcByNameContainer returns a ReplicationControoler with specified name and container
|
||||||
|
func RcByNameContainer(name string, replicas int32, labels map[string]string, gracePeriod *int64) *v1.ReplicationController {
|
||||||
|
|
||||||
|
zeroGracePeriod := int64(0)
|
||||||
|
|
||||||
|
// Add "name": name to the labels, overwriting if it exists.
|
||||||
|
labels["name"] = name
|
||||||
|
if gracePeriod == nil {
|
||||||
|
gracePeriod = &zeroGracePeriod
|
||||||
|
}
|
||||||
|
return &v1.ReplicationController{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(),
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Spec: v1.ReplicationControllerSpec{
|
||||||
|
Replicas: func(i int32) *int32 { return &i }(replicas),
|
||||||
|
Selector: map[string]string{
|
||||||
|
"name": name,
|
||||||
|
},
|
||||||
|
Template: &v1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: labels,
|
||||||
|
},
|
||||||
|
Spec: MakePodSpec(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// startEndToEndForLowNodeUtilization tests the lownode utilization strategy.
|
||||||
|
func startEndToEndForLowNodeUtilization(clientset clientset.Interface) {
|
||||||
|
var thresholds = make(deschedulerapi.ResourceThresholds)
|
||||||
|
var targetThresholds = make(deschedulerapi.ResourceThresholds)
|
||||||
|
thresholds[v1.ResourceMemory] = 20
|
||||||
|
thresholds[v1.ResourcePods] = 20
|
||||||
|
thresholds[v1.ResourceCPU] = 85
|
||||||
|
targetThresholds[v1.ResourceMemory] = 20
|
||||||
|
targetThresholds[v1.ResourcePods] = 20
|
||||||
|
targetThresholds[v1.ResourceCPU] = 90
|
||||||
|
// Run descheduler.
|
||||||
|
evictionPolicyGroupVersion, err := eutils.SupportEviction(clientset)
|
||||||
|
if err != nil || len(evictionPolicyGroupVersion) == 0 {
|
||||||
|
glog.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
stopChannel := make(chan struct{})
|
||||||
|
nodes, err := nodeutil.ReadyNodes(clientset, "", stopChannel)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
nodeUtilizationThresholds := deschedulerapi.NodeResourceUtilizationThresholds{Thresholds: thresholds, TargetThresholds: targetThresholds}
|
||||||
|
nodeUtilizationStrategyParams := deschedulerapi.StrategyParameters{NodeResourceUtilizationThresholds: nodeUtilizationThresholds}
|
||||||
|
lowNodeUtilizationStrategy := deschedulerapi.DeschedulerStrategy{Enabled: true, Params: nodeUtilizationStrategyParams}
|
||||||
|
ds := &options.DeschedulerServer{Client: clientset}
|
||||||
|
nodePodCount := strategies.InitializeNodePodCount(nodes)
|
||||||
|
strategies.LowNodeUtilization(ds, lowNodeUtilizationStrategy, evictionPolicyGroupVersion, nodes, nodePodCount)
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestE2E(t *testing.T) {
|
||||||
|
// If we have reached here, it means cluster would have been already setup and the kubeconfig file should
|
||||||
|
// be in /tmp directory.
|
||||||
|
clientSet, err := client.CreateClient("/tmp/admin.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error during client creation with %v", err)
|
||||||
|
}
|
||||||
|
nodeList, err := clientSet.Core().Nodes().List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error listing node with %v", err)
|
||||||
|
}
|
||||||
|
// Assumption: We would have 3 node cluster by now. Kubeadm brings all the master components onto master node.
|
||||||
|
// So, the last node would have least utilization.
|
||||||
|
leastLoadedNode := nodeList.Items[2]
|
||||||
|
rc := RcByNameContainer("test-rc", int32(15), map[string]string{"test": "app"}, nil)
|
||||||
|
_, err = clientSet.CoreV1().ReplicationControllers("default").Create(rc)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error creating deployment %v", err)
|
||||||
|
}
|
||||||
|
podsOnleastUtilizedNode, err := podutil.ListPodsOnANode(clientSet, &leastLoadedNode)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error listing pods on a node %v", err)
|
||||||
|
}
|
||||||
|
podsBefore := len(podsOnleastUtilizedNode)
|
||||||
|
t.Log("Eviction of pods starting")
|
||||||
|
startEndToEndForLowNodeUtilization(clientSet)
|
||||||
|
podsOnleastUtilizedNode, err = podutil.ListPodsOnANode(clientSet, &leastLoadedNode)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error listing pods on a node %v", err)
|
||||||
|
}
|
||||||
|
podsAfter := len(podsOnleastUtilizedNode)
|
||||||
|
if podsBefore > podsAfter {
|
||||||
|
t.Fatalf("We should have see more pods on this node as per kubeadm's way of installing %v, %v", podsBefore, podsAfter)
|
||||||
|
}
|
||||||
|
}
|
||||||
20
test/run-e2e-tests.sh
Executable file
20
test/run-e2e-tests.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This just run e2e tests.
|
||||||
|
PRJ_PREFIX="github.com/${REPO_ORG:-kubernetes-incubator}/descheduler"
|
||||||
|
go test ${PRJ_PREFIX}/test/e2e/ -v
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# run unit tests
|
# This just run unit-tests. Ignoring the current directory so as to avoid running e2e tests.
|
||||||
go test $(go list github.com/kubernetes-incubator/descheduler/... | grep -v github.com/kubernetes-incubator/descheduler/vendor/)
|
PRJ_PREFIX="github.com/${REPO_ORG:-kubernetes-incubator}/descheduler"
|
||||||
|
go test $(go list ${PRJ_PREFIX}/... | grep -v ${PRJ_PREFIX}/vendor/| grep -v ${PRJ_PREFIX}/test/)
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,15 @@ limitations under the License.
|
|||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import ("fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO:@ravisantoshgudimetla. As of now building some test pods here. This needs to
|
// BuildTestPod creates a test pod with given parameters.
|
||||||
// move to utils after refactor.
|
|
||||||
// buildTestPod creates a test pod with given parameters.
|
|
||||||
func BuildTestPod(name string, cpu int64, memory int64, nodeName string) *v1.Pod {
|
func BuildTestPod(name string, cpu int64, memory int64, nodeName string) *v1.Pod {
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -63,25 +62,25 @@ func GetMirrorPodAnnotation() map[string]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNormalPodAnnotation returns the annotation needed for a pod.
|
// GetNormalPodOwnerRefList returns the ownerRef needed for a pod.
|
||||||
func GetNormalPodAnnotation() map[string]string {
|
func GetNormalPodOwnerRefList() []metav1.OwnerReference {
|
||||||
return map[string]string{
|
ownerRefList := make([]metav1.OwnerReference, 0)
|
||||||
"kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"Pod\"}}",
|
ownerRefList = append(ownerRefList, metav1.OwnerReference{Kind: "Pod", APIVersion: "v1"})
|
||||||
}
|
return ownerRefList
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReplicaSetAnnotation returns the annotation needed for replicaset pod.
|
// GetReplicaSetOwnerRefList returns the ownerRef needed for replicaset pod.
|
||||||
func GetReplicaSetAnnotation() map[string]string {
|
func GetReplicaSetOwnerRefList() []metav1.OwnerReference {
|
||||||
return map[string]string{
|
ownerRefList := make([]metav1.OwnerReference, 0)
|
||||||
"kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"ReplicaSet\"}}",
|
ownerRefList = append(ownerRefList, metav1.OwnerReference{Kind: "ReplicaSet", APIVersion: "v1"})
|
||||||
}
|
return ownerRefList
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDaemonSetAnnotation returns the annotation needed for daemonset pod.
|
// GetDaemonSetOwnerRefList returns the ownerRef needed for daemonset pod.
|
||||||
func GetDaemonSetAnnotation() map[string]string {
|
func GetDaemonSetOwnerRefList() []metav1.OwnerReference {
|
||||||
return map[string]string{
|
ownerRefList := make([]metav1.OwnerReference, 0)
|
||||||
"kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1\",\"reference\":{\"kind\":\"DaemonSet\"}}",
|
ownerRefList = append(ownerRefList, metav1.OwnerReference{Kind: "DaemonSet", APIVersion: "v1"})
|
||||||
}
|
return ownerRefList
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCriticalPodAnnotation returns the annotation needed for critical pod.
|
// GetCriticalPodAnnotation returns the annotation needed for critical pod.
|
||||||
@@ -92,7 +91,6 @@ func GetCriticalPodAnnotation() map[string]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// BuildTestNode creates a node with specified capacity.
|
// BuildTestNode creates a node with specified capacity.
|
||||||
func BuildTestNode(name string, millicpu int64, mem int64, pods int64) *v1.Node {
|
func BuildTestNode(name string, millicpu int64, mem int64, pods int64) *v1.Node {
|
||||||
node := &v1.Node{
|
node := &v1.Node{
|
||||||
|
|||||||
9
vendor/github.com/davecgh/go-spew/.travis.yml
generated
vendored
9
vendor/github.com/davecgh/go-spew/.travis.yml
generated
vendored
@@ -1,9 +1,12 @@
|
|||||||
language: go
|
language: go
|
||||||
go: 1.2
|
go:
|
||||||
|
- 1.5.4
|
||||||
|
- 1.6.3
|
||||||
|
- 1.7
|
||||||
install:
|
install:
|
||||||
- go get -v code.google.com/p/go.tools/cmd/cover
|
- go get -v golang.org/x/tools/cmd/cover
|
||||||
script:
|
script:
|
||||||
- go test -v -tags=disableunsafe ./spew
|
- go test -v -tags=safe ./spew
|
||||||
- go test -v -tags=testcgo ./spew -covermode=count -coverprofile=profile.cov
|
- go test -v -tags=testcgo ./spew -covermode=count -coverprofile=profile.cov
|
||||||
after_success:
|
after_success:
|
||||||
- go get -v github.com/mattn/goveralls
|
- go get -v github.com/mattn/goveralls
|
||||||
|
|||||||
4
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
4
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
@@ -1,4 +1,6 @@
|
|||||||
Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
31
vendor/github.com/davecgh/go-spew/README.md
generated
vendored
31
vendor/github.com/davecgh/go-spew/README.md
generated
vendored
@@ -1,11 +1,13 @@
|
|||||||
go-spew
|
go-spew
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[]
|
[]
|
||||||
(https://travis-ci.org/davecgh/go-spew) [![Coverage Status]
|
(https://travis-ci.org/davecgh/go-spew) [![ISC License]
|
||||||
(https://coveralls.io/repos/davecgh/go-spew/badge.png?branch=master)]
|
(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![Coverage Status]
|
||||||
|
(https://img.shields.io/coveralls/davecgh/go-spew.svg)]
|
||||||
(https://coveralls.io/r/davecgh/go-spew?branch=master)
|
(https://coveralls.io/r/davecgh/go-spew?branch=master)
|
||||||
|
|
||||||
|
|
||||||
Go-spew implements a deep pretty printer for Go data structures to aid in
|
Go-spew implements a deep pretty printer for Go data structures to aid in
|
||||||
debugging. A comprehensive suite of tests with 100% test coverage is provided
|
debugging. A comprehensive suite of tests with 100% test coverage is provided
|
||||||
to ensure proper functionality. See `test_coverage.txt` for the gocov coverage
|
to ensure proper functionality. See `test_coverage.txt` for the gocov coverage
|
||||||
@@ -15,11 +17,11 @@ open source or commercial projects.
|
|||||||
If you're interested in reading about how this package came to life and some
|
If you're interested in reading about how this package came to life and some
|
||||||
of the challenges involved in providing a deep pretty printer, there is a blog
|
of the challenges involved in providing a deep pretty printer, there is a blog
|
||||||
post about it
|
post about it
|
||||||
[here](https://blog.cyphertite.com/go-spew-a-journey-into-dumping-go-data-structures/).
|
[here](https://web.archive.org/web/20160304013555/https://blog.cyphertite.com/go-spew-a-journey-into-dumping-go-data-structures/).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
[]
|
[]
|
||||||
(http://godoc.org/github.com/davecgh/go-spew/spew)
|
(http://godoc.org/github.com/davecgh/go-spew/spew)
|
||||||
|
|
||||||
Full `go doc` style documentation for the project can be viewed online without
|
Full `go doc` style documentation for the project can be viewed online without
|
||||||
@@ -157,9 +159,18 @@ options. See the ConfigState documentation for more details.
|
|||||||
which only accept pointer receivers from non-pointer variables. This option
|
which only accept pointer receivers from non-pointer variables. This option
|
||||||
relies on access to the unsafe package, so it will not have any effect when
|
relies on access to the unsafe package, so it will not have any effect when
|
||||||
running in environments without access to the unsafe package such as Google
|
running in environments without access to the unsafe package such as Google
|
||||||
App Engine or with the "disableunsafe" build tag specified.
|
App Engine or with the "safe" build tag specified.
|
||||||
Pointer method invocation is enabled by default.
|
Pointer method invocation is enabled by default.
|
||||||
|
|
||||||
|
* DisablePointerAddresses
|
||||||
|
DisablePointerAddresses specifies whether to disable the printing of
|
||||||
|
pointer addresses. This is useful when diffing data structures in tests.
|
||||||
|
|
||||||
|
* DisableCapacities
|
||||||
|
DisableCapacities specifies whether to disable the printing of capacities
|
||||||
|
for arrays, slices, maps and channels. This is useful when diffing data
|
||||||
|
structures in tests.
|
||||||
|
|
||||||
* ContinueOnMethod
|
* ContinueOnMethod
|
||||||
Enables recursion into types after invoking error and Stringer interface
|
Enables recursion into types after invoking error and Stringer interface
|
||||||
methods. Recursion after method invocation is disabled by default.
|
methods. Recursion after method invocation is disabled by default.
|
||||||
@@ -185,10 +196,10 @@ options. See the ConfigState documentation for more details.
|
|||||||
This package relies on the unsafe package to perform some of the more advanced
|
This package relies on the unsafe package to perform some of the more advanced
|
||||||
features, however it also supports a "limited" mode which allows it to work in
|
features, however it also supports a "limited" mode which allows it to work in
|
||||||
environments where the unsafe package is not available. By default, it will
|
environments where the unsafe package is not available. By default, it will
|
||||||
operate in this mode on Google App Engine. The "disableunsafe" build tag may
|
operate in this mode on Google App Engine and when compiled with GopherJS. The
|
||||||
also be specified to force the package to build without using the unsafe
|
"safe" build tag may also be specified to force the package to build without
|
||||||
package.
|
using the unsafe package.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Go-spew is licensed under the liberal ISC License.
|
Go-spew is licensed under the [copyfree](http://copyfree.org) ISC License.
|
||||||
|
|||||||
9
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -13,9 +13,10 @@
|
|||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
// when the code is not running on Google App Engine and "-tags disableunsafe"
|
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||||
// is not added to the go build command line.
|
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||||
// +build !appengine,!disableunsafe
|
// tag is deprecated and thus should not be used.
|
||||||
|
// +build !js,!appengine,!safe,!disableunsafe
|
||||||
|
|
||||||
package spew
|
package spew
|
||||||
|
|
||||||
|
|||||||
9
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -13,9 +13,10 @@
|
|||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
// when either the code is running on Google App Engine or "-tags disableunsafe"
|
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||||
// is added to the go build command line.
|
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||||
// +build appengine disableunsafe
|
// tag is deprecated and thus should not be used.
|
||||||
|
// +build js appengine safe disableunsafe
|
||||||
|
|
||||||
package spew
|
package spew
|
||||||
|
|
||||||
|
|||||||
4
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
4
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
|||||||
w.Write(closeParenBytes)
|
w.Write(closeParenBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
|
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
||||||
// prefix to Writer w.
|
// prefix to Writer w.
|
||||||
func printHexPtr(w io.Writer, p uintptr) {
|
func printHexPtr(w io.Writer, p uintptr) {
|
||||||
// Null pointer.
|
// Null pointer.
|
||||||
|
|||||||
2
vendor/github.com/davecgh/go-spew/spew/common_test.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/common_test.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
13
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
13
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -64,9 +64,18 @@ type ConfigState struct {
|
|||||||
// inside these interface methods. As a result, this option relies on
|
// inside these interface methods. As a result, this option relies on
|
||||||
// access to the unsafe package, so it will not have any effect when
|
// access to the unsafe package, so it will not have any effect when
|
||||||
// running in environments without access to the unsafe package such as
|
// running in environments without access to the unsafe package such as
|
||||||
// Google App Engine or with the "disableunsafe" build tag specified.
|
// Google App Engine or with the "safe" build tag specified.
|
||||||
DisablePointerMethods bool
|
DisablePointerMethods bool
|
||||||
|
|
||||||
|
// DisablePointerAddresses specifies whether to disable the printing of
|
||||||
|
// pointer addresses. This is useful when diffing data structures in tests.
|
||||||
|
DisablePointerAddresses bool
|
||||||
|
|
||||||
|
// DisableCapacities specifies whether to disable the printing of capacities
|
||||||
|
// for arrays, slices, maps and channels. This is useful when diffing
|
||||||
|
// data structures in tests.
|
||||||
|
DisableCapacities bool
|
||||||
|
|
||||||
// ContinueOnMethod specifies whether or not recursion should continue once
|
// ContinueOnMethod specifies whether or not recursion should continue once
|
||||||
// a custom error or Stringer interface is invoked. The default, false,
|
// a custom error or Stringer interface is invoked. The default, false,
|
||||||
// means it will print the results of invoking the custom error or Stringer
|
// means it will print the results of invoking the custom error or Stringer
|
||||||
|
|||||||
11
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
11
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -91,6 +91,15 @@ The following configuration options are available:
|
|||||||
which only accept pointer receivers from non-pointer variables.
|
which only accept pointer receivers from non-pointer variables.
|
||||||
Pointer method invocation is enabled by default.
|
Pointer method invocation is enabled by default.
|
||||||
|
|
||||||
|
* DisablePointerAddresses
|
||||||
|
DisablePointerAddresses specifies whether to disable the printing of
|
||||||
|
pointer addresses. This is useful when diffing data structures in tests.
|
||||||
|
|
||||||
|
* DisableCapacities
|
||||||
|
DisableCapacities specifies whether to disable the printing of
|
||||||
|
capacities for arrays, slices, maps and channels. This is useful when
|
||||||
|
diffing data structures in tests.
|
||||||
|
|
||||||
* ContinueOnMethod
|
* ContinueOnMethod
|
||||||
Enables recursion into types after invoking error and Stringer interface
|
Enables recursion into types after invoking error and Stringer interface
|
||||||
methods. Recursion after method invocation is disabled by default.
|
methods. Recursion after method invocation is disabled by default.
|
||||||
|
|||||||
8
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
8
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -129,7 +129,7 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
|
|||||||
d.w.Write(closeParenBytes)
|
d.w.Write(closeParenBytes)
|
||||||
|
|
||||||
// Display pointer information.
|
// Display pointer information.
|
||||||
if len(pointerChain) > 0 {
|
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
|
||||||
d.w.Write(openParenBytes)
|
d.w.Write(openParenBytes)
|
||||||
for i, addr := range pointerChain {
|
for i, addr := range pointerChain {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@@ -282,13 +282,13 @@ func (d *dumpState) dump(v reflect.Value) {
|
|||||||
case reflect.Map, reflect.String:
|
case reflect.Map, reflect.String:
|
||||||
valueLen = v.Len()
|
valueLen = v.Len()
|
||||||
}
|
}
|
||||||
if valueLen != 0 || valueCap != 0 {
|
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
|
||||||
d.w.Write(openParenBytes)
|
d.w.Write(openParenBytes)
|
||||||
if valueLen != 0 {
|
if valueLen != 0 {
|
||||||
d.w.Write(lenEqualsBytes)
|
d.w.Write(lenEqualsBytes)
|
||||||
printInt(d.w, int64(valueLen), 10)
|
printInt(d.w, int64(valueLen), 10)
|
||||||
}
|
}
|
||||||
if valueCap != 0 {
|
if !d.cs.DisableCapacities && valueCap != 0 {
|
||||||
if valueLen != 0 {
|
if valueLen != 0 {
|
||||||
d.w.Write(spaceBytes)
|
d.w.Write(spaceBytes)
|
||||||
}
|
}
|
||||||
|
|||||||
4
vendor/github.com/davecgh/go-spew/spew/dump_test.go
generated
vendored
4
vendor/github.com/davecgh/go-spew/spew/dump_test.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -70,7 +70,7 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
)
|
)
|
||||||
|
|
||||||
// dumpTest is used to describe a test to be perfomed against the Dump method.
|
// dumpTest is used to describe a test to be performed against the Dump method.
|
||||||
type dumpTest struct {
|
type dumpTest struct {
|
||||||
in interface{}
|
in interface{}
|
||||||
wants []string
|
wants []string
|
||||||
|
|||||||
5
vendor/github.com/davecgh/go-spew/spew/dumpcgo_test.go
generated
vendored
5
vendor/github.com/davecgh/go-spew/spew/dumpcgo_test.go
generated
vendored
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2013 Dave Collins <dave@davec.name>
|
// Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -59,10 +59,11 @@ func addCgoDumpTests() {
|
|||||||
v3Len := fmt.Sprintf("%d", v3l)
|
v3Len := fmt.Sprintf("%d", v3l)
|
||||||
v3Cap := fmt.Sprintf("%d", v3c)
|
v3Cap := fmt.Sprintf("%d", v3c)
|
||||||
v3t := "[6]testdata._Ctype_unsignedchar"
|
v3t := "[6]testdata._Ctype_unsignedchar"
|
||||||
|
v3t2 := "[6]testdata._Ctype_uchar"
|
||||||
v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " +
|
v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " +
|
||||||
"{\n 00000000 74 65 73 74 33 00 " +
|
"{\n 00000000 74 65 73 74 33 00 " +
|
||||||
" |test3.|\n}"
|
" |test3.|\n}"
|
||||||
addDumpTest(v3, "("+v3t+") "+v3s+"\n")
|
addDumpTest(v3, "("+v3t+") "+v3s+"\n", "("+v3t2+") "+v3s+"\n")
|
||||||
|
|
||||||
// C signed char array.
|
// C signed char array.
|
||||||
v4, v4l, v4c := testdata.GetCgoSignedCharArray()
|
v4, v4l, v4c := testdata.GetCgoSignedCharArray()
|
||||||
|
|||||||
2
vendor/github.com/davecgh/go-spew/spew/example_test.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/example_test.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
2
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
4
vendor/github.com/davecgh/go-spew/spew/format_test.go
generated
vendored
4
vendor/github.com/davecgh/go-spew/spew/format_test.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -75,7 +75,7 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
)
|
)
|
||||||
|
|
||||||
// formatterTest is used to describe a test to be perfomed against NewFormatter.
|
// formatterTest is used to describe a test to be performed against NewFormatter.
|
||||||
type formatterTest struct {
|
type formatterTest struct {
|
||||||
format string
|
format string
|
||||||
in interface{}
|
in interface{}
|
||||||
|
|||||||
2
vendor/github.com/davecgh/go-spew/spew/internal_test.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/internal_test.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
9
vendor/github.com/davecgh/go-spew/spew/internalunsafe_test.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/internalunsafe_test.go
generated
vendored
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2013-2015 Dave Collins <dave@davec.name>
|
// Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -13,9 +13,10 @@
|
|||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
// when the code is not running on Google App Engine and "-tags disableunsafe"
|
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||||
// is not added to the go build command line.
|
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||||
// +build !appengine,!disableunsafe
|
// tag is deprecated and thus should not be used.
|
||||||
|
// +build !js,!appengine,!safe,!disableunsafe
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This test file is part of the spew package rather than than the spew_test
|
This test file is part of the spew package rather than than the spew_test
|
||||||
|
|||||||
2
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
13
vendor/github.com/davecgh/go-spew/spew/spew_test.go
generated
vendored
13
vendor/github.com/davecgh/go-spew/spew/spew_test.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -130,12 +130,19 @@ func initSpewTests() {
|
|||||||
scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
|
scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
|
||||||
scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
|
scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
|
||||||
scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
|
scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
|
||||||
|
scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true}
|
||||||
|
scsNoCap := &spew.ConfigState{DisableCapacities: true}
|
||||||
|
|
||||||
// Variables for tests on types which implement Stringer interface with and
|
// Variables for tests on types which implement Stringer interface with and
|
||||||
// without a pointer receiver.
|
// without a pointer receiver.
|
||||||
ts := stringer("test")
|
ts := stringer("test")
|
||||||
tps := pstringer("test")
|
tps := pstringer("test")
|
||||||
|
|
||||||
|
type ptrTester struct {
|
||||||
|
s *struct{}
|
||||||
|
}
|
||||||
|
tptr := &ptrTester{s: &struct{}{}}
|
||||||
|
|
||||||
// depthTester is used to test max depth handling for structs, array, slices
|
// depthTester is used to test max depth handling for structs, array, slices
|
||||||
// and maps.
|
// and maps.
|
||||||
type depthTester struct {
|
type depthTester struct {
|
||||||
@@ -192,6 +199,10 @@ func initSpewTests() {
|
|||||||
{scsContinue, fCSFprint, "", te, "(error: 10) 10"},
|
{scsContinue, fCSFprint, "", te, "(error: 10) 10"},
|
||||||
{scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
|
{scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
|
||||||
"(error: 10) 10\n"},
|
"(error: 10) 10\n"},
|
||||||
|
{scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"},
|
||||||
|
{scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"},
|
||||||
|
{scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"},
|
||||||
|
{scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
vendor/github.com/docker/distribution/.mailmap
generated
vendored
2
vendor/github.com/docker/distribution/.mailmap
generated
vendored
@@ -14,3 +14,5 @@ Sven Dowideit <SvenDowideit@home.org.au> Sven Dowideit <SvenDowideit@users.norep
|
|||||||
Vincent Giersch <vincent.giersch@ovh.net> Vincent Giersch <vincent@giersch.fr>
|
Vincent Giersch <vincent.giersch@ovh.net> Vincent Giersch <vincent@giersch.fr>
|
||||||
davidli <wenquan.li@hp.com> davidli <wenquan.li@hpe.com>
|
davidli <wenquan.li@hp.com> davidli <wenquan.li@hpe.com>
|
||||||
Omer Cohen <git@omer.io> Omer Cohen <git@omerc.net>
|
Omer Cohen <git@omer.io> Omer Cohen <git@omerc.net>
|
||||||
|
Eric Yang <windfarer@gmail.com> Eric Yang <Windfarer@users.noreply.github.com>
|
||||||
|
Nikita Tarasov <nikita@mygento.ru> Nikita <luckyraul@users.noreply.github.com>
|
||||||
|
|||||||
54
vendor/github.com/docker/distribution/AUTHORS
generated
vendored
54
vendor/github.com/docker/distribution/AUTHORS
generated
vendored
@@ -1,32 +1,47 @@
|
|||||||
|
a-palchikov <deemok@gmail.com>
|
||||||
Aaron Lehmann <aaron.lehmann@docker.com>
|
Aaron Lehmann <aaron.lehmann@docker.com>
|
||||||
|
Aaron Schlesinger <aschlesinger@deis.com>
|
||||||
Aaron Vinson <avinson.public@gmail.com>
|
Aaron Vinson <avinson.public@gmail.com>
|
||||||
|
Adam Duke <adam.v.duke@gmail.com>
|
||||||
Adam Enger <adamenger@gmail.com>
|
Adam Enger <adamenger@gmail.com>
|
||||||
Adrian Mouat <adrian.mouat@gmail.com>
|
Adrian Mouat <adrian.mouat@gmail.com>
|
||||||
Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
|
Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
|
||||||
Alex Chan <alex.chan@metaswitch.com>
|
Alex Chan <alex.chan@metaswitch.com>
|
||||||
Alex Elman <aelman@indeed.com>
|
Alex Elman <aelman@indeed.com>
|
||||||
|
Alexey Gladkov <gladkov.alexey@gmail.com>
|
||||||
|
allencloud <allen.sun@daocloud.io>
|
||||||
amitshukla <ashukla73@hotmail.com>
|
amitshukla <ashukla73@hotmail.com>
|
||||||
Amy Lindburg <amy.lindburg@docker.com>
|
Amy Lindburg <amy.lindburg@docker.com>
|
||||||
|
Andrew Hsu <andrewhsu@acm.org>
|
||||||
Andrew Meredith <andymeredith@gmail.com>
|
Andrew Meredith <andymeredith@gmail.com>
|
||||||
Andrew T Nguyen <andrew.nguyen@docker.com>
|
Andrew T Nguyen <andrew.nguyen@docker.com>
|
||||||
Andrey Kostov <kostov.andrey@gmail.com>
|
Andrey Kostov <kostov.andrey@gmail.com>
|
||||||
Andy Goldstein <agoldste@redhat.com>
|
Andy Goldstein <agoldste@redhat.com>
|
||||||
|
Anis Elleuch <vadmeste@gmail.com>
|
||||||
Anton Tiurin <noxiouz@yandex.ru>
|
Anton Tiurin <noxiouz@yandex.ru>
|
||||||
Antonio Mercado <amercado@thinknode.com>
|
Antonio Mercado <amercado@thinknode.com>
|
||||||
Antonio Murdaca <runcom@redhat.com>
|
Antonio Murdaca <runcom@redhat.com>
|
||||||
|
Anusha Ragunathan <anusha@docker.com>
|
||||||
|
Arien Holthuizen <aholthuizen@schubergphilis.com>
|
||||||
Arnaud Porterie <arnaud.porterie@docker.com>
|
Arnaud Porterie <arnaud.porterie@docker.com>
|
||||||
Arthur Baars <arthur@semmle.com>
|
Arthur Baars <arthur@semmle.com>
|
||||||
Asuka Suzuki <hello@tanksuzuki.com>
|
Asuka Suzuki <hello@tanksuzuki.com>
|
||||||
Avi Miller <avi.miller@oracle.com>
|
Avi Miller <avi.miller@oracle.com>
|
||||||
Ayose Cazorla <ayosec@gmail.com>
|
Ayose Cazorla <ayosec@gmail.com>
|
||||||
BadZen <dave.trombley@gmail.com>
|
BadZen <dave.trombley@gmail.com>
|
||||||
|
Ben Bodenmiller <bbodenmiller@hotmail.com>
|
||||||
Ben Firshman <ben@firshman.co.uk>
|
Ben Firshman <ben@firshman.co.uk>
|
||||||
bin liu <liubin0329@gmail.com>
|
bin liu <liubin0329@gmail.com>
|
||||||
Brian Bland <brian.bland@docker.com>
|
Brian Bland <brian.bland@docker.com>
|
||||||
burnettk <burnettk@gmail.com>
|
burnettk <burnettk@gmail.com>
|
||||||
Carson A <ca@carsonoid.net>
|
Carson A <ca@carsonoid.net>
|
||||||
|
Cezar Sa Espinola <cezarsa@gmail.com>
|
||||||
|
Charles Smith <charles.smith@docker.com>
|
||||||
Chris Dillon <squarism@gmail.com>
|
Chris Dillon <squarism@gmail.com>
|
||||||
|
cuiwei13 <cuiwei13@pku.edu.cn>
|
||||||
|
cyli <cyli@twistedmatrix.com>
|
||||||
Daisuke Fujita <dtanshi45@gmail.com>
|
Daisuke Fujita <dtanshi45@gmail.com>
|
||||||
|
Daniel Huhn <daniel@danielhuhn.de>
|
||||||
Darren Shepherd <darren@rancher.com>
|
Darren Shepherd <darren@rancher.com>
|
||||||
Dave Trombley <dave.trombley@gmail.com>
|
Dave Trombley <dave.trombley@gmail.com>
|
||||||
Dave Tucker <dt@docker.com>
|
Dave Tucker <dt@docker.com>
|
||||||
@@ -40,12 +55,17 @@ Diogo Mónica <diogo.monica@gmail.com>
|
|||||||
DJ Enriquez <dj.enriquez@infospace.com>
|
DJ Enriquez <dj.enriquez@infospace.com>
|
||||||
Donald Huang <don.hcd@gmail.com>
|
Donald Huang <don.hcd@gmail.com>
|
||||||
Doug Davis <dug@us.ibm.com>
|
Doug Davis <dug@us.ibm.com>
|
||||||
|
Edgar Lee <edgar.lee@docker.com>
|
||||||
Eric Yang <windfarer@gmail.com>
|
Eric Yang <windfarer@gmail.com>
|
||||||
|
Fabio Berchtold <jamesclonk@jamesclonk.ch>
|
||||||
|
Fabio Huser <fabio@fh1.ch>
|
||||||
farmerworking <farmerworking@gmail.com>
|
farmerworking <farmerworking@gmail.com>
|
||||||
Felix Yan <felixonmars@archlinux.org>
|
Felix Yan <felixonmars@archlinux.org>
|
||||||
Florentin Raud <florentin.raud@gmail.com>
|
Florentin Raud <florentin.raud@gmail.com>
|
||||||
|
Frank Chen <frankchn@gmail.com>
|
||||||
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
|
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
|
||||||
gabriell nascimento <gabriell@bluesoft.com.br>
|
gabriell nascimento <gabriell@bluesoft.com.br>
|
||||||
|
Gleb Schukin <gschukin@ptsecurity.com>
|
||||||
harche <p.harshal@gmail.com>
|
harche <p.harshal@gmail.com>
|
||||||
Henri Gomez <henri.gomez@gmail.com>
|
Henri Gomez <henri.gomez@gmail.com>
|
||||||
Hu Keping <hukeping@huawei.com>
|
Hu Keping <hukeping@huawei.com>
|
||||||
@@ -54,16 +74,26 @@ HuKeping <hukeping@huawei.com>
|
|||||||
Ian Babrou <ibobrik@gmail.com>
|
Ian Babrou <ibobrik@gmail.com>
|
||||||
igayoso <igayoso@gmail.com>
|
igayoso <igayoso@gmail.com>
|
||||||
Jack Griffin <jackpg14@gmail.com>
|
Jack Griffin <jackpg14@gmail.com>
|
||||||
|
James Findley <jfindley@fastmail.com>
|
||||||
Jason Freidman <jason.freidman@gmail.com>
|
Jason Freidman <jason.freidman@gmail.com>
|
||||||
|
Jason Heiss <jheiss@aput.net>
|
||||||
Jeff Nickoloff <jeff@allingeek.com>
|
Jeff Nickoloff <jeff@allingeek.com>
|
||||||
|
Jess Frazelle <acidburn@google.com>
|
||||||
Jessie Frazelle <jessie@docker.com>
|
Jessie Frazelle <jessie@docker.com>
|
||||||
|
jhaohai <jhaohai@foxmail.com>
|
||||||
Jianqing Wang <tsing@jianqing.org>
|
Jianqing Wang <tsing@jianqing.org>
|
||||||
|
Jihoon Chung <jihoon@gmail.com>
|
||||||
|
Joao Fernandes <joao.fernandes@docker.com>
|
||||||
|
John Mulhausen <john@docker.com>
|
||||||
John Starks <jostarks@microsoft.com>
|
John Starks <jostarks@microsoft.com>
|
||||||
|
Jon Johnson <jonjohnson@google.com>
|
||||||
Jon Poler <jonathan.poler@apcera.com>
|
Jon Poler <jonathan.poler@apcera.com>
|
||||||
Jonathan Boulle <jonathanboulle@gmail.com>
|
Jonathan Boulle <jonathanboulle@gmail.com>
|
||||||
Jordan Liggitt <jliggitt@redhat.com>
|
Jordan Liggitt <jliggitt@redhat.com>
|
||||||
|
Josh Chorlton <josh.chorlton@docker.com>
|
||||||
Josh Hawn <josh.hawn@docker.com>
|
Josh Hawn <josh.hawn@docker.com>
|
||||||
Julien Fernandez <julien.fernandez@gmail.com>
|
Julien Fernandez <julien.fernandez@gmail.com>
|
||||||
|
Ke Xu <leonhartx.k@gmail.com>
|
||||||
Keerthan Mala <kmala@engineyard.com>
|
Keerthan Mala <kmala@engineyard.com>
|
||||||
Kelsey Hightower <kelsey.hightower@gmail.com>
|
Kelsey Hightower <kelsey.hightower@gmail.com>
|
||||||
Kenneth Lim <kennethlimcp@gmail.com>
|
Kenneth Lim <kennethlimcp@gmail.com>
|
||||||
@@ -71,38 +101,56 @@ Kenny Leung <kleung@google.com>
|
|||||||
Li Yi <denverdino@gmail.com>
|
Li Yi <denverdino@gmail.com>
|
||||||
Liu Hua <sdu.liu@huawei.com>
|
Liu Hua <sdu.liu@huawei.com>
|
||||||
liuchang0812 <liuchang0812@gmail.com>
|
liuchang0812 <liuchang0812@gmail.com>
|
||||||
|
Lloyd Ramey <lnr0626@gmail.com>
|
||||||
Louis Kottmann <louis.kottmann@gmail.com>
|
Louis Kottmann <louis.kottmann@gmail.com>
|
||||||
Luke Carpenter <x@rubynerd.net>
|
Luke Carpenter <x@rubynerd.net>
|
||||||
|
Marcus Martins <marcus@docker.com>
|
||||||
Mary Anthony <mary@docker.com>
|
Mary Anthony <mary@docker.com>
|
||||||
Matt Bentley <mbentley@mbentley.net>
|
Matt Bentley <mbentley@mbentley.net>
|
||||||
Matt Duch <matt@learnmetrics.com>
|
Matt Duch <matt@learnmetrics.com>
|
||||||
Matt Moore <mattmoor@google.com>
|
Matt Moore <mattmoor@google.com>
|
||||||
Matt Robenolt <matt@ydekproductions.com>
|
Matt Robenolt <matt@ydekproductions.com>
|
||||||
|
Matthew Green <greenmr@live.co.uk>
|
||||||
Michael Prokop <mika@grml.org>
|
Michael Prokop <mika@grml.org>
|
||||||
Michal Minar <miminar@redhat.com>
|
Michal Minar <miminar@redhat.com>
|
||||||
|
Michal Minář <miminar@redhat.com>
|
||||||
|
Mike Brown <brownwm@us.ibm.com>
|
||||||
Miquel Sabaté <msabate@suse.com>
|
Miquel Sabaté <msabate@suse.com>
|
||||||
|
Misty Stanley-Jones <misty@apache.org>
|
||||||
|
Misty Stanley-Jones <misty@docker.com>
|
||||||
Morgan Bauer <mbauer@us.ibm.com>
|
Morgan Bauer <mbauer@us.ibm.com>
|
||||||
moxiegirl <mary@docker.com>
|
moxiegirl <mary@docker.com>
|
||||||
Nathan Sullivan <nathan@nightsys.net>
|
Nathan Sullivan <nathan@nightsys.net>
|
||||||
nevermosby <robolwq@qq.com>
|
nevermosby <robolwq@qq.com>
|
||||||
Nghia Tran <tcnghia@gmail.com>
|
Nghia Tran <tcnghia@gmail.com>
|
||||||
|
Nikita Tarasov <nikita@mygento.ru>
|
||||||
|
Noah Treuhaft <noah.treuhaft@docker.com>
|
||||||
Nuutti Kotivuori <nuutti.kotivuori@poplatek.fi>
|
Nuutti Kotivuori <nuutti.kotivuori@poplatek.fi>
|
||||||
Oilbeater <liumengxinfly@gmail.com>
|
Oilbeater <liumengxinfly@gmail.com>
|
||||||
Olivier Gambier <olivier@docker.com>
|
Olivier Gambier <olivier@docker.com>
|
||||||
Olivier Jacques <olivier.jacques@hp.com>
|
Olivier Jacques <olivier.jacques@hp.com>
|
||||||
Omer Cohen <git@omer.io>
|
Omer Cohen <git@omer.io>
|
||||||
Patrick Devine <patrick.devine@docker.com>
|
Patrick Devine <patrick.devine@docker.com>
|
||||||
|
Phil Estes <estesp@linux.vnet.ibm.com>
|
||||||
Philip Misiowiec <philip@atlashealth.com>
|
Philip Misiowiec <philip@atlashealth.com>
|
||||||
|
Pierre-Yves Ritschard <pyr@spootnik.org>
|
||||||
|
Qiao Anran <qiaoanran@gmail.com>
|
||||||
|
Randy Barlow <randy@electronsweatshop.com>
|
||||||
Richard Scothern <richard.scothern@docker.com>
|
Richard Scothern <richard.scothern@docker.com>
|
||||||
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
||||||
Rusty Conover <rusty@luckydinosaur.com>
|
Rusty Conover <rusty@luckydinosaur.com>
|
||||||
Sean Boran <Boran@users.noreply.github.com>
|
Sean Boran <Boran@users.noreply.github.com>
|
||||||
Sebastiaan van Stijn <github@gone.nl>
|
Sebastiaan van Stijn <github@gone.nl>
|
||||||
|
Sebastien Coavoux <s.coavoux@free.fr>
|
||||||
|
Serge Dubrouski <sergeyfd@gmail.com>
|
||||||
Sharif Nassar <sharif@mrwacky.com>
|
Sharif Nassar <sharif@mrwacky.com>
|
||||||
Shawn Falkner-Horine <dreadpirateshawn@gmail.com>
|
Shawn Falkner-Horine <dreadpirateshawn@gmail.com>
|
||||||
Shreyas Karnik <karnik.shreyas@gmail.com>
|
Shreyas Karnik <karnik.shreyas@gmail.com>
|
||||||
Simon Thulbourn <simon+github@thulbourn.com>
|
Simon Thulbourn <simon+github@thulbourn.com>
|
||||||
|
spacexnice <yaoyao.xyy@alibaba-inc.com>
|
||||||
Spencer Rinehart <anubis@overthemonkey.com>
|
Spencer Rinehart <anubis@overthemonkey.com>
|
||||||
|
Stan Hu <stanhu@gmail.com>
|
||||||
|
Stefan Majewsky <stefan.majewsky@sap.com>
|
||||||
Stefan Weil <sw@weilnetz.de>
|
Stefan Weil <sw@weilnetz.de>
|
||||||
Stephen J Day <stephen.day@docker.com>
|
Stephen J Day <stephen.day@docker.com>
|
||||||
Sungho Moon <sungho.moon@navercorp.com>
|
Sungho Moon <sungho.moon@navercorp.com>
|
||||||
@@ -114,8 +162,11 @@ Thomas Sjögren <konstruktoid@users.noreply.github.com>
|
|||||||
Tianon Gravi <admwiggin@gmail.com>
|
Tianon Gravi <admwiggin@gmail.com>
|
||||||
Tibor Vass <teabee89@gmail.com>
|
Tibor Vass <teabee89@gmail.com>
|
||||||
Tonis Tiigi <tonistiigi@gmail.com>
|
Tonis Tiigi <tonistiigi@gmail.com>
|
||||||
|
Tony Holdstock-Brown <tony@docker.com>
|
||||||
Trevor Pounds <trevor.pounds@gmail.com>
|
Trevor Pounds <trevor.pounds@gmail.com>
|
||||||
Troels Thomsen <troels@thomsen.io>
|
Troels Thomsen <troels@thomsen.io>
|
||||||
|
Victor Vieux <vieux@docker.com>
|
||||||
|
Victoria Bialas <victoria.bialas@docker.com>
|
||||||
Vincent Batts <vbatts@redhat.com>
|
Vincent Batts <vbatts@redhat.com>
|
||||||
Vincent Demeester <vincent@sbr.pm>
|
Vincent Demeester <vincent@sbr.pm>
|
||||||
Vincent Giersch <vincent.giersch@ovh.net>
|
Vincent Giersch <vincent.giersch@ovh.net>
|
||||||
@@ -124,5 +175,8 @@ weiyuan.yl <weiyuan.yl@alibaba-inc.com>
|
|||||||
xg.song <xg.song@venusource.com>
|
xg.song <xg.song@venusource.com>
|
||||||
xiekeyang <xiekeyang@huawei.com>
|
xiekeyang <xiekeyang@huawei.com>
|
||||||
Yann ROBERT <yann.robert@anantaplex.fr>
|
Yann ROBERT <yann.robert@anantaplex.fr>
|
||||||
|
yaoyao.xyy <yaoyao.xyy@alibaba-inc.com>
|
||||||
|
yuexiao-wang <wang.yuexiao@zte.com.cn>
|
||||||
yuzou <zouyu7@huawei.com>
|
yuzou <zouyu7@huawei.com>
|
||||||
|
zhouhaibing089 <zhouhaibing089@gmail.com>
|
||||||
姜继忠 <jizhong.jiangjz@alibaba-inc.com>
|
姜继忠 <jizhong.jiangjz@alibaba-inc.com>
|
||||||
|
|||||||
117
vendor/github.com/docker/distribution/BUILDING.md
generated
vendored
Normal file
117
vendor/github.com/docker/distribution/BUILDING.md
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
# Building the registry source
|
||||||
|
|
||||||
|
## Use-case
|
||||||
|
|
||||||
|
This is useful if you intend to actively work on the registry.
|
||||||
|
|
||||||
|
### Alternatives
|
||||||
|
|
||||||
|
Most people should use the [official Registry docker image](https://hub.docker.com/r/library/registry/).
|
||||||
|
|
||||||
|
People looking for advanced operational use cases might consider rolling their own image with a custom Dockerfile inheriting `FROM registry:2`.
|
||||||
|
|
||||||
|
OS X users who want to run natively can do so following [the instructions here](https://github.com/docker/docker.github.io/blob/master/registry/recipes/osx-setup-guide.md).
|
||||||
|
|
||||||
|
### Gotchas
|
||||||
|
|
||||||
|
You are expected to know your way around with go & git.
|
||||||
|
|
||||||
|
If you are a casual user with no development experience, and no preliminary knowledge of go, building from source is probably not a good solution for you.
|
||||||
|
|
||||||
|
## Build the development environment
|
||||||
|
|
||||||
|
The first prerequisite of properly building distribution targets is to have a Go
|
||||||
|
development environment setup. Please follow [How to Write Go Code](https://golang.org/doc/code.html)
|
||||||
|
for proper setup. If done correctly, you should have a GOROOT and GOPATH set in the
|
||||||
|
environment.
|
||||||
|
|
||||||
|
If a Go development environment is setup, one can use `go get` to install the
|
||||||
|
`registry` command from the current latest:
|
||||||
|
|
||||||
|
go get github.com/docker/distribution/cmd/registry
|
||||||
|
|
||||||
|
The above will install the source repository into the `GOPATH`.
|
||||||
|
|
||||||
|
Now create the directory for the registry data (this might require you to set permissions properly)
|
||||||
|
|
||||||
|
mkdir -p /var/lib/registry
|
||||||
|
|
||||||
|
... or alternatively `export REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/somewhere` if you want to store data into another location.
|
||||||
|
|
||||||
|
The `registry`
|
||||||
|
binary can then be run with the following:
|
||||||
|
|
||||||
|
$ $GOPATH/bin/registry --version
|
||||||
|
$GOPATH/bin/registry github.com/docker/distribution v2.0.0-alpha.1+unknown
|
||||||
|
|
||||||
|
> __NOTE:__ While you do not need to use `go get` to checkout the distribution
|
||||||
|
> project, for these build instructions to work, the project must be checked
|
||||||
|
> out in the correct location in the `GOPATH`. This should almost always be
|
||||||
|
> `$GOPATH/src/github.com/docker/distribution`.
|
||||||
|
|
||||||
|
The registry can be run with the default config using the following
|
||||||
|
incantation:
|
||||||
|
|
||||||
|
$ $GOPATH/bin/registry serve $GOPATH/src/github.com/docker/distribution/cmd/registry/config-example.yml
|
||||||
|
INFO[0000] endpoint local-5003 disabled, skipping app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown
|
||||||
|
INFO[0000] endpoint local-8083 disabled, skipping app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown
|
||||||
|
INFO[0000] listening on :5000 app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown
|
||||||
|
INFO[0000] debug server listening localhost:5001
|
||||||
|
|
||||||
|
If it is working, one should see the above log messages.
|
||||||
|
|
||||||
|
### Repeatable Builds
|
||||||
|
|
||||||
|
For the full development experience, one should `cd` into
|
||||||
|
`$GOPATH/src/github.com/docker/distribution`. From there, the regular `go`
|
||||||
|
commands, such as `go test`, should work per package (please see
|
||||||
|
[Developing](#developing) if they don't work).
|
||||||
|
|
||||||
|
A `Makefile` has been provided as a convenience to support repeatable builds.
|
||||||
|
Please install the following into `GOPATH` for it to work:
|
||||||
|
|
||||||
|
go get github.com/golang/lint/golint
|
||||||
|
|
||||||
|
Once these commands are available in the `GOPATH`, run `make` to get a full
|
||||||
|
build:
|
||||||
|
|
||||||
|
$ make
|
||||||
|
+ clean
|
||||||
|
+ fmt
|
||||||
|
+ vet
|
||||||
|
+ lint
|
||||||
|
+ build
|
||||||
|
github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar
|
||||||
|
github.com/sirupsen/logrus
|
||||||
|
github.com/docker/libtrust
|
||||||
|
...
|
||||||
|
github.com/yvasiyarov/gorelic
|
||||||
|
github.com/docker/distribution/registry/handlers
|
||||||
|
github.com/docker/distribution/cmd/registry
|
||||||
|
+ test
|
||||||
|
...
|
||||||
|
ok github.com/docker/distribution/digest 7.875s
|
||||||
|
ok github.com/docker/distribution/manifest 0.028s
|
||||||
|
ok github.com/docker/distribution/notifications 17.322s
|
||||||
|
? github.com/docker/distribution/registry [no test files]
|
||||||
|
ok github.com/docker/distribution/registry/api/v2 0.101s
|
||||||
|
? github.com/docker/distribution/registry/auth [no test files]
|
||||||
|
ok github.com/docker/distribution/registry/auth/silly 0.011s
|
||||||
|
...
|
||||||
|
+ /Users/sday/go/src/github.com/docker/distribution/bin/registry
|
||||||
|
+ /Users/sday/go/src/github.com/docker/distribution/bin/registry-api-descriptor-template
|
||||||
|
+ binaries
|
||||||
|
|
||||||
|
The above provides a repeatable build using the contents of the vendor
|
||||||
|
directory. This includes formatting, vetting, linting, building,
|
||||||
|
testing and generating tagged binaries. We can verify this worked by running
|
||||||
|
the registry binary generated in the "./bin" directory:
|
||||||
|
|
||||||
|
$ ./bin/registry -version
|
||||||
|
./bin/registry github.com/docker/distribution v2.0.0-alpha.2-80-g16d8b2c.m
|
||||||
|
|
||||||
|
### Optional build tags
|
||||||
|
|
||||||
|
Optional [build tags](http://golang.org/pkg/go/build/) can be provided using
|
||||||
|
the environment variable `DOCKER_BUILDTAGS`.
|
||||||
108
vendor/github.com/docker/distribution/CHANGELOG.md
generated
vendored
Normal file
108
vendor/github.com/docker/distribution/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2.6.0 (2017-01-18)
|
||||||
|
|
||||||
|
#### Storage
|
||||||
|
- S3: fixed bug in delete due to read-after-write inconsistency
|
||||||
|
- S3: allow EC2 IAM roles to be used when authorizing region endpoints
|
||||||
|
- S3: add Object ACL Support
|
||||||
|
- S3: fix delete method's notion of subpaths
|
||||||
|
- S3: use multipart upload API in `Move` method for performance
|
||||||
|
- S3: add v2 signature signing for legacy S3 clones
|
||||||
|
- Swift: add simple heuristic to detect incomplete DLOs during read ops
|
||||||
|
- Swift: support different user and tenant domains
|
||||||
|
- Swift: bulk deletes in chunks
|
||||||
|
- Aliyun OSS: fix delete method's notion of subpaths
|
||||||
|
- Aliyun OSS: optimize data copy after upload finishes
|
||||||
|
- Azure: close leaking response body
|
||||||
|
- Fix storage drivers dropping non-EOF errors when listing repositories
|
||||||
|
- Compare path properly when listing repositories in catalog
|
||||||
|
- Add a foreign layer URL host whitelist
|
||||||
|
- Improve catalog enumerate runtime
|
||||||
|
|
||||||
|
#### Registry
|
||||||
|
- Export `storage.CreateOptions` in top-level package
|
||||||
|
- Enable notifications to endpoints that use self-signed certificates
|
||||||
|
- Properly validate multi-URL foreign layers
|
||||||
|
- Add control over validation of URLs in pushed manifests
|
||||||
|
- Proxy mode: fix socket leak when pull is cancelled
|
||||||
|
- Tag service: properly handle error responses on HEAD request
|
||||||
|
- Support for custom authentication URL in proxying registry
|
||||||
|
- Add configuration option to disable access logging
|
||||||
|
- Add notification filtering by target media type
|
||||||
|
- Manifest: `References()` returns all children
|
||||||
|
- Honor `X-Forwarded-Port` and Forwarded headers
|
||||||
|
- Reference: Preserve tag and digest in With* functions
|
||||||
|
- Add policy configuration for enforcing repository classes
|
||||||
|
|
||||||
|
#### Client
|
||||||
|
- Changes the client Tags `All()` method to follow links
|
||||||
|
- Allow registry clients to connect via HTTP2
|
||||||
|
- Better handling of OAuth errors in client
|
||||||
|
|
||||||
|
#### Spec
|
||||||
|
- Manifest: clarify relationship between urls and foreign layers
|
||||||
|
- Authorization: add support for repository classes
|
||||||
|
|
||||||
|
#### Manifest
|
||||||
|
- Override media type returned from `Stat()` for existing manifests
|
||||||
|
- Add plugin mediatype to distribution manifest
|
||||||
|
|
||||||
|
#### Docs
|
||||||
|
- Document `TOOMANYREQUESTS` error code
|
||||||
|
- Document required Let's Encrypt port
|
||||||
|
- Improve documentation around implementation of OAuth2
|
||||||
|
- Improve documentation for configuration
|
||||||
|
|
||||||
|
#### Auth
|
||||||
|
- Add support for registry type in scope
|
||||||
|
- Add support for using v2 ping challenges for v1
|
||||||
|
- Add leeway to JWT `nbf` and `exp` checking
|
||||||
|
- htpasswd: dynamically parse htpasswd file
|
||||||
|
- Fix missing auth headers with PATCH HTTP request when pushing to default port
|
||||||
|
|
||||||
|
#### Dockerfile
|
||||||
|
- Update to go1.7
|
||||||
|
- Reorder Dockerfile steps for better layer caching
|
||||||
|
|
||||||
|
#### Notes
|
||||||
|
|
||||||
|
Documentation has moved to the documentation repository at
|
||||||
|
`github.com/docker/docker.github.io/tree/master/registry`
|
||||||
|
|
||||||
|
The registry is go 1.7 compliant, and passes newer, more restrictive `lint` and `vet` ing.
|
||||||
|
|
||||||
|
|
||||||
|
## 2.5.0 (2016-06-14)
|
||||||
|
|
||||||
|
#### Storage
|
||||||
|
- Ensure uploads directory is cleaned after upload is committed
|
||||||
|
- Add ability to cap concurrent operations in filesystem driver
|
||||||
|
- S3: Add 'us-gov-west-1' to the valid region list
|
||||||
|
- Swift: Handle ceph not returning Last-Modified header for HEAD requests
|
||||||
|
- Add redirect middleware
|
||||||
|
|
||||||
|
#### Registry
|
||||||
|
- Add support for blobAccessController middleware
|
||||||
|
- Add support for layers from foreign sources
|
||||||
|
- Remove signature store
|
||||||
|
- Add support for Let's Encrypt
|
||||||
|
- Correct yaml key names in configuration
|
||||||
|
|
||||||
|
#### Client
|
||||||
|
- Add option to get content digest from manifest get
|
||||||
|
|
||||||
|
#### Spec
|
||||||
|
- Update the auth spec scope grammar to reflect the fact that hostnames are optionally supported
|
||||||
|
- Clarify API documentation around catalog fetch behavior
|
||||||
|
|
||||||
|
#### API
|
||||||
|
- Support returning HTTP 429 (Too Many Requests)
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
- Update auth documentation examples to show "expires in" as int
|
||||||
|
|
||||||
|
#### Docker Image
|
||||||
|
- Use Alpine Linux as base image
|
||||||
|
|
||||||
|
|
||||||
8
vendor/github.com/docker/distribution/CONTRIBUTING.md
generated
vendored
8
vendor/github.com/docker/distribution/CONTRIBUTING.md
generated
vendored
@@ -21,6 +21,14 @@ Then please do not open an issue here yet - you should first try one of the foll
|
|||||||
- irc: #docker-distribution on freenode
|
- irc: #docker-distribution on freenode
|
||||||
- mailing-list: <distribution@dockerproject.org> or https://groups.google.com/a/dockerproject.org/forum/#!forum/distribution
|
- mailing-list: <distribution@dockerproject.org> or https://groups.google.com/a/dockerproject.org/forum/#!forum/distribution
|
||||||
|
|
||||||
|
### Reporting security issues
|
||||||
|
|
||||||
|
The Docker maintainers take security seriously. If you discover a security
|
||||||
|
issue, please bring it to their attention right away!
|
||||||
|
|
||||||
|
Please **DO NOT** file a public issue, instead send your report privately to
|
||||||
|
[security@docker.com](mailto:security@docker.com).
|
||||||
|
|
||||||
## Reporting an issue properly
|
## Reporting an issue properly
|
||||||
|
|
||||||
By following these simple rules you will get better and faster feedback on your issue.
|
By following these simple rules you will get better and faster feedback on your issue.
|
||||||
|
|||||||
13
vendor/github.com/docker/distribution/Dockerfile
generated
vendored
13
vendor/github.com/docker/distribution/Dockerfile
generated
vendored
@@ -1,15 +1,18 @@
|
|||||||
FROM golang:1.6
|
FROM golang:1.8-alpine
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y apache2-utils && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution
|
ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution
|
||||||
ENV DOCKER_BUILDTAGS include_oss include_gcs
|
ENV DOCKER_BUILDTAGS include_oss include_gcs
|
||||||
|
|
||||||
|
ARG GOOS=linux
|
||||||
|
ARG GOARCH=amd64
|
||||||
|
|
||||||
|
RUN set -ex \
|
||||||
|
&& apk add --no-cache make git
|
||||||
|
|
||||||
WORKDIR $DISTRIBUTION_DIR
|
WORKDIR $DISTRIBUTION_DIR
|
||||||
COPY . $DISTRIBUTION_DIR
|
COPY . $DISTRIBUTION_DIR
|
||||||
COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml
|
COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml
|
||||||
|
|
||||||
RUN make PREFIX=/go clean binaries
|
RUN make PREFIX=/go clean binaries
|
||||||
|
|
||||||
VOLUME ["/var/lib/registry"]
|
VOLUME ["/var/lib/registry"]
|
||||||
|
|||||||
430
vendor/github.com/docker/distribution/Godeps/Godeps.json
generated
vendored
430
vendor/github.com/docker/distribution/Godeps/Godeps.json
generated
vendored
@@ -1,430 +0,0 @@
|
|||||||
{
|
|
||||||
"ImportPath": "github.com/docker/distribution",
|
|
||||||
"GoVersion": "go1.6",
|
|
||||||
"GodepVersion": "v60",
|
|
||||||
"Packages": [
|
|
||||||
"./..."
|
|
||||||
],
|
|
||||||
"Deps": [
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Azure/azure-sdk-for-go/storage",
|
|
||||||
"Comment": "v1.2-334-g95361a2",
|
|
||||||
"Rev": "95361a2573b1fa92a00c5fc2707a80308483c6f9"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Sirupsen/logrus",
|
|
||||||
"Comment": "v0.7.3",
|
|
||||||
"Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Sirupsen/logrus/formatters/logstash",
|
|
||||||
"Comment": "v0.7.3",
|
|
||||||
"Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/cloudfront/sign",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
|
||||||
"Comment": "v1.1.0-14-g49c3892",
|
|
||||||
"Rev": "49c3892b61af1d4996292a3025f36e4dfa25eaee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/bugsnag/bugsnag-go",
|
|
||||||
"Comment": "v1.0.2-5-gb1d1530",
|
|
||||||
"Rev": "b1d153021fcd90ca3f080db36bec96dc690fb274"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/bugsnag/bugsnag-go/errors",
|
|
||||||
"Comment": "v1.0.2-5-gb1d1530",
|
|
||||||
"Rev": "b1d153021fcd90ca3f080db36bec96dc690fb274"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/bugsnag/osext",
|
|
||||||
"Rev": "0dd3f918b21bec95ace9dc86c7e70266cfc5c702"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/bugsnag/panicwrap",
|
|
||||||
"Comment": "1.0.0-2-ge2c2850",
|
|
||||||
"Rev": "e2c28503fcd0675329da73bf48b33404db873782"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/denverdino/aliyungo/common",
|
|
||||||
"Rev": "6ffb587da9da6d029d0ce517b85fecc82172d502"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/denverdino/aliyungo/oss",
|
|
||||||
"Rev": "6ffb587da9da6d029d0ce517b85fecc82172d502"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/denverdino/aliyungo/util",
|
|
||||||
"Rev": "6ffb587da9da6d029d0ce517b85fecc82172d502"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/docker/goamz/aws",
|
|
||||||
"Rev": "f0a21f5b2e12f83a505ecf79b633bb2035cf6f85"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/docker/goamz/s3",
|
|
||||||
"Rev": "f0a21f5b2e12f83a505ecf79b633bb2035cf6f85"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/docker/libtrust",
|
|
||||||
"Rev": "fa567046d9b14f6aa788882a950d69651d230b21"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/garyburd/redigo/internal",
|
|
||||||
"Rev": "535138d7bcd717d6531c701ef5933d98b1866257"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/garyburd/redigo/redis",
|
|
||||||
"Rev": "535138d7bcd717d6531c701ef5933d98b1866257"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/go-ini/ini",
|
|
||||||
"Comment": "v1.8.6",
|
|
||||||
"Rev": "afbd495e5aaea13597b5e14fe514ddeaa4d76fc3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/golang/protobuf/proto",
|
|
||||||
"Rev": "8d92cf5fc15a4382f8964b08e1f42a75c0591aa3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/gorilla/context",
|
|
||||||
"Rev": "14f550f51af52180c2eefed15e5fd18d63c0a64a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/gorilla/handlers",
|
|
||||||
"Rev": "60c7bfde3e33c201519a200a4507a158cc03a17b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/gorilla/mux",
|
|
||||||
"Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/inconshreveable/mousetrap",
|
|
||||||
"Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/jmespath/go-jmespath",
|
|
||||||
"Comment": "0.2.2-12-g0b12d6b",
|
|
||||||
"Rev": "0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/mapstructure",
|
|
||||||
"Rev": "482a9fd5fa83e8c4e7817413b80f3eb8feec03ef"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/ncw/swift",
|
|
||||||
"Rev": "c54732e87b0b283d1baf0a18db689d0aea460ba3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/ncw/swift/swifttest",
|
|
||||||
"Rev": "c54732e87b0b283d1baf0a18db689d0aea460ba3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/spf13/cobra",
|
|
||||||
"Rev": "312092086bed4968099259622145a0c9ae280064"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/spf13/pflag",
|
|
||||||
"Rev": "5644820622454e71517561946e3d94b9f9db6842"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/stevvooe/resumable",
|
|
||||||
"Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/stevvooe/resumable/sha256",
|
|
||||||
"Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/stevvooe/resumable/sha512",
|
|
||||||
"Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/yvasiyarov/go-metrics",
|
|
||||||
"Rev": "57bccd1ccd43f94bb17fdd8bf3007059b802f85e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/yvasiyarov/gorelic",
|
|
||||||
"Comment": "v0.0.6-8-ga9bba5b",
|
|
||||||
"Rev": "a9bba5b9ab508a086f9a12b8c51fab68478e2128"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/yvasiyarov/newrelic_platform_go",
|
|
||||||
"Rev": "b21fdbd4370f3717f3bbd2bf41c223bc273068e6"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
|
||||||
"Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/crypto/blowfish",
|
|
||||||
"Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/context",
|
|
||||||
"Rev": "4876518f9e71663000c348837735820161a42df7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
|
||||||
"Rev": "4876518f9e71663000c348837735820161a42df7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/http2",
|
|
||||||
"Rev": "4876518f9e71663000c348837735820161a42df7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/http2/hpack",
|
|
||||||
"Rev": "4876518f9e71663000c348837735820161a42df7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/internal/timeseries",
|
|
||||||
"Rev": "4876518f9e71663000c348837735820161a42df7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/trace",
|
|
||||||
"Rev": "4876518f9e71663000c348837735820161a42df7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/oauth2",
|
|
||||||
"Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/oauth2/google",
|
|
||||||
"Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/oauth2/internal",
|
|
||||||
"Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/oauth2/jws",
|
|
||||||
"Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/oauth2/jwt",
|
|
||||||
"Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/api/gensupport",
|
|
||||||
"Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/api/googleapi",
|
|
||||||
"Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/api/googleapi/internal/uritemplates",
|
|
||||||
"Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/api/storage/v1",
|
|
||||||
"Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal/app_identity",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal/base",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal/datastore",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal/log",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal/modules",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/appengine/internal/remote_api",
|
|
||||||
"Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/cloud",
|
|
||||||
"Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/cloud/compute/metadata",
|
|
||||||
"Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/cloud/internal",
|
|
||||||
"Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/cloud/internal/opts",
|
|
||||||
"Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/cloud/storage",
|
|
||||||
"Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/codes",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/credentials",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/grpclog",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/internal",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/metadata",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/naming",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/peer",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "google.golang.org/grpc/transport",
|
|
||||||
"Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "gopkg.in/check.v1",
|
|
||||||
"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "gopkg.in/yaml.v2",
|
|
||||||
"Rev": "bef53efd0c76e49e6de55ead051f886bea7e9420"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
5
vendor/github.com/docker/distribution/MAINTAINERS
generated
vendored
5
vendor/github.com/docker/distribution/MAINTAINERS
generated
vendored
@@ -32,11 +32,6 @@
|
|||||||
Email = "aaron.lehmann@docker.com"
|
Email = "aaron.lehmann@docker.com"
|
||||||
GitHub = "aaronlehmann"
|
GitHub = "aaronlehmann"
|
||||||
|
|
||||||
[people.brianbland]
|
|
||||||
Name = "Brian Bland"
|
|
||||||
Email = "brian.bland@docker.com"
|
|
||||||
GitHub = "BrianBland"
|
|
||||||
|
|
||||||
[people.dmcgowan]
|
[people.dmcgowan]
|
||||||
Name = "Derek McGowan"
|
Name = "Derek McGowan"
|
||||||
Email = "derek@mcgstyle.net"
|
Email = "derek@mcgstyle.net"
|
||||||
|
|||||||
41
vendor/github.com/docker/distribution/Makefile
generated
vendored
41
vendor/github.com/docker/distribution/Makefile
generated
vendored
@@ -13,7 +13,7 @@ endif
|
|||||||
|
|
||||||
GO_LDFLAGS=-ldflags "-X `go list ./version`.Version=$(VERSION)"
|
GO_LDFLAGS=-ldflags "-X `go list ./version`.Version=$(VERSION)"
|
||||||
|
|
||||||
.PHONY: clean all fmt vet lint build test binaries
|
.PHONY: all build binaries clean dep-restore dep-save dep-validate fmt lint test test-full vet
|
||||||
.DEFAULT: all
|
.DEFAULT: all
|
||||||
all: fmt vet lint build test binaries
|
all: fmt vet lint build test binaries
|
||||||
|
|
||||||
@@ -27,22 +27,25 @@ version/version.go:
|
|||||||
# Required for go 1.5 to build
|
# Required for go 1.5 to build
|
||||||
GO15VENDOREXPERIMENT := 1
|
GO15VENDOREXPERIMENT := 1
|
||||||
|
|
||||||
|
# Go files
|
||||||
|
GOFILES=$(shell find . -type f -name '*.go')
|
||||||
|
|
||||||
# Package list
|
# Package list
|
||||||
PKGS := $(shell go list -tags "${DOCKER_BUILDTAGS}" ./... | grep -v ^github.com/docker/distribution/vendor/)
|
PKGS=$(shell go list -tags "${DOCKER_BUILDTAGS}" ./... | grep -v ^github.com/docker/distribution/vendor/)
|
||||||
|
|
||||||
# Resolving binary dependencies for specific targets
|
# Resolving binary dependencies for specific targets
|
||||||
GOLINT := $(shell which golint || echo '')
|
GOLINT=$(shell which golint || echo '')
|
||||||
GODEP := $(shell which godep || echo '')
|
VNDR=$(shell which vndr || echo '')
|
||||||
|
|
||||||
${PREFIX}/bin/registry: $(wildcard **/*.go)
|
${PREFIX}/bin/registry: $(GOFILES)
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry
|
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry
|
||||||
|
|
||||||
${PREFIX}/bin/digest: $(wildcard **/*.go)
|
${PREFIX}/bin/digest: $(GOFILES)
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/digest
|
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/digest
|
||||||
|
|
||||||
${PREFIX}/bin/registry-api-descriptor-template: $(wildcard **/*.go)
|
${PREFIX}/bin/registry-api-descriptor-template: $(GOFILES)
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
@go build -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry-api-descriptor-template
|
@go build -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry-api-descriptor-template
|
||||||
|
|
||||||
@@ -83,24 +86,14 @@ clean:
|
|||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
@rm -rf "${PREFIX}/bin/registry" "${PREFIX}/bin/digest" "${PREFIX}/bin/registry-api-descriptor-template"
|
@rm -rf "${PREFIX}/bin/registry" "${PREFIX}/bin/digest" "${PREFIX}/bin/registry-api-descriptor-template"
|
||||||
|
|
||||||
dep-save:
|
dep-validate:
|
||||||
@echo "+ $@"
|
|
||||||
$(if $(GODEP), , \
|
|
||||||
$(error Please install godep: go get github.com/tools/godep))
|
|
||||||
@$(GODEP) save $(PKGS)
|
|
||||||
|
|
||||||
dep-restore:
|
|
||||||
@echo "+ $@"
|
|
||||||
$(if $(GODEP), , \
|
|
||||||
$(error Please install godep: go get github.com/tools/godep))
|
|
||||||
@$(GODEP) restore -v
|
|
||||||
|
|
||||||
dep-validate: dep-restore
|
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
|
$(if $(VNDR), , \
|
||||||
|
$(error Please install vndr: go get github.com/lk4d4/vndr))
|
||||||
@rm -Rf .vendor.bak
|
@rm -Rf .vendor.bak
|
||||||
@mv vendor .vendor.bak
|
@mv vendor .vendor.bak
|
||||||
@rm -Rf Godeps
|
@$(VNDR)
|
||||||
@$(GODEP) save ./...
|
|
||||||
@test -z "$$(diff -r vendor .vendor.bak 2>&1 | tee /dev/stderr)" || \
|
@test -z "$$(diff -r vendor .vendor.bak 2>&1 | tee /dev/stderr)" || \
|
||||||
(echo >&2 "+ borked dependencies! what you have in Godeps/Godeps.json does not match with what you have in vendor" && false)
|
(echo >&2 "+ inconsistent dependencies! what you have in vendor.conf does not match with what you have in vendor" && false)
|
||||||
@rm -Rf .vendor.bak
|
@rm -Rf vendor
|
||||||
|
@mv .vendor.bak vendor
|
||||||
|
|||||||
9
vendor/github.com/docker/distribution/README.md
generated
vendored
9
vendor/github.com/docker/distribution/README.md
generated
vendored
@@ -19,7 +19,7 @@ This repository contains the following components:
|
|||||||
| **registry** | An implementation of the [Docker Registry HTTP API V2](docs/spec/api.md) for use with docker 1.6+. |
|
| **registry** | An implementation of the [Docker Registry HTTP API V2](docs/spec/api.md) for use with docker 1.6+. |
|
||||||
| **libraries** | A rich set of libraries for interacting with distribution components. Please see [godoc](https://godoc.org/github.com/docker/distribution) for details. **Note**: These libraries are **unstable**. |
|
| **libraries** | A rich set of libraries for interacting with distribution components. Please see [godoc](https://godoc.org/github.com/docker/distribution) for details. **Note**: These libraries are **unstable**. |
|
||||||
| **specifications** | _Distribution_ related specifications are available in [docs/spec](docs/spec) |
|
| **specifications** | _Distribution_ related specifications are available in [docs/spec](docs/spec) |
|
||||||
| **documentation** | Docker's full documentation set is available at [docs.docker.com](https://docs.docker.com). This repository [contains the subset](docs/index.md) related just to the registry. |
|
| **documentation** | Docker's full documentation set is available at [docs.docker.com](https://docs.docker.com). This repository [contains the subset](docs/) related just to the registry. |
|
||||||
|
|
||||||
### How does this integrate with Docker engine?
|
### How does this integrate with Docker engine?
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ others, it is not.
|
|||||||
For example, users with their own software products may want to maintain a
|
For example, users with their own software products may want to maintain a
|
||||||
registry for private, company images. Also, you may wish to deploy your own
|
registry for private, company images. Also, you may wish to deploy your own
|
||||||
image repository for images used to test or in continuous integration. For these
|
image repository for images used to test or in continuous integration. For these
|
||||||
use cases and others, [deploying your own registry instance](docs/deploying.md)
|
use cases and others, [deploying your own registry instance](https://github.com/docker/docker.github.io/blob/master/registry/deploying.md)
|
||||||
may be the better choice.
|
may be the better choice.
|
||||||
|
|
||||||
### Migration to Registry 2.0
|
### Migration to Registry 2.0
|
||||||
@@ -76,14 +76,13 @@ may be the better choice.
|
|||||||
For those who have previously deployed their own registry based on the Registry
|
For those who have previously deployed their own registry based on the Registry
|
||||||
1.0 implementation and wish to deploy a Registry 2.0 while retaining images,
|
1.0 implementation and wish to deploy a Registry 2.0 while retaining images,
|
||||||
data migration is required. A tool to assist with migration efforts has been
|
data migration is required. A tool to assist with migration efforts has been
|
||||||
created. For more information see [docker/migrator]
|
created. For more information see [docker/migrator](https://github.com/docker/migrator).
|
||||||
(https://github.com/docker/migrator).
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute
|
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute
|
||||||
issues, fixes, and patches to this project. If you are contributing code, see
|
issues, fixes, and patches to this project. If you are contributing code, see
|
||||||
the instructions for [building a development environment](docs/building.md).
|
the instructions for [building a development environment](BUILDING.md).
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
|||||||
44
vendor/github.com/docker/distribution/RELEASE-CHECKLIST.md
generated
vendored
Normal file
44
vendor/github.com/docker/distribution/RELEASE-CHECKLIST.md
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
## Registry Release Checklist
|
||||||
|
|
||||||
|
10. Compile release notes detailing features and since the last release.
|
||||||
|
|
||||||
|
Update the `CHANGELOG.md` file and create a PR to master with the updates.
|
||||||
|
Once that PR has been approved by maintainers the change may be cherry-picked
|
||||||
|
to the release branch (new release branches may be forked from this commit).
|
||||||
|
|
||||||
|
20. Update the version file: `https://github.com/docker/distribution/blob/master/version/version.go`
|
||||||
|
|
||||||
|
30. Update the `MAINTAINERS` (if necessary), `AUTHORS` and `.mailmap` files.
|
||||||
|
|
||||||
|
```
|
||||||
|
make AUTHORS
|
||||||
|
```
|
||||||
|
|
||||||
|
40. Create a signed tag.
|
||||||
|
|
||||||
|
Distribution uses semantic versioning. Tags are of the format
|
||||||
|
`vx.y.z[-rcn]`. You will need PGP installed and a PGP key which has been added
|
||||||
|
to your Github account. The comment for the tag should include the release
|
||||||
|
notes, use previous tags as a guide for formatting consistently. Run
|
||||||
|
`git tag -s vx.y.z[-rcn]` to create tag and `git -v vx.y.z[-rcn]` to verify tag,
|
||||||
|
check comment and correct commit hash.
|
||||||
|
|
||||||
|
50. Push the signed tag
|
||||||
|
|
||||||
|
60. Create a new [release](https://github.com/docker/distribution/releases). In the case of a release candidate, tick the `pre-release` checkbox.
|
||||||
|
|
||||||
|
70. Update the registry binary in [distribution library image repo](https://github.com/docker/distribution-library-image) by running the update script and opening a pull request.
|
||||||
|
|
||||||
|
80. Update the official image. Add the new version in the [official images repo](https://github.com/docker-library/official-images) by appending a new version to the `registry/registry` file with the git hash pointed to by the signed tag. Update the major version to point to the latest version and the minor version to point to new patch release if necessary.
|
||||||
|
e.g. to release `2.3.1`
|
||||||
|
|
||||||
|
`2.3.1 (new)`
|
||||||
|
|
||||||
|
`2.3.0 -> 2.3.0` can be removed
|
||||||
|
|
||||||
|
`2 -> 2.3.1`
|
||||||
|
|
||||||
|
`2.3 -> 2.3.1`
|
||||||
|
|
||||||
|
90. Build a new distribution/registry image on [Docker hub](https://hub.docker.com/u/distribution/dashboard) by adding a new automated build with the new tag and re-building the images.
|
||||||
|
|
||||||
2
vendor/github.com/docker/distribution/ROADMAP.md
generated
vendored
2
vendor/github.com/docker/distribution/ROADMAP.md
generated
vendored
@@ -156,7 +156,7 @@ full and understand the problems behind deletes.
|
|||||||
While, at first glance, implementing deleting seems simple, there are a number
|
While, at first glance, implementing deleting seems simple, there are a number
|
||||||
mitigating factors that make many solutions not ideal or even pathological in
|
mitigating factors that make many solutions not ideal or even pathological in
|
||||||
the context of a registry. The following paragraph discuss the background and
|
the context of a registry. The following paragraph discuss the background and
|
||||||
approaches that could be applied to a arrive at a solution.
|
approaches that could be applied to arrive at a solution.
|
||||||
|
|
||||||
The goal of deletes in any system is to remove unused or unneeded data. Only
|
The goal of deletes in any system is to remove unused or unneeded data. Only
|
||||||
data requested for deletion should be removed and no other data. Removing
|
data requested for deletion should be removed and no other data. Removing
|
||||||
|
|||||||
24
vendor/github.com/docker/distribution/blobs.go
generated
vendored
24
vendor/github.com/docker/distribution/blobs.go
generated
vendored
@@ -8,8 +8,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/digest"
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -69,6 +69,9 @@ type Descriptor struct {
|
|||||||
// against against this digest.
|
// against against this digest.
|
||||||
Digest digest.Digest `json:"digest,omitempty"`
|
Digest digest.Digest `json:"digest,omitempty"`
|
||||||
|
|
||||||
|
// URLs contains the source URLs of this content.
|
||||||
|
URLs []string `json:"urls,omitempty"`
|
||||||
|
|
||||||
// NOTE: Before adding a field here, please ensure that all
|
// NOTE: Before adding a field here, please ensure that all
|
||||||
// other options have been exhausted. Much of the type relationships
|
// other options have been exhausted. Much of the type relationships
|
||||||
// depend on the simplicity of this type.
|
// depend on the simplicity of this type.
|
||||||
@@ -124,6 +127,11 @@ type BlobDescriptorService interface {
|
|||||||
Clear(ctx context.Context, dgst digest.Digest) error
|
Clear(ctx context.Context, dgst digest.Digest) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlobDescriptorServiceFactory creates middleware for BlobDescriptorService.
|
||||||
|
type BlobDescriptorServiceFactory interface {
|
||||||
|
BlobAccessController(svc BlobDescriptorService) BlobDescriptorService
|
||||||
|
}
|
||||||
|
|
||||||
// ReadSeekCloser is the primary reader type for blob data, combining
|
// ReadSeekCloser is the primary reader type for blob data, combining
|
||||||
// io.ReadSeeker with io.Closer.
|
// io.ReadSeeker with io.Closer.
|
||||||
type ReadSeekCloser interface {
|
type ReadSeekCloser interface {
|
||||||
@@ -144,7 +152,7 @@ type BlobProvider interface {
|
|||||||
|
|
||||||
// BlobServer can serve blobs via http.
|
// BlobServer can serve blobs via http.
|
||||||
type BlobServer interface {
|
type BlobServer interface {
|
||||||
// ServeBlob attempts to serve the blob, identifed by dgst, via http. The
|
// ServeBlob attempts to serve the blob, identified by dgst, via http. The
|
||||||
// service may decide to redirect the client elsewhere or serve the data
|
// service may decide to redirect the client elsewhere or serve the data
|
||||||
// directly.
|
// directly.
|
||||||
//
|
//
|
||||||
@@ -184,6 +192,18 @@ type BlobCreateOption interface {
|
|||||||
Apply(interface{}) error
|
Apply(interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateOptions is a collection of blob creation modifiers relevant to general
|
||||||
|
// blob storage intended to be configured by the BlobCreateOption.Apply method.
|
||||||
|
type CreateOptions struct {
|
||||||
|
Mount struct {
|
||||||
|
ShouldMount bool
|
||||||
|
From reference.Canonical
|
||||||
|
// Stat allows to pass precalculated descriptor to link and return.
|
||||||
|
// Blob access check will be skipped if set.
|
||||||
|
Stat *Descriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BlobWriter provides a handle for inserting data into a blob store.
|
// BlobWriter provides a handle for inserting data into a blob store.
|
||||||
// Instances should be obtained from BlobWriteService.Writer and
|
// Instances should be obtained from BlobWriteService.Writer and
|
||||||
// BlobWriteService.Resume. If supported by the store, a writer can be
|
// BlobWriteService.Resume. If supported by the store, a writer can be
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user