mirror of
https://github.com/fluxcd/flagger.git
synced 2026-02-26 07:43:49 +00:00
Compare commits
29 Commits
0.1.0-alph
...
0.1.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3eaeec500e | ||
|
|
df98de7d11 | ||
|
|
580924e63b | ||
|
|
1b2108001f | ||
|
|
3a28768bf9 | ||
|
|
53c09f40eb | ||
|
|
074e57aa12 | ||
|
|
e16dde809d | ||
|
|
188e4ea82e | ||
|
|
4a8aa3b547 | ||
|
|
6bf4a8f95b | ||
|
|
c5ea947899 | ||
|
|
344c7db968 | ||
|
|
65b908e702 | ||
|
|
8e66baa0e7 | ||
|
|
667e915700 | ||
|
|
7af103f112 | ||
|
|
8e2f538e4c | ||
|
|
be289ef7ce | ||
|
|
4a074e50c4 | ||
|
|
fa13c92a15 | ||
|
|
dbd0908313 | ||
|
|
9b5c4586b9 | ||
|
|
bfbb272c88 | ||
|
|
4b4a88cbe5 | ||
|
|
b022124415 | ||
|
|
663dc82574 | ||
|
|
baeee62a26 | ||
|
|
56f2ee9078 |
@@ -14,7 +14,9 @@ addons:
|
||||
|
||||
script:
|
||||
- set -e
|
||||
- make test
|
||||
- make test-fmt
|
||||
- make test-codegen
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic ./pkg/controller/
|
||||
- make build
|
||||
|
||||
after_success:
|
||||
@@ -33,6 +35,8 @@ after_success:
|
||||
docker push stefanprodan/flagger:latest;
|
||||
docker push stefanprodan/flagger:$TRAVIS_TAG;
|
||||
fi
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
- rm coverage.txt
|
||||
|
||||
deploy:
|
||||
- provider: script
|
||||
|
||||
72
CONTRIBUTING.md
Normal file
72
CONTRIBUTING.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# How to Contribute
|
||||
|
||||
Flagger is [Apache 2.0 licensed](LICENSE) and accepts contributions via GitHub
|
||||
pull requests. This document outlines some of the conventions on development
|
||||
workflow, commit message formatting, contact points and other resources to make
|
||||
it easier to get your contribution accepted.
|
||||
|
||||
We gratefully welcome improvements to documentation as well as to code.
|
||||
|
||||
## Certificate of Origin
|
||||
|
||||
By contributing to this project you agree to the Developer Certificate of
|
||||
Origin (DCO). This document was created by the Linux Kernel community and is a
|
||||
simple statement that you, as a contributor, have the legal right to make the
|
||||
contribution.
|
||||
|
||||
## Chat
|
||||
|
||||
The project uses Slack: To join the conversation, simply join the
|
||||
[Weave community](https://slack.weave.works/) Slack workspace.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- Fork the repository on GitHub
|
||||
- If you want to contribute as a developer, continue reading this document for further instructions
|
||||
- If you have questions, concerns, get stuck or need a hand, let us know
|
||||
on the Slack channel. We are happy to help and look forward to having
|
||||
you part of the team. No matter in which capacity.
|
||||
- Play with the project, submit bugs, submit pull requests!
|
||||
|
||||
## Contribution workflow
|
||||
|
||||
This is a rough outline of how to prepare a contribution:
|
||||
|
||||
- Create a topic branch from where you want to base your work (usually branched from master).
|
||||
- Make commits of logical units.
|
||||
- Make sure your commit messages are in the proper format (see below).
|
||||
- Push your changes to a topic branch in your fork of the repository.
|
||||
- If you changed code:
|
||||
- add automated tests to cover your changes
|
||||
- Submit a pull request to the original repository.
|
||||
|
||||
## Acceptance policy
|
||||
|
||||
These things will make a PR more likely to be accepted:
|
||||
|
||||
- a well-described requirement
|
||||
- new code and tests follow the conventions in old code and tests
|
||||
- a good commit message (see below)
|
||||
- All code must abide [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
|
||||
- Names should abide [What's in a name](https://talks.golang.org/2014/names.slide#1)
|
||||
- Code must build on both Linux and Darwin, via plain `go build`
|
||||
- Code should have appropriate test coverage and tests should be written
|
||||
to work with `go test`
|
||||
|
||||
In general, we will merge a PR once one maintainer has endorsed it.
|
||||
For substantial changes, more people may become involved, and you might
|
||||
get asked to resubmit the PR or divide the changes into more than one PR.
|
||||
|
||||
### Format of the Commit Message
|
||||
|
||||
For Flux we prefer the following rules for good commit messages:
|
||||
|
||||
- Limit the subject to 50 characters and write as the continuation
|
||||
of the sentence "If applied, this commit will ..."
|
||||
- Explain what and why in the body, if more than a trivial change;
|
||||
wrap it at 72 characters.
|
||||
|
||||
The [following article](https://chris.beams.io/posts/git-commit/#seven-rules)
|
||||
has some more helpful advice on documenting your work.
|
||||
|
||||
This doc is adapted from the [Weaveworks Flux](https://github.com/weaveworks/flux/blob/master/CONTRIBUTING.md)
|
||||
10
Dockerfile
10
Dockerfile
@@ -13,17 +13,17 @@ RUN GIT_COMMIT=$(git rev-list -1 HEAD) && \
|
||||
|
||||
FROM alpine:3.8
|
||||
|
||||
RUN addgroup -S app \
|
||||
&& adduser -S -g app app \
|
||||
RUN addgroup -S flagger \
|
||||
&& adduser -S -g flagger flagger \
|
||||
&& apk --no-cache add ca-certificates
|
||||
|
||||
WORKDIR /home/app
|
||||
WORKDIR /home/flagger
|
||||
|
||||
COPY --from=0 /go/src/github.com/stefanprodan/flagger/flagger .
|
||||
|
||||
RUN chown -R app:app ./
|
||||
RUN chown -R flagger:flagger ./
|
||||
|
||||
USER app
|
||||
USER flagger
|
||||
|
||||
ENTRYPOINT ["./flagger"]
|
||||
|
||||
|
||||
41
Gopkg.lock
generated
41
Gopkg.lock
generated
@@ -163,7 +163,7 @@
|
||||
revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:555e31114bd0e89c6340c47ab73162e8c8d873e4d88914310923566f487bfcd5"
|
||||
digest = "1:03a74b0d86021c8269b52b7c908eb9bb3852ff590b363dad0a807cf58cec2f89"
|
||||
name = "github.com/knative/pkg"
|
||||
packages = [
|
||||
"apis",
|
||||
@@ -175,10 +175,14 @@
|
||||
"apis/istio/common/v1alpha1",
|
||||
"apis/istio/v1alpha3",
|
||||
"client/clientset/versioned",
|
||||
"client/clientset/versioned/fake",
|
||||
"client/clientset/versioned/scheme",
|
||||
"client/clientset/versioned/typed/authentication/v1alpha1",
|
||||
"client/clientset/versioned/typed/authentication/v1alpha1/fake",
|
||||
"client/clientset/versioned/typed/duck/v1alpha1",
|
||||
"client/clientset/versioned/typed/duck/v1alpha1/fake",
|
||||
"client/clientset/versioned/typed/istio/v1alpha3",
|
||||
"client/clientset/versioned/typed/istio/v1alpha3/fake",
|
||||
"signals",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
@@ -524,42 +528,72 @@
|
||||
version = "kubernetes-1.11.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:29e55bcff61dd3d1f768724450a3933ea76e6277684796eb7c315154f41db902"
|
||||
digest = "1:c7d6cf5e28c377ab4000b94b6b9ff562c4b13e7e8b948ad943f133c5104be011"
|
||||
name = "k8s.io/client-go"
|
||||
packages = [
|
||||
"discovery",
|
||||
"discovery/fake",
|
||||
"kubernetes",
|
||||
"kubernetes/fake",
|
||||
"kubernetes/scheme",
|
||||
"kubernetes/typed/admissionregistration/v1alpha1",
|
||||
"kubernetes/typed/admissionregistration/v1alpha1/fake",
|
||||
"kubernetes/typed/admissionregistration/v1beta1",
|
||||
"kubernetes/typed/admissionregistration/v1beta1/fake",
|
||||
"kubernetes/typed/apps/v1",
|
||||
"kubernetes/typed/apps/v1/fake",
|
||||
"kubernetes/typed/apps/v1beta1",
|
||||
"kubernetes/typed/apps/v1beta1/fake",
|
||||
"kubernetes/typed/apps/v1beta2",
|
||||
"kubernetes/typed/apps/v1beta2/fake",
|
||||
"kubernetes/typed/authentication/v1",
|
||||
"kubernetes/typed/authentication/v1/fake",
|
||||
"kubernetes/typed/authentication/v1beta1",
|
||||
"kubernetes/typed/authentication/v1beta1/fake",
|
||||
"kubernetes/typed/authorization/v1",
|
||||
"kubernetes/typed/authorization/v1/fake",
|
||||
"kubernetes/typed/authorization/v1beta1",
|
||||
"kubernetes/typed/authorization/v1beta1/fake",
|
||||
"kubernetes/typed/autoscaling/v1",
|
||||
"kubernetes/typed/autoscaling/v1/fake",
|
||||
"kubernetes/typed/autoscaling/v2beta1",
|
||||
"kubernetes/typed/autoscaling/v2beta1/fake",
|
||||
"kubernetes/typed/batch/v1",
|
||||
"kubernetes/typed/batch/v1/fake",
|
||||
"kubernetes/typed/batch/v1beta1",
|
||||
"kubernetes/typed/batch/v1beta1/fake",
|
||||
"kubernetes/typed/batch/v2alpha1",
|
||||
"kubernetes/typed/batch/v2alpha1/fake",
|
||||
"kubernetes/typed/certificates/v1beta1",
|
||||
"kubernetes/typed/certificates/v1beta1/fake",
|
||||
"kubernetes/typed/core/v1",
|
||||
"kubernetes/typed/core/v1/fake",
|
||||
"kubernetes/typed/events/v1beta1",
|
||||
"kubernetes/typed/events/v1beta1/fake",
|
||||
"kubernetes/typed/extensions/v1beta1",
|
||||
"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/scheduling/v1beta1",
|
||||
"kubernetes/typed/scheduling/v1beta1/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",
|
||||
"pkg/apis/clientauthentication",
|
||||
"pkg/apis/clientauthentication/v1alpha1",
|
||||
"pkg/apis/clientauthentication/v1beta1",
|
||||
@@ -657,12 +691,14 @@
|
||||
"github.com/istio/glog",
|
||||
"github.com/knative/pkg/apis/istio/v1alpha3",
|
||||
"github.com/knative/pkg/client/clientset/versioned",
|
||||
"github.com/knative/pkg/client/clientset/versioned/fake",
|
||||
"github.com/knative/pkg/signals",
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp",
|
||||
"go.uber.org/zap",
|
||||
"go.uber.org/zap/zapcore",
|
||||
"k8s.io/api/apps/v1",
|
||||
"k8s.io/api/autoscaling/v1",
|
||||
"k8s.io/api/autoscaling/v2beta1",
|
||||
"k8s.io/api/core/v1",
|
||||
"k8s.io/apimachinery/pkg/api/errors",
|
||||
"k8s.io/apimachinery/pkg/api/resource",
|
||||
@@ -680,6 +716,7 @@
|
||||
"k8s.io/client-go/discovery",
|
||||
"k8s.io/client-go/discovery/fake",
|
||||
"k8s.io/client-go/kubernetes",
|
||||
"k8s.io/client-go/kubernetes/fake",
|
||||
"k8s.io/client-go/kubernetes/scheme",
|
||||
"k8s.io/client-go/kubernetes/typed/core/v1",
|
||||
"k8s.io/client-go/plugin/pkg/client/auth/gcp",
|
||||
|
||||
4
Makefile
4
Makefile
@@ -4,7 +4,7 @@ VERSION_MINOR:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4
|
||||
PATCH:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"' | awk -F. '{print $$NF}')
|
||||
SOURCE_DIRS = cmd pkg/apis pkg/controller pkg/server pkg/logging pkg/version
|
||||
run:
|
||||
go run cmd/flagger/* -kubeconfig=$$HOME/.kube/config -log-level=info -metrics-server=https://prometheus.istio.weavedx.com
|
||||
go run cmd/flagger/* -kubeconfig=$$HOME/.kube/config -log-level=info -metrics-server=https://prometheus.iowa.weavedx.com
|
||||
|
||||
build:
|
||||
docker build -t stefanprodan/flagger:$(TAG) . -f Dockerfile
|
||||
@@ -25,7 +25,7 @@ test: test-fmt test-codegen
|
||||
go test ./...
|
||||
|
||||
helm-package:
|
||||
cd charts/ && helm package flagger/ && helm package podinfo-flagger/ && helm package grafana/
|
||||
cd charts/ && helm package flagger/ && helm package grafana/
|
||||
mv charts/*.tgz docs/
|
||||
helm repo index docs --url https://stefanprodan.github.io/flagger --merge ./docs/index.yaml
|
||||
|
||||
|
||||
33
README.md
33
README.md
@@ -2,6 +2,7 @@
|
||||
|
||||
[](https://travis-ci.org/stefanprodan/flagger)
|
||||
[](https://goreportcard.com/report/github.com/stefanprodan/flagger)
|
||||
[](https://codecov.io/gh/stefanprodan/flagger)
|
||||
[](https://github.com/stefanprodan/flagger/blob/master/LICENSE)
|
||||
[](https://github.com/stefanprodan/flagger/releases)
|
||||
|
||||
@@ -180,6 +181,7 @@ Create a deployment and a horizontal pod autoscaler:
|
||||
kubectl apply -f ${REPO}/artifacts/canaries/deployment.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/canaries/hpa.yaml
|
||||
```
|
||||
|
||||
Create a canary promotion custom resource (replace the Istio gateway and the internet domain with your own):
|
||||
|
||||
```bash
|
||||
@@ -189,15 +191,17 @@ kubectl apply -f ${REPO}/artifacts/canaries/canary.yaml
|
||||
After a couple of seconds Flagger will create the canary objects:
|
||||
|
||||
```bash
|
||||
canaries.flagger.app/podinfo
|
||||
# applied
|
||||
deployment.apps/podinfo
|
||||
deployment.apps/podinfo-primary
|
||||
horizontalpodautoscaler.autoscaling/podinfo
|
||||
canary.flagger.app/podinfo
|
||||
# generated
|
||||
deployment.apps/podinfo-primary
|
||||
horizontalpodautoscaler.autoscaling/podinfo-primary
|
||||
service/podinfo
|
||||
service/podinfo-canary
|
||||
service/podinfo-primary
|
||||
virtualservices.networking.istio.io/podinfo
|
||||
virtualservice.networking.istio.io/podinfo
|
||||
```
|
||||
|
||||

|
||||
@@ -326,12 +330,33 @@ Scaling down podinfo.test
|
||||
Promotion completed! podinfo.test
|
||||
```
|
||||
|
||||
Flagger exposes Prometheus metrics that can be used to determine the canary analysis status and the destination weight values:
|
||||
|
||||
```bash
|
||||
# Canaries total gauge
|
||||
flagger_canary_total{namespace="test"} 1
|
||||
|
||||
# Canary promotion last known status gauge
|
||||
# 0 - running, 1 - successful, 2 - failed
|
||||
flagger_canary_status{name="podinfo" namespace="test"} 1
|
||||
|
||||
# Canary traffic weight gauge
|
||||
flagger_canary_weight{workload="podinfo-primary" namespace="test"} 95
|
||||
flagger_canary_weight{workload="podinfo" namespace="test"} 5
|
||||
|
||||
# Seconds spent performing canary analysis histogram
|
||||
flagger_canary_duration_seconds_bucket{name="podinfo",namespace="test",le="10"} 6
|
||||
flagger_canary_duration_seconds_bucket{name="podinfo",namespace="test",le="+Inf"} 6
|
||||
flagger_canary_duration_seconds_sum{name="podinfo",namespace="test"} 17.3561329
|
||||
flagger_canary_duration_seconds_count{name="podinfo",namespace="test"} 6
|
||||
```
|
||||
|
||||
### Roadmap
|
||||
|
||||
* Extend the canary analysis and promotion to other types than Kubernetes deployments such as Flux Helm releases or OpenFaaS functions
|
||||
* Extend the validation mechanism to support other metrics than HTTP success rate and latency
|
||||
* Add support for comparing the canary metrics to the primary ones and do the validation based on the derivation between the two
|
||||
* Alerting: Trigger Alertmanager on successful or failed promotions (Prometheus instrumentation of the canary analysis)
|
||||
* Alerting: trigger Alertmanager on successful or failed promotions
|
||||
* Reporting: publish canary analysis results to Slack/Jira/etc
|
||||
|
||||
### Contributing
|
||||
|
||||
@@ -22,16 +22,16 @@ spec:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
# Istio virtual service host names (optional)
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
- podinfo.iowa.weavedx.com
|
||||
canaryAnalysis:
|
||||
# max number of failed metric checks before rollback
|
||||
threshold: 5
|
||||
threshold: 10
|
||||
# max traffic percentage routed to canary
|
||||
# percentage (0-100)
|
||||
maxWeight: 50
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 10
|
||||
stepWeight: 5
|
||||
metrics:
|
||||
- name: istio_requests_total
|
||||
# minimum req success rate (non 5xx responses)
|
||||
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: quay.io/stefanprodan/podinfo:1.2.1
|
||||
image: quay.io/stefanprodan/podinfo:1.3.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 9898
|
||||
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
serviceAccountName: flagger
|
||||
containers:
|
||||
- name: flagger
|
||||
image: stefanprodan/flagger:0.1.0-alpha.1
|
||||
image: stefanprodan/flagger:0.1.0-beta.6
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -8,7 +8,7 @@ spec:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
- mesh
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
- podinfo.iowa.weavedx.com
|
||||
- podinfo
|
||||
http:
|
||||
- match:
|
||||
@@ -17,18 +17,18 @@ spec:
|
||||
regex: ^(?!.*Chrome)(?=.*\bSafari\b).*$
|
||||
route:
|
||||
- destination:
|
||||
host: podinfo
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 0
|
||||
- destination:
|
||||
host: podinfo-canary
|
||||
host: podinfo
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
- route:
|
||||
- destination:
|
||||
host: podinfo
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
|
||||
@@ -10,16 +10,16 @@ spec:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
- mesh
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
- podinfo.iowa.weavedx.com
|
||||
- podinfo
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: podinfo
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
mirror:
|
||||
host: podinfo-canary
|
||||
host: podinfo
|
||||
port:
|
||||
number: 9898
|
||||
|
||||
@@ -10,17 +10,17 @@ spec:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
- mesh
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
- podinfo.iowa.weavedx.com
|
||||
- podinfo
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: podinfo
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
- destination:
|
||||
host: podinfo-canary
|
||||
host: podinfo
|
||||
port:
|
||||
number: 9898
|
||||
weight: 0
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: podinfo-canary
|
||||
name: podinfo
|
||||
namespace: test
|
||||
labels:
|
||||
app: podinfo-canary
|
||||
app: podinfo
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
@@ -13,13 +13,13 @@ spec:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo-canary
|
||||
app: podinfo
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
app: podinfo-canary
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: podinfo-canary
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo-canary
|
||||
name: podinfo
|
||||
minReplicas: 2
|
||||
maxReplicas: 3
|
||||
metrics:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: podinfo-canary
|
||||
name: podinfo
|
||||
namespace: test
|
||||
labels:
|
||||
app: podinfo-canary
|
||||
app: podinfo
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: podinfo-canary
|
||||
app: podinfo
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: podinfo
|
||||
name: podinfo-primary
|
||||
namespace: test
|
||||
labels:
|
||||
app: podinfo
|
||||
app: podinfo-primary
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
@@ -13,13 +13,13 @@ spec:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
app: podinfo-primary
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
app: podinfo
|
||||
app: podinfo-primary
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: podinfo
|
||||
name: podinfo-primary
|
||||
namespace: test
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
name: podinfo-primary
|
||||
minReplicas: 2
|
||||
maxReplicas: 4
|
||||
metrics:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: podinfo
|
||||
name: podinfo-primary
|
||||
namespace: test
|
||||
labels:
|
||||
app: podinfo
|
||||
app: podinfo-primary
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: podinfo
|
||||
app: podinfo-primary
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
|
||||
@@ -10,17 +10,17 @@ spec:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
- mesh
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
- podinfo.istio.weavedx.com
|
||||
- podinfo
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: podinfo
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
- destination:
|
||||
host: podinfo-canary
|
||||
host: podinfo
|
||||
port:
|
||||
number: 9898
|
||||
weight: 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
name: flagger
|
||||
version: 0.1.0
|
||||
appVersion: 0.1.0-alpha.1
|
||||
appVersion: 0.1.0-beta.6
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of canary deployments using Istio routing for traffic shifting and Prometheus metrics for canary analysis.
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
image:
|
||||
repository: stefanprodan/flagger
|
||||
tag: 0.1.0-alpha.1
|
||||
tag: 0.1.0-beta.6
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
controlLoopInterval: "10s"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
name: grafana
|
||||
version: 5.2.4
|
||||
appVersion: 5.2.0
|
||||
description: A Helm chart for monitoring progressive deployments powered by Istio and Flagger
|
||||
version: 0.1.0
|
||||
appVersion: 5.3.1
|
||||
description: A Grafana Helm chart for monitoring progressive deployments powered by Istio and Flagger
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"content": "<div class=\"dashboard-header text-center\">\n<span>RED: $primary.$namespace</span>\n</div>",
|
||||
"content": "<div class=\"dashboard-header text-center\">\n<span>RED: $canary.$namespace</span>\n</div>",
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 24,
|
||||
@@ -568,7 +568,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"content": "<div class=\"dashboard-header text-center\">\n<span>USE: $primary.$namespace</span>\n</div>",
|
||||
"content": "<div class=\"dashboard-header text-center\">\n<span>USE: $canary.$namespace</span>\n</div>",
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 24,
|
||||
@@ -712,7 +712,7 @@
|
||||
"targets": [
|
||||
{
|
||||
"$$hashKey": "object:1685",
|
||||
"expr": "sum(rate(container_cpu_usage_seconds_total{cpu=\"total\",namespace=\"$namespace\",pod_name=~\"$canary.*\", container_name!~\"POD|istio-proxy\"}[1m])) by (pod_name)",
|
||||
"expr": "sum(rate(container_cpu_usage_seconds_total{cpu=\"total\",namespace=\"$namespace\",pod_name=~\"$canary.*\", pod_name!~\"$primary.*\", container_name!~\"POD|istio-proxy\"}[1m])) by (pod_name)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"intervalFactor": 1,
|
||||
@@ -890,7 +890,7 @@
|
||||
"targets": [
|
||||
{
|
||||
"$$hashKey": "object:1685",
|
||||
"expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",pod_name=~\"$canary.*\", container_name!~\"POD|istio-proxy\"}) by (pod_name)",
|
||||
"expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",pod_name=~\"$canary.*\", pod_name!~\"$primary.*\", container_name!~\"POD|istio-proxy\"}) by (pod_name)",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
@@ -1098,7 +1098,7 @@
|
||||
"targets": [
|
||||
{
|
||||
"$$hashKey": "object:2598",
|
||||
"expr": "sum(rate (container_network_receive_bytes_total{namespace=\"$namespace\",pod_name=~\"$canary.*\"}[1m])) ",
|
||||
"expr": "sum(rate (container_network_receive_bytes_total{namespace=\"$namespace\",pod_name=~\"$canary.*\",pod_name!~\"$primary.*\"}[1m])) ",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "received",
|
||||
@@ -1106,7 +1106,7 @@
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:3245",
|
||||
"expr": "-sum (rate (container_network_transmit_bytes_total{namespace=\"$namespace\",pod_name=~\"$canary.*\"}[1m]))",
|
||||
"expr": "-sum (rate (container_network_transmit_bytes_total{namespace=\"$namespace\",pod_name=~\"$canary.*\",pod_name!~\"$primary.*\"}[1m]))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "transmited",
|
||||
@@ -1153,7 +1153,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"content": "<div class=\"dashboard-header text-center\">\n<span>IN/OUTBOUND: $primary.$namespace</span>\n</div>",
|
||||
"content": "<div class=\"dashboard-header text-center\">\n<span>IN/OUTBOUND: $canary.$namespace</span>\n</div>",
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 24,
|
||||
|
||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: grafana/grafana
|
||||
tag: 5.2.4
|
||||
tag: 5.3.1
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
version: 2.0.0
|
||||
appVersion: 1.2.1
|
||||
engine: gotpl
|
||||
name: podinfo-flagger
|
||||
description: Podinfo Helm chart for Flagger progressive delivery
|
||||
home: https://github.com/stefanprodan/k8s-podinfo
|
||||
maintainers:
|
||||
- email: stefanprodan@users.noreply.github.com
|
||||
name: stefanprodan
|
||||
sources:
|
||||
- https://github.com/stefanprodan/flagger
|
||||
@@ -1,56 +0,0 @@
|
||||
# Podinfo Istio
|
||||
|
||||
Podinfo is a tiny web application made with Go
|
||||
that showcases best practices of running microservices in Kubernetes.
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
Create an Istio enabled namespace:
|
||||
|
||||
```console
|
||||
kubectl create namespace test
|
||||
kubectl label namespace test istio-injection=enabled
|
||||
```
|
||||
|
||||
Create an Istio Gateway in the `istio-system` namespace named `public-gateway`:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: public-gateway
|
||||
namespace: istio-system
|
||||
spec:
|
||||
selector:
|
||||
istio: ingressgateway
|
||||
servers:
|
||||
- port:
|
||||
number: 80
|
||||
name: http
|
||||
protocol: HTTP
|
||||
hosts:
|
||||
- "*"
|
||||
tls:
|
||||
httpsRedirect: true
|
||||
- port:
|
||||
number: 443
|
||||
name: https
|
||||
protocol: HTTPS
|
||||
hosts:
|
||||
- "*"
|
||||
tls:
|
||||
mode: SIMPLE
|
||||
privateKey: /etc/istio/ingressgateway-certs/tls.key
|
||||
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
|
||||
```
|
||||
|
||||
Create the `frontend` release by specifying the external domain name:
|
||||
|
||||
```console
|
||||
helm upgrade frontend -i ./charts/podinfo-flagger \
|
||||
--namespace=test \
|
||||
--set gateway.enabled=true \
|
||||
--set gateway.host=podinfo.example.com
|
||||
```
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{{ template "podinfo-flagger.fullname" . }} has been deployed successfully!
|
||||
@@ -1,36 +0,0 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "podinfo-flagger.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
The release name is used as a full name.
|
||||
*/}}
|
||||
{{- define "podinfo-flagger.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "podinfo-flagger.primary" -}}
|
||||
{{- printf "%s-%s" .Release.Name "primary" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "podinfo-flagger.canary" -}}
|
||||
{{- printf "%s-%s" .Release.Name "canary" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "podinfo-flagger.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.canary" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "podinfo-flagger.canary" . }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.canary" . }}
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 30
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.imagePullPolicy }}
|
||||
command:
|
||||
- ./podinfo
|
||||
- --port={{ .Values.containerPort }}
|
||||
- --level={{ .Values.logLevel }}
|
||||
env:
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: green
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.containerPort }}
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:{{ .Values.containerPort }}/healthz
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:{{ .Values.containerPort }}/readyz
|
||||
periodSeconds: 3
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 12 }}
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
@@ -1,21 +0,0 @@
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.canary" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ template "podinfo-flagger.canary" . }}
|
||||
minReplicas: {{ .Values.hpa.minReplicas }}
|
||||
maxReplicas: {{ .Values.hpa.maxReplicas }}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.hpa.targetAverageUtilization }}
|
||||
@@ -1,18 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.canary" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: {{ .Values.containerPort }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ template "podinfo-flagger.canary" . }}
|
||||
@@ -1,63 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.primary" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "podinfo-flagger.primary" . }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.primary" . }}
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 30
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: "quay.io/stefanprodan/podinfo:1.1.1"
|
||||
imagePullPolicy: {{ .Values.imagePullPolicy }}
|
||||
command:
|
||||
- ./podinfo
|
||||
- --port={{ .Values.containerPort }}
|
||||
- --level={{ .Values.logLevel }}
|
||||
env:
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: blue
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.containerPort }}
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:{{ .Values.containerPort }}/healthz
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:{{ .Values.containerPort }}/readyz
|
||||
periodSeconds: 3
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 12 }}
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
@@ -1,21 +0,0 @@
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.primary" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ template "podinfo-flagger.primary" . }}
|
||||
minReplicas: {{ .Values.hpa.minReplicas }}
|
||||
maxReplicas: {{ .Values.hpa.maxReplicas }}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.hpa.targetAverageUtilization }}
|
||||
@@ -1,18 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.primary" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: {{ .Values.containerPort }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ template "podinfo-flagger.primary" . }}
|
||||
@@ -1,30 +0,0 @@
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: {{ template "podinfo-flagger.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo-flagger.fullname" . }}
|
||||
chart: {{ template "podinfo-flagger.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
hosts:
|
||||
- {{ template "podinfo-flagger.fullname" . }}
|
||||
{{- if .Values.gateway.enabled }}
|
||||
- {{ .Values.gateway.host }}
|
||||
gateways:
|
||||
- {{ .Values.gateway.name }}
|
||||
{{- end }}
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: {{ template "podinfo-flagger.primary" . }}
|
||||
port:
|
||||
number: {{ .Values.containerPort }}
|
||||
weight: 100
|
||||
- destination:
|
||||
host: {{ template "podinfo-flagger.canary" . }}
|
||||
port:
|
||||
number: {{ .Values.containerPort }}
|
||||
weight: 0
|
||||
timeout: {{ .Values.timeout }}
|
||||
@@ -1,30 +0,0 @@
|
||||
# Default values for podinfo-flagger.
|
||||
|
||||
image:
|
||||
repository: quay.io/stefanprodan/podinfo
|
||||
tag: "1.2.0"
|
||||
|
||||
# enable the gateway when exposing the service outside the cluster
|
||||
gateway:
|
||||
enabled: false
|
||||
name: public-gateway.istio-system.svc.cluster.local
|
||||
# external domain name
|
||||
host:
|
||||
|
||||
hpa:
|
||||
minReplicas: 2
|
||||
maxReplicas: 4
|
||||
targetAverageUtilization: 99
|
||||
|
||||
timeout: 30s
|
||||
logLevel: info
|
||||
containerPort: 9898
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
@@ -64,13 +64,13 @@ func main() {
|
||||
logger.Fatalf("Error building shared clientset: %v", err)
|
||||
}
|
||||
|
||||
rolloutClient, err := clientset.NewForConfig(cfg)
|
||||
flaggerClient, err := clientset.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
logger.Fatalf("Error building example clientset: %s", err.Error())
|
||||
}
|
||||
|
||||
canaryInformerFactory := informers.NewSharedInformerFactory(rolloutClient, time.Second*30)
|
||||
canaryInformer := canaryInformerFactory.Flagger().V1alpha1().Canaries()
|
||||
flaggerInformerFactory := informers.NewSharedInformerFactory(flaggerClient, time.Second*30)
|
||||
canaryInformer := flaggerInformerFactory.Flagger().V1alpha1().Canaries()
|
||||
|
||||
logger.Infof("Starting flagger version %s revision %s", version.VERSION, version.REVISION)
|
||||
|
||||
@@ -94,14 +94,14 @@ func main() {
|
||||
c := controller.NewController(
|
||||
kubeClient,
|
||||
sharedClient,
|
||||
rolloutClient,
|
||||
flaggerClient,
|
||||
canaryInformer,
|
||||
controlLoopInterval,
|
||||
metricsServer,
|
||||
logger,
|
||||
)
|
||||
|
||||
canaryInformerFactory.Start(stopCh)
|
||||
flaggerInformerFactory.Start(stopCh)
|
||||
|
||||
logger.Info("Waiting for informer caches to sync")
|
||||
for _, synced := range []cache.InformerSynced{
|
||||
|
||||
73
code-of-conduct.md
Normal file
73
code-of-conduct.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
education, socio-economic status, nationality, personal appearance, race,
|
||||
religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
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, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior
|
||||
may be reported by contacting stefan.prodan(at)gmail.com.
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed
|
||||
necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of
|
||||
an incident. Further details of specific enforcement policies may be
|
||||
posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
240
docs/README.md
240
docs/README.md
@@ -2,6 +2,7 @@
|
||||
|
||||
[](https://travis-ci.org/stefanprodan/flagger)
|
||||
[](https://goreportcard.com/report/github.com/stefanprodan/flagger)
|
||||
[](https://codecov.io/gh/stefanprodan/flagger)
|
||||
[](https://github.com/stefanprodan/flagger/blob/master/LICENSE)
|
||||
[](https://github.com/stefanprodan/flagger/releases)
|
||||
|
||||
@@ -19,7 +20,7 @@ Deploy Flagger in the `istio-system` namespace using Helm:
|
||||
|
||||
```bash
|
||||
# add the Helm repository
|
||||
helm repo add flagger https://stefanprodan.github.io/flagger
|
||||
helm repo add flagger https://flagger.app
|
||||
|
||||
# install or upgrade
|
||||
helm upgrade -i flagger flagger/flagger \
|
||||
@@ -32,10 +33,11 @@ Flagger is compatible with Kubernetes >1.10.0 and Istio >1.0.0.
|
||||
|
||||
### Usage
|
||||
|
||||
Flagger requires two Kubernetes [deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/):
|
||||
one for the version you want to upgrade called _primary_ and one for the _canary_.
|
||||
Each deployment must have a corresponding ClusterIP [service](https://kubernetes.io/docs/concepts/services-networking/service/)
|
||||
that exposes a port named http or https. These services are used as destinations in a Istio [virtual service](https://istio.io/docs/reference/config/istio.networking.v1alpha3/#VirtualService).
|
||||
Flagger takes a Kubernetes deployment and creates a series of objects
|
||||
(Kubernetes [deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/),
|
||||
ClusterIP [services](https://kubernetes.io/docs/concepts/services-networking/service/) and
|
||||
Istio [virtual services](https://istio.io/docs/reference/config/istio.networking.v1alpha3/#VirtualService))
|
||||
to drive the canary analysis and promotion.
|
||||
|
||||

|
||||
|
||||
@@ -44,25 +46,25 @@ Gated canary promotion stages:
|
||||
* scan for canary deployments
|
||||
* check Istio virtual service routes are mapped to primary and canary ClusterIP services
|
||||
* check primary and canary deployments status
|
||||
* halt rollout if a rolling update is underway
|
||||
* halt rollout if pods are unhealthy
|
||||
* halt advancement if a rolling update is underway
|
||||
* halt advancement if pods are unhealthy
|
||||
* increase canary traffic weight percentage from 0% to 5% (step weight)
|
||||
* check canary HTTP request success rate and latency
|
||||
* halt rollout if any metric is under the specified threshold
|
||||
* halt advancement if any metric is under the specified threshold
|
||||
* increment the failed checks counter
|
||||
* check if the number of failed checks reached the threshold
|
||||
* route all traffic to primary
|
||||
* scale to zero the canary deployment and mark it as failed
|
||||
* wait for the canary deployment to be updated (revision bump) and start over
|
||||
* increase canary traffic weight by 5% (step weight) till it reaches 50% (max weight)
|
||||
* halt rollout while canary request success rate is under the threshold
|
||||
* halt rollout while canary request duration P99 is over the threshold
|
||||
* halt rollout if the primary or canary deployment becomes unhealthy
|
||||
* halt rollout while canary deployment is being scaled up/down by HPA
|
||||
* halt advancement while canary request success rate is under the threshold
|
||||
* halt advancement while canary request duration P99 is over the threshold
|
||||
* halt advancement if the primary or canary deployment becomes unhealthy
|
||||
* halt advancement while canary deployment is being scaled up/down by HPA
|
||||
* promote canary to primary
|
||||
* copy canary deployment spec template over primary
|
||||
* wait for primary rolling update to finish
|
||||
* halt rollout if pods are unhealthy
|
||||
* halt advancement if pods are unhealthy
|
||||
* route all traffic to primary
|
||||
* scale to zero the canary deployment
|
||||
* mark rollout as finished
|
||||
@@ -70,76 +72,43 @@ Gated canary promotion stages:
|
||||
|
||||
You can change the canary analysis _max weight_ and the _step weight_ percentage in the Flagger's custom resource.
|
||||
|
||||
Assuming the primary deployment is named _podinfo_ and the canary one _podinfo-canary_, Flagger will require
|
||||
a virtual service configured with weight-based routing:
|
||||
For a deployment named _podinfo_, a canary promotion can be defined using Flagger's custom resource:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
hosts:
|
||||
- podinfo
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: podinfo
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
- destination:
|
||||
host: podinfo-canary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 0
|
||||
```
|
||||
|
||||
Primary and canary services should expose a port named http:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: podinfo-canary
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: podinfo-canary
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
targetPort: 9898
|
||||
```
|
||||
|
||||
Based on the two deployments, services and virtual service, a canary promotion can be defined using Flagger's custom resource:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
apiVersion: flagger.app/v1alpha1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
targetKind: Deployment
|
||||
virtualService:
|
||||
# deployment reference
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
primary:
|
||||
# hpa reference (optional)
|
||||
autoscalerRef:
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
name: podinfo
|
||||
host: podinfo
|
||||
canary:
|
||||
name: podinfo-canary
|
||||
host: podinfo-canary
|
||||
service:
|
||||
# container port
|
||||
port: 9898
|
||||
# Istio gateways (optional)
|
||||
gateways:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
# Istio virtual service host names (optional)
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
canaryAnalysis:
|
||||
# max number of failed checks
|
||||
# before rolling back the canary
|
||||
threshold: 10
|
||||
# max number of failed metric checks before rollback
|
||||
threshold: 5
|
||||
# max traffic percentage routed to canary
|
||||
# percentage (0-100)
|
||||
maxWeight: 50
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 5
|
||||
stepWeight: 10
|
||||
metrics:
|
||||
- name: istio_requests_total
|
||||
# minimum req success rate (non 5xx responses)
|
||||
@@ -150,14 +119,14 @@ spec:
|
||||
# maximum req duration P99
|
||||
# milliseconds
|
||||
threshold: 500
|
||||
interval: 1m
|
||||
interval: 30s
|
||||
```
|
||||
|
||||
The canary analysis is using the following promql queries:
|
||||
|
||||
_HTTP requests success rate percentage_
|
||||
|
||||
```promql
|
||||
```
|
||||
sum(
|
||||
rate(
|
||||
istio_requests_total{
|
||||
@@ -182,7 +151,7 @@ sum(
|
||||
|
||||
_HTTP requests milliseconds duration P99_
|
||||
|
||||
```promql
|
||||
```
|
||||
histogram_quantile(0.99,
|
||||
sum(
|
||||
irate(
|
||||
@@ -198,8 +167,6 @@ histogram_quantile(0.99,
|
||||
|
||||
### Automated canary analysis, promotions and rollbacks
|
||||
|
||||

|
||||
|
||||
Create a test namespace with Istio sidecar injection enabled:
|
||||
|
||||
```bash
|
||||
@@ -208,66 +175,72 @@ export REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
|
||||
kubectl apply -f ${REPO}/artifacts/namespaces/test.yaml
|
||||
```
|
||||
|
||||
Create the primary deployment, service and hpa:
|
||||
Create a deployment and a horizontal pod autoscaler:
|
||||
|
||||
```bash
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/primary-deployment.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/primary-service.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/primary-hpa.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/canaries/deployment.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/canaries/hpa.yaml
|
||||
```
|
||||
|
||||
Create the canary deployment, service and hpa:
|
||||
Create a canary promotion custom resource (replace the Istio gateway and the internet domain with your own):
|
||||
|
||||
```bash
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/canary-deployment.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/canary-service.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/canary-hpa.yaml
|
||||
kubectl apply -f ${REPO}/artifacts/canaries/canary.yaml
|
||||
```
|
||||
|
||||
Create a virtual service (replace the Istio gateway and the internet domain with your own):
|
||||
After a couple of seconds Flagger will create the canary objects:
|
||||
|
||||
```bash
|
||||
kubectl apply -f ${REPO}/artifacts/workloads/virtual-service.yaml
|
||||
# applied
|
||||
deployment.apps/podinfo
|
||||
horizontalpodautoscaler.autoscaling/podinfo
|
||||
canary.flagger.app/podinfo
|
||||
# generated
|
||||
deployment.apps/podinfo-primary
|
||||
horizontalpodautoscaler.autoscaling/podinfo-primary
|
||||
service/podinfo
|
||||
service/podinfo-canary
|
||||
service/podinfo-primary
|
||||
virtualservice.networking.istio.io/podinfo
|
||||
```
|
||||
|
||||
Create a canary promotion custom resource:
|
||||

|
||||
|
||||
Trigger a canary deployment by updating the container image:
|
||||
|
||||
```bash
|
||||
kubectl apply -f ${REPO}/artifacts/rollouts/podinfo.yaml
|
||||
kubectl -n test set image deployment/podinfo \
|
||||
podinfod=quay.io/stefanprodan/podinfo:1.2.1
|
||||
```
|
||||
|
||||
Canary promotion output:
|
||||
Flagger detects that the deployment revision changed and starts a new rollout:
|
||||
|
||||
```
|
||||
kubectl -n test describe canary/podinfo
|
||||
|
||||
Status:
|
||||
Canary Revision: 16271121
|
||||
Failed Checks: 6
|
||||
Canary Revision: 19871136
|
||||
Failed Checks: 0
|
||||
State: finished
|
||||
Events:
|
||||
Type Reason Age From Message
|
||||
---- ------ ---- ---- -------
|
||||
Normal Synced 3m flagger Starting canary deployment for podinfo.test
|
||||
Normal Synced 3m flagger New revision detected podinfo.test
|
||||
Normal Synced 3m flagger Scaling up podinfo.test
|
||||
Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
|
||||
Normal Synced 3m flagger Advance podinfo.test canary weight 5
|
||||
Normal Synced 3m flagger Advance podinfo.test canary weight 10
|
||||
Normal Synced 3m flagger Advance podinfo.test canary weight 15
|
||||
Warning Synced 3m flagger Halt podinfo.test advancement request duration 2.525s > 500ms
|
||||
Warning Synced 3m flagger Halt podinfo.test advancement request duration 1.567s > 500ms
|
||||
Warning Synced 3m flagger Halt podinfo.test advancement request duration 823ms > 500ms
|
||||
Normal Synced 2m flagger Advance podinfo.test canary weight 20
|
||||
Normal Synced 2m flagger Advance podinfo.test canary weight 25
|
||||
Normal Synced 1m flagger Advance podinfo.test canary weight 30
|
||||
Warning Synced 1m flagger Halt podinfo.test advancement success rate 82.33% < 99%
|
||||
Warning Synced 1m flagger Halt podinfo.test advancement success rate 87.22% < 99%
|
||||
Warning Synced 1m flagger Halt podinfo.test advancement success rate 94.74% < 99%
|
||||
Normal Synced 1m flagger Advance podinfo.test canary weight 35
|
||||
Normal Synced 55s flagger Advance podinfo.test canary weight 40
|
||||
Normal Synced 45s flagger Advance podinfo.test canary weight 45
|
||||
Normal Synced 35s flagger Advance podinfo.test canary weight 50
|
||||
Normal Synced 25s flagger Copying podinfo-canary.test template spec to podinfo.test
|
||||
Warning Synced 15s flagger Waiting for podinfo.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Normal Synced 5s flagger Promotion completed! Scaling down podinfo-canary.test
|
||||
Normal Synced 25s flagger Copying podinfo.test template spec to podinfo-primary.test
|
||||
Warning Synced 15s flagger Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Normal Synced 5s flagger Promotion completed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
During the canary analysis you can generate HTTP 500 errors and high latency to test if Flagger pauses the rollout.
|
||||
@@ -313,45 +286,8 @@ Events:
|
||||
Normal Synced 2m flagger Halt podinfo.test advancement success rate 55.06% < 99%
|
||||
Normal Synced 2m flagger Halt podinfo.test advancement success rate 47.00% < 99%
|
||||
Normal Synced 2m flagger (combined from similar events): Halt podinfo.test advancement success rate 38.08% < 99%
|
||||
Warning Synced 1m flagger Rolling back podinfo-canary.test failed checks threshold reached 10
|
||||
Warning Synced 1m flagger Canary failed! Scaling down podinfo-canary.test
|
||||
```
|
||||
|
||||
Trigger a new canary deployment by updating the canary image:
|
||||
|
||||
```bash
|
||||
kubectl -n test set image deployment/podinfo-canary \
|
||||
podinfod=quay.io/stefanprodan/podinfo:1.2.1
|
||||
```
|
||||
|
||||
Steer detects that the canary revision changed and starts a new rollout:
|
||||
|
||||
```
|
||||
kubectl -n test describe canary/podinfo
|
||||
|
||||
Status:
|
||||
Canary Revision: 19871136
|
||||
Failed Checks: 0
|
||||
State: finished
|
||||
Events:
|
||||
Type Reason Age From Message
|
||||
---- ------ ---- ---- -------
|
||||
Normal Synced 3m flagger New revision detected podinfo-canary.test old 17211012 new 17246876
|
||||
Normal Synced 3m flagger Scaling up podinfo.test
|
||||
Warning Synced 3m flagger Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
|
||||
Normal Synced 3m flagger Advance podinfo.test canary weight 5
|
||||
Normal Synced 3m flagger Advance podinfo.test canary weight 10
|
||||
Normal Synced 3m flagger Advance podinfo.test canary weight 15
|
||||
Normal Synced 2m flagger Advance podinfo.test canary weight 20
|
||||
Normal Synced 2m flagger Advance podinfo.test canary weight 25
|
||||
Normal Synced 1m flagger Advance podinfo.test canary weight 30
|
||||
Normal Synced 1m flagger Advance podinfo.test canary weight 35
|
||||
Normal Synced 55s flagger Advance podinfo.test canary weight 40
|
||||
Normal Synced 45s flagger Advance podinfo.test canary weight 45
|
||||
Normal Synced 35s flagger Advance podinfo.test canary weight 50
|
||||
Normal Synced 25s flagger Copying podinfo-canary.test template spec to podinfo.test
|
||||
Warning Synced 15s flagger Waiting for podinfo.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Normal Synced 5s flagger Promotion completed! Scaling down podinfo-canary.test
|
||||
Warning Synced 1m flagger Rolling back podinfo.test failed checks threshold reached 10
|
||||
Warning Synced 1m flagger Canary failed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
### Monitoring
|
||||
@@ -388,9 +324,31 @@ Advance podinfo.test canary weight 40
|
||||
Halt podinfo.test advancement request duration 1.515s > 500ms
|
||||
Advance podinfo.test canary weight 45
|
||||
Advance podinfo.test canary weight 50
|
||||
Copying podinfo-canary.test template spec to podinfo-primary.test
|
||||
Scaling down podinfo-canary.test
|
||||
Promotion completed! podinfo-canary.test revision 81289
|
||||
Copying podinfo.test template spec to podinfo-primary.test
|
||||
Halt podinfo-primary.test advancement waiting for rollout to finish: 1 old replicas are pending termination
|
||||
Scaling down podinfo.test
|
||||
Promotion completed! podinfo.test
|
||||
```
|
||||
|
||||
Flagger exposes Prometheus metrics that can be used to determine the canary analysis status and the destination weight values:
|
||||
|
||||
```bash
|
||||
# Canaries total gauge
|
||||
flagger_canary_total{namespace="test"} 1
|
||||
|
||||
# Canary promotion last known status gauge
|
||||
# 0 - running, 1 - successful, 2 - failed
|
||||
flagger_canary_status{name="podinfo" namespace="test"} 1
|
||||
|
||||
# Canary traffic weight gauge
|
||||
flagger_canary_weight{workload="podinfo-primary" namespace="test"} 95
|
||||
flagger_canary_weight{workload="podinfo" namespace="test"} 5
|
||||
|
||||
# Seconds spent performing canary analysis histogram
|
||||
flagger_canary_duration_seconds_bucket{name="podinfo",namespace="test",le="10"} 6
|
||||
flagger_canary_duration_seconds_bucket{name="podinfo",namespace="test",le="+Inf"} 6
|
||||
flagger_canary_duration_seconds_sum{name="podinfo",namespace="test"} 17.3561329
|
||||
flagger_canary_duration_seconds_count{name="podinfo",namespace="test"} 6
|
||||
```
|
||||
|
||||
### Roadmap
|
||||
@@ -398,7 +356,7 @@ Promotion completed! podinfo-canary.test revision 81289
|
||||
* Extend the canary analysis and promotion to other types than Kubernetes deployments such as Flux Helm releases or OpenFaaS functions
|
||||
* Extend the validation mechanism to support other metrics than HTTP success rate and latency
|
||||
* Add support for comparing the canary metrics to the primary ones and do the validation based on the derivation between the two
|
||||
* Alerting: Trigger Alertmanager on successful or failed promotions (Prometheus instrumentation of the canary analysis)
|
||||
* Alerting: trigger Alertmanager on successful or failed promotions
|
||||
* Reporting: publish canary analysis results to Slack/Jira/etc
|
||||
|
||||
### Contributing
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
docs/grafana-0.1.0.tgz
Normal file
BIN
docs/grafana-0.1.0.tgz
Normal file
Binary file not shown.
Binary file not shown.
@@ -2,72 +2,27 @@ apiVersion: v1
|
||||
entries:
|
||||
flagger:
|
||||
- apiVersion: v1
|
||||
appVersion: 0.1.0-alpha.1
|
||||
created: 2018-10-11T11:16:00.30124+03:00
|
||||
appVersion: 0.1.0-beta.6
|
||||
created: 2018-10-29T21:46:00.29473+02:00
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of
|
||||
canary deployments using Istio routing for traffic shifting and Prometheus metrics
|
||||
for canary analysis.
|
||||
digest: 3368bc9efbabe6043f399db46884f8a18319756b028ebe007ca69f9e81b72b3b
|
||||
digest: c17380b0f4e08a9b1f76a0e52d53677248c5756eff6a1fcd5629d3465dd1ad58
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
name: flagger
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/flagger-0.1.0.tgz
|
||||
version: 0.1.0
|
||||
- apiVersion: v1
|
||||
appVersion: 0.0.1
|
||||
created: 2018-10-11T11:16:00.300274+03:00
|
||||
description: Flagger is a Kubernetes operator that automates the promotion of
|
||||
canary deployments using Istio routing for traffic shifting and Prometheus metrics
|
||||
for canary analysis.
|
||||
digest: b6fe3d84b5981e667e0cfed6146a04474192553111a2d11157dc6b705ec8e14c
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
name: flagger
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/flagger-0.0.1.tgz
|
||||
version: 0.0.1
|
||||
grafana:
|
||||
- apiVersion: v1
|
||||
appVersion: 5.2.0
|
||||
created: 2018-10-11T11:16:00.302086+03:00
|
||||
description: A Helm chart for monitoring progressive deployments powered by Istio
|
||||
and Flagger
|
||||
digest: 109afd61ac5aaa212f18bfad4a1ad38425458f9d0a492547c5522d3898836faf
|
||||
appVersion: 5.3.1
|
||||
created: 2018-10-29T21:46:00.295247+02:00
|
||||
description: A Grafana Helm chart for monitoring progressive deployments powered
|
||||
by Istio and Flagger
|
||||
digest: 370aa2e6a0d4ab717f047658bdb02969b8f2a4d2e81c0bc96b90e3365229715f
|
||||
home: https://github.com/stefanprodan/flagger
|
||||
name: grafana
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/grafana-5.2.4.tgz
|
||||
version: 5.2.4
|
||||
podinfo-flagger:
|
||||
- apiVersion: v1
|
||||
appVersion: 1.2.1
|
||||
created: 2018-10-11T11:16:00.302902+03:00
|
||||
description: Podinfo Helm chart for Flagger progressive delivery
|
||||
digest: 72d95f4f4ec1eea85ffc2a7cbb9b5f95bb56ea9d934ba24c5dde078d4f9c7605
|
||||
engine: gotpl
|
||||
home: https://github.com/stefanprodan/k8s-podinfo
|
||||
maintainers:
|
||||
- email: stefanprodan@users.noreply.github.com
|
||||
name: stefanprodan
|
||||
name: podinfo-flagger
|
||||
sources:
|
||||
- https://github.com/stefanprodan/flagger
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/podinfo-flagger-2.0.0.tgz
|
||||
version: 2.0.0
|
||||
- apiVersion: v1
|
||||
appVersion: 1.2.1
|
||||
created: 2018-10-04T14:48:57.586403+03:00
|
||||
description: Podinfo Helm chart for Flagger progressive delivery
|
||||
digest: f559f387aa45005be085af207b8b4c91776e489fcb6ca7e60f20913ecd21184e
|
||||
engine: gotpl
|
||||
home: https://github.com/stefanprodan/k8s-podinfo
|
||||
maintainers:
|
||||
- email: stefanprodan@users.noreply.github.com
|
||||
name: stefanprodan
|
||||
name: podinfo-flagger
|
||||
sources:
|
||||
- https://github.com/stefanprodan/flagger
|
||||
urls:
|
||||
- https://stefanprodan.github.io/flagger/podinfo-flagger-1.2.1.tgz
|
||||
version: 1.2.1
|
||||
generated: 2018-10-11T11:16:00.298073+03:00
|
||||
- https://stefanprodan.github.io/flagger/grafana-0.1.0.tgz
|
||||
version: 0.1.0
|
||||
generated: 2018-10-29T21:46:00.293821+02:00
|
||||
|
||||
Binary file not shown.
@@ -67,12 +67,15 @@ type CanaryStatus struct {
|
||||
FailedChecks int `json:"failedChecks"`
|
||||
}
|
||||
|
||||
// CanaryService is used to create ClusterIP services
|
||||
// and Istio Virtual Service
|
||||
type CanaryService struct {
|
||||
Port int32 `json:"port"`
|
||||
Gateways []string `json:"gateways"`
|
||||
Hosts []string `json:"hosts"`
|
||||
}
|
||||
|
||||
// CanaryAnalysis is used to describe how the analysis should be done
|
||||
type CanaryAnalysis struct {
|
||||
Threshold int `json:"threshold"`
|
||||
MaxWeight int `json:"maxWeight"`
|
||||
@@ -80,6 +83,7 @@ type CanaryAnalysis struct {
|
||||
Metrics []CanaryMetric `json:"metrics"`
|
||||
}
|
||||
|
||||
// CanaryMetric hold the reference to Istio metrics used for canary analysis
|
||||
type CanaryMetric struct {
|
||||
Name string `json:"name"`
|
||||
Interval string `json:"interval"`
|
||||
|
||||
@@ -27,26 +27,30 @@ import (
|
||||
|
||||
const controllerAgentName = "flagger"
|
||||
|
||||
// Controller is managing the canary objects and schedules canary deployments
|
||||
type Controller struct {
|
||||
kubeClient kubernetes.Interface
|
||||
istioClient istioclientset.Interface
|
||||
rolloutClient clientset.Interface
|
||||
rolloutLister flaggerlisters.CanaryLister
|
||||
rolloutSynced cache.InformerSynced
|
||||
rolloutWindow time.Duration
|
||||
flaggerClient clientset.Interface
|
||||
flaggerLister flaggerlisters.CanaryLister
|
||||
flaggerSynced cache.InformerSynced
|
||||
flaggerWindow time.Duration
|
||||
workqueue workqueue.RateLimitingInterface
|
||||
recorder record.EventRecorder
|
||||
eventRecorder record.EventRecorder
|
||||
logger *zap.SugaredLogger
|
||||
metricsServer string
|
||||
rollouts *sync.Map
|
||||
canaries *sync.Map
|
||||
deployer CanaryDeployer
|
||||
router CanaryRouter
|
||||
observer CanaryObserver
|
||||
recorder CanaryRecorder
|
||||
}
|
||||
|
||||
func NewController(
|
||||
kubeClient kubernetes.Interface,
|
||||
istioClient istioclientset.Interface,
|
||||
rolloutClient clientset.Interface,
|
||||
rolloutInformer flaggerinformers.CanaryInformer,
|
||||
rolloutWindow time.Duration,
|
||||
flaggerClient clientset.Interface,
|
||||
flaggerInformer flaggerinformers.CanaryInformer,
|
||||
flaggerWindow time.Duration,
|
||||
metricServer string,
|
||||
logger *zap.SugaredLogger,
|
||||
|
||||
@@ -58,24 +62,47 @@ func NewController(
|
||||
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{
|
||||
Interface: kubeClient.CoreV1().Events(""),
|
||||
})
|
||||
recorder := eventBroadcaster.NewRecorder(
|
||||
eventRecorder := eventBroadcaster.NewRecorder(
|
||||
scheme.Scheme, corev1.EventSource{Component: controllerAgentName})
|
||||
|
||||
deployer := CanaryDeployer{
|
||||
logger: logger,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
flaggerClient: flaggerClient,
|
||||
}
|
||||
|
||||
router := CanaryRouter{
|
||||
logger: logger,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
flaggerClient: flaggerClient,
|
||||
}
|
||||
|
||||
observer := CanaryObserver{
|
||||
metricsServer: metricServer,
|
||||
}
|
||||
|
||||
recorder := NewCanaryRecorder(true)
|
||||
|
||||
ctrl := &Controller{
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
rolloutClient: rolloutClient,
|
||||
rolloutLister: rolloutInformer.Lister(),
|
||||
rolloutSynced: rolloutInformer.Informer().HasSynced,
|
||||
flaggerClient: flaggerClient,
|
||||
flaggerLister: flaggerInformer.Lister(),
|
||||
flaggerSynced: flaggerInformer.Informer().HasSynced,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), controllerAgentName),
|
||||
recorder: recorder,
|
||||
eventRecorder: eventRecorder,
|
||||
logger: logger,
|
||||
rollouts: new(sync.Map),
|
||||
metricsServer: metricServer,
|
||||
rolloutWindow: rolloutWindow,
|
||||
canaries: new(sync.Map),
|
||||
flaggerWindow: flaggerWindow,
|
||||
deployer: deployer,
|
||||
router: router,
|
||||
observer: observer,
|
||||
recorder: recorder,
|
||||
}
|
||||
|
||||
rolloutInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
flaggerInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: ctrl.enqueue,
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
oldRoll, ok := checkCustomResourceType(old, logger)
|
||||
@@ -96,7 +123,7 @@ func NewController(
|
||||
r, ok := checkCustomResourceType(old, logger)
|
||||
if ok {
|
||||
ctrl.logger.Infof("Deleting %s.%s from cache", r.Name, r.Namespace)
|
||||
ctrl.rollouts.Delete(fmt.Sprintf("%s.%s", r.Name, r.Namespace))
|
||||
ctrl.canaries.Delete(fmt.Sprintf("%s.%s", r.Name, r.Namespace))
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -104,6 +131,7 @@ func NewController(
|
||||
return ctrl
|
||||
}
|
||||
|
||||
// Run starts the K8s workers and the canary scheduler
|
||||
func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
@@ -119,18 +147,16 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
||||
|
||||
c.logger.Info("Started operator workers")
|
||||
|
||||
tickChan := time.NewTicker(c.rolloutWindow).C
|
||||
tickChan := time.NewTicker(c.flaggerWindow).C
|
||||
for {
|
||||
select {
|
||||
case <-tickChan:
|
||||
c.doRollouts()
|
||||
c.scheduleCanaries()
|
||||
case <-stopCh:
|
||||
c.logger.Info("Shutting down operator workers")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) processNextWorkItem() bool {
|
||||
@@ -174,21 +200,21 @@ func (c *Controller) syncHandler(key string) error {
|
||||
utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
|
||||
return nil
|
||||
}
|
||||
cd, err := c.rolloutLister.Canaries(namespace).Get(name)
|
||||
cd, err := c.flaggerLister.Canaries(namespace).Get(name)
|
||||
if errors.IsNotFound(err) {
|
||||
utilruntime.HandleError(fmt.Errorf("'%s' in work queue no longer exists", key))
|
||||
return nil
|
||||
}
|
||||
|
||||
c.rollouts.Store(fmt.Sprintf("%s.%s", cd.Name, cd.Namespace), cd)
|
||||
c.canaries.Store(fmt.Sprintf("%s.%s", cd.Name, cd.Namespace), cd)
|
||||
|
||||
if cd.Spec.TargetRef.Kind == "Deployment" {
|
||||
err = c.bootstrapDeployment(cd)
|
||||
if err != nil {
|
||||
c.logger.Warnf("%s.%s bootstrap error %v", cd.Name, cd.Namespace, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
//if cd.Spec.TargetRef.Kind == "Deployment" {
|
||||
// err = c.bootstrapDeployment(cd)
|
||||
// if err != nil {
|
||||
// c.logger.Warnf("%s.%s bootstrap error %v", cd.Name, cd.Namespace, err)
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
|
||||
c.logger.Infof("Synced %s", key)
|
||||
|
||||
@@ -217,15 +243,19 @@ func checkCustomResourceType(obj interface{}, logger *zap.SugaredLogger) (flagge
|
||||
|
||||
func (c *Controller) recordEventInfof(r *flaggerv1.Canary, template string, args ...interface{}) {
|
||||
c.logger.Infof(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeNormal, "Synced", fmt.Sprintf(template, args...))
|
||||
c.eventRecorder.Event(r, corev1.EventTypeNormal, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func (c *Controller) recordEventErrorf(r *flaggerv1.Canary, template string, args ...interface{}) {
|
||||
c.logger.Errorf(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
c.eventRecorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func (c *Controller) recordEventWarningf(r *flaggerv1.Canary, template string, args ...interface{}) {
|
||||
c.logger.Infof(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
c.eventRecorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func int32p(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
@@ -1,32 +1,225 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
istioclientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
"go.uber.org/zap"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
hpav1 "k8s.io/api/autoscaling/v2beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
func (c *Controller) bootstrapDeployment(cd *flaggerv1.Canary) error {
|
||||
// CanaryDeployer is managing the operations for Kubernetes deployment kind
|
||||
type CanaryDeployer struct {
|
||||
kubeClient kubernetes.Interface
|
||||
istioClient istioclientset.Interface
|
||||
flaggerClient clientset.Interface
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
// Promote copies the pod spec from canary to primary
|
||||
func (c *CanaryDeployer) Promote(cd *flaggerv1.Canary) error {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(cd.Spec.TargetRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
}
|
||||
return fmt.Errorf("deployment %s.%s query error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
primary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(primaryName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found", primaryName, cd.Namespace)
|
||||
}
|
||||
return fmt.Errorf("deployment %s.%s query error %v", primaryName, cd.Namespace, err)
|
||||
}
|
||||
|
||||
primary.Spec.Template.Spec = canary.Spec.Template.Spec
|
||||
_, err = c.kubeClient.AppsV1().Deployments(primary.Namespace).Update(primary)
|
||||
if err != nil {
|
||||
return fmt.Errorf("updating template spec %s.%s failed: %v", primary.GetName(), primary.Namespace, err)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsReady checks the primary and canary deployment status and returns an error if
|
||||
// the deployments are in the middle of a rolling update or if the pods are unhealthy
|
||||
func (c *CanaryDeployer) IsReady(cd *flaggerv1.Canary) error {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(cd.Spec.TargetRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
}
|
||||
return fmt.Errorf("deployment %s.%s query error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
if msg, healthy := c.getDeploymentStatus(canary); !healthy {
|
||||
return fmt.Errorf("Halt %s.%s advancement %s", cd.Name, cd.Namespace, msg)
|
||||
}
|
||||
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
primary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(primaryName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found", primaryName, cd.Namespace)
|
||||
}
|
||||
return fmt.Errorf("deployment %s.%s query error %v", primaryName, cd.Namespace, err)
|
||||
}
|
||||
if msg, healthy := c.getDeploymentStatus(primary); !healthy {
|
||||
return fmt.Errorf("Halt %s.%s advancement %s", cd.Name, cd.Namespace, msg)
|
||||
}
|
||||
|
||||
if primary.Spec.Replicas == int32p(0) {
|
||||
return fmt.Errorf("halt %s.%s advancement %s",
|
||||
cd.Name, cd.Namespace, "primary deployment is scaled to zero")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsNewSpec returns true if the canary deployment pod spec has changed
|
||||
func (c *CanaryDeployer) IsNewSpec(cd *flaggerv1.Canary) (bool, error) {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(cd.Spec.TargetRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return false, fmt.Errorf("deployment %s.%s not found", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
}
|
||||
return false, fmt.Errorf("deployment %s.%s query error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
|
||||
if cd.Status.CanaryRevision == "" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
newSpec := &canary.Spec.Template.Spec
|
||||
oldSpecJson, err := base64.StdEncoding.DecodeString(cd.Status.CanaryRevision)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
oldSpec := &corev1.PodSpec{}
|
||||
err = json.Unmarshal(oldSpecJson, oldSpec)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("%s.%s unmarshal error %v", cd.Name, cd.Namespace, err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(*newSpec, *oldSpec, cmpopts.IgnoreUnexported(resource.Quantity{})); diff != "" {
|
||||
//fmt.Println(diff)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// SetFailedChecks updates the canary failed checks counter
|
||||
func (c *CanaryDeployer) SetFailedChecks(cd *flaggerv1.Canary, val int) error {
|
||||
cd.Status.FailedChecks = val
|
||||
cd, err := c.flaggerClient.FlaggerV1alpha1().Canaries(cd.Namespace).Update(cd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("deployment %s.%s update error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetState updates the canary status state
|
||||
func (c *CanaryDeployer) SetState(cd *flaggerv1.Canary, state string) error {
|
||||
cd.Status.State = state
|
||||
cd, err := c.flaggerClient.FlaggerV1alpha1().Canaries(cd.Namespace).Update(cd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("deployment %s.%s update error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncStatus encodes the canary pod spec and updates the canary status
|
||||
func (c *CanaryDeployer) SyncStatus(cd *flaggerv1.Canary, status flaggerv1.CanaryStatus) error {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(cd.Spec.TargetRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
}
|
||||
return fmt.Errorf("deployment %s.%s query error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
|
||||
specJson, err := json.Marshal(canary.Spec.Template.Spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("deployment %s.%s marshal error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
|
||||
specEnc := base64.StdEncoding.EncodeToString(specJson)
|
||||
cd.Status.State = status.State
|
||||
cd.Status.FailedChecks = status.FailedChecks
|
||||
cd.Status.CanaryRevision = specEnc
|
||||
cd, err = c.flaggerClient.FlaggerV1alpha1().Canaries(cd.Namespace).Update(cd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("deployment %s.%s update error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scale sets the canary deployment replicas
|
||||
func (c *CanaryDeployer) Scale(cd *flaggerv1.Canary, replicas int32) error {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(cd.Spec.TargetRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
}
|
||||
return fmt.Errorf("deployment %s.%s query error %v", cd.Spec.TargetRef.Name, cd.Namespace, err)
|
||||
}
|
||||
canary.Spec.Replicas = int32p(replicas)
|
||||
canary, err = c.kubeClient.AppsV1().Deployments(canary.Namespace).Update(canary)
|
||||
if err != nil {
|
||||
return fmt.Errorf("scaling %s.%s to %v failed: %v", canary.GetName(), canary.Namespace, replicas, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sync creates the primary deployment and hpa
|
||||
// and scales to zero the canary deployment
|
||||
func (c *CanaryDeployer) Sync(cd *flaggerv1.Canary) error {
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
if err := c.createPrimaryDeployment(cd); err != nil {
|
||||
return fmt.Errorf("creating deployment %s.%s failed: %v", primaryName, cd.Namespace, err)
|
||||
}
|
||||
|
||||
if cd.Status.State == "" {
|
||||
c.logger.Infof("Scaling down %s.%s", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
if err := c.Scale(cd, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if cd.Spec.AutoscalerRef.Kind == "HorizontalPodAutoscaler" {
|
||||
if err := c.createPrimaryHpa(cd); err != nil {
|
||||
return fmt.Errorf("creating hpa %s.%s failed: %v", primaryName, cd.Namespace, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CanaryDeployer) createPrimaryDeployment(cd *flaggerv1.Canary) error {
|
||||
canaryName := cd.Spec.TargetRef.Name
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
|
||||
canaryDep, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(canaryName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("deployment %s.%s not found, retrying in %v",
|
||||
canaryName, cd.Namespace, c.rolloutWindow)
|
||||
} else {
|
||||
return err
|
||||
return fmt.Errorf("deployment %s.%s not found, retrying", canaryName, cd.Namespace)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
primaryDep, err := c.kubeClient.AppsV1().Deployments(cd.Namespace).Get(primaryName, metav1.GetOptions{})
|
||||
@@ -67,225 +260,90 @@ func (c *Controller) bootstrapDeployment(cd *flaggerv1.Canary) error {
|
||||
return err
|
||||
}
|
||||
|
||||
c.recordEventInfof(cd, "Deployment %s.%s created", primaryDep.GetName(), cd.Namespace)
|
||||
c.logger.Infof("Deployment %s.%s created", primaryDep.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
if cd.Status.State == "" {
|
||||
c.scaleToZeroCanary(cd)
|
||||
}
|
||||
|
||||
canaryService, err := c.kubeClient.CoreV1().Services(cd.Namespace).Get(canaryName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
canaryService = &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: canaryName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Selector: map[string]string{"app": canaryName},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
Port: cd.Spec.Service.Port,
|
||||
TargetPort: intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
IntVal: cd.Spec.Service.Port,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.CoreV1().Services(cd.Namespace).Create(canaryService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.recordEventInfof(cd, "Service %s.%s created", canaryService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
canaryTestServiceName := fmt.Sprintf("%s-canary", cd.Spec.TargetRef.Name)
|
||||
canaryTestService, err := c.kubeClient.CoreV1().Services(cd.Namespace).Get(canaryTestServiceName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
canaryTestService = &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: canaryTestServiceName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Selector: map[string]string{"app": canaryName},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
Port: cd.Spec.Service.Port,
|
||||
TargetPort: intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
IntVal: cd.Spec.Service.Port,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.CoreV1().Services(cd.Namespace).Create(canaryTestService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.recordEventInfof(cd, "Service %s.%s created", canaryTestService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
primaryService, err := c.kubeClient.CoreV1().Services(cd.Namespace).Get(primaryName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
primaryService = &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: primaryName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Selector: map[string]string{"app": primaryName},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
Port: cd.Spec.Service.Port,
|
||||
TargetPort: intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
IntVal: cd.Spec.Service.Port,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.CoreV1().Services(cd.Namespace).Create(primaryService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.recordEventInfof(cd, "Service %s.%s created", primaryService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
hosts := append(cd.Spec.Service.Hosts, canaryName)
|
||||
gateways := append(cd.Spec.Service.Gateways, "mesh")
|
||||
virtualService, err := c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Get(canaryName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
virtualService = &istiov1alpha3.VirtualService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: canaryName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: istiov1alpha3.VirtualServiceSpec{
|
||||
Hosts: hosts,
|
||||
Gateways: gateways,
|
||||
Http: []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Route: []istiov1alpha3.DestinationWeight{
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: primaryName,
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(cd.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: canaryName,
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(cd.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Create(virtualService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.recordEventInfof(cd, "VirtualService %s.%s created", virtualService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
if cd.Spec.AutoscalerRef.Kind == "HorizontalPodAutoscaler" {
|
||||
hpa, err := c.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(cd.Namespace).Get(cd.Spec.AutoscalerRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("HorizontalPodAutoscaler %s.%s not found, retrying in %v",
|
||||
cd.Spec.AutoscalerRef.Name, cd.Namespace, c.rolloutWindow)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
primaryHpaName := fmt.Sprintf("%s-primary", cd.Spec.AutoscalerRef.Name)
|
||||
primaryHpa, err := c.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(cd.Namespace).Get(primaryHpaName, metav1.GetOptions{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CanaryDeployer) createPrimaryHpa(cd *flaggerv1.Canary) error {
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
hpa, err := c.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(cd.Namespace).Get(cd.Spec.AutoscalerRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
primaryHpa = &hpav1.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: primaryHpaName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: hpav1.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: hpav1.CrossVersionObjectReference{
|
||||
Name: primaryName,
|
||||
Kind: hpa.Spec.ScaleTargetRef.Kind,
|
||||
APIVersion: hpa.Spec.ScaleTargetRef.APIVersion,
|
||||
},
|
||||
MinReplicas: hpa.Spec.MinReplicas,
|
||||
MaxReplicas: hpa.Spec.MaxReplicas,
|
||||
Metrics: hpa.Spec.Metrics,
|
||||
},
|
||||
}
|
||||
return fmt.Errorf("HorizontalPodAutoscaler %s.%s not found, retrying",
|
||||
cd.Spec.AutoscalerRef.Name, cd.Namespace)
|
||||
}
|
||||
return err
|
||||
}
|
||||
primaryHpaName := fmt.Sprintf("%s-primary", cd.Spec.AutoscalerRef.Name)
|
||||
primaryHpa, err := c.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(cd.Namespace).Get(primaryHpaName, metav1.GetOptions{})
|
||||
|
||||
_, err = c.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(cd.Namespace).Create(primaryHpa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.recordEventInfof(cd, "HorizontalPodAutoscaler %s.%s created", primaryHpa.GetName(), cd.Namespace)
|
||||
if errors.IsNotFound(err) {
|
||||
primaryHpa = &hpav1.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: primaryHpaName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: hpav1.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: hpav1.CrossVersionObjectReference{
|
||||
Name: primaryName,
|
||||
Kind: hpa.Spec.ScaleTargetRef.Kind,
|
||||
APIVersion: hpa.Spec.ScaleTargetRef.APIVersion,
|
||||
},
|
||||
MinReplicas: hpa.Spec.MinReplicas,
|
||||
MaxReplicas: hpa.Spec.MaxReplicas,
|
||||
Metrics: hpa.Spec.Metrics,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers(cd.Namespace).Create(primaryHpa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.logger.Infof("HorizontalPodAutoscaler %s.%s created", primaryHpa.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CanaryDeployer) getDeploymentStatus(deployment *appsv1.Deployment) (string, bool) {
|
||||
if deployment.Generation <= deployment.Status.ObservedGeneration {
|
||||
cond := c.getDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)
|
||||
if cond != nil && cond.Reason == "ProgressDeadlineExceeded" {
|
||||
return fmt.Sprintf("deployment %q exceeded its progress deadline", deployment.GetName()), false
|
||||
} else if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d out of %d new replicas have been updated",
|
||||
deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false
|
||||
} else if deployment.Status.Replicas > deployment.Status.UpdatedReplicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d old replicas are pending termination",
|
||||
deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false
|
||||
} else if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d of %d updated replicas are available",
|
||||
deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false
|
||||
}
|
||||
} else {
|
||||
return "waiting for rollout to finish: observed deployment generation less then desired generation", false
|
||||
}
|
||||
|
||||
return "ready", true
|
||||
}
|
||||
|
||||
func (c *CanaryDeployer) getDeploymentCondition(
|
||||
status appsv1.DeploymentStatus,
|
||||
conditionType appsv1.DeploymentConditionType,
|
||||
) *appsv1.DeploymentCondition {
|
||||
for i := range status.Conditions {
|
||||
c := status.Conditions[i]
|
||||
if c.Type == conditionType {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
476
pkg/controller/deployer_test.go
Normal file
476
pkg/controller/deployer_test.go
Normal file
@@ -0,0 +1,476 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
fakeFlagger "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/fake"
|
||||
"github.com/stefanprodan/flagger/pkg/logging"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
hpav1 "k8s.io/api/autoscaling/v1"
|
||||
hpav2 "k8s.io/api/autoscaling/v2beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func newTestCanary() *v1alpha1.Canary {
|
||||
cd := &v1alpha1.Canary{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: v1alpha1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: v1alpha1.CanarySpec{
|
||||
TargetRef: hpav1.CrossVersionObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
AutoscalerRef: hpav1.CrossVersionObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "autoscaling/v2beta1",
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
}, Service: v1alpha1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: v1alpha1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
Metrics: []v1alpha1.CanaryMetric{
|
||||
{
|
||||
Name: "istio_requests_total",
|
||||
Threshold: 99,
|
||||
Interval: "1m",
|
||||
},
|
||||
{
|
||||
Name: "istio_request_duration_seconds_bucket",
|
||||
Threshold: 500,
|
||||
Interval: "1m",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return cd
|
||||
}
|
||||
|
||||
func newTestDeployment() *appsv1.Deployment {
|
||||
d := &appsv1.Deployment{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "podinfo",
|
||||
Image: "quay.io/stefanprodan/podinfo:1.2.0",
|
||||
Ports: []corev1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: 9898,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"./podinfo",
|
||||
"--port=9898",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newTestDeploymentUpdated() *appsv1.Deployment {
|
||||
d := &appsv1.Deployment{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "podinfo",
|
||||
Image: "quay.io/stefanprodan/podinfo:1.2.1",
|
||||
Ports: []corev1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: 9898,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"./podinfo",
|
||||
"--port=9898",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newTestHPA() *hpav2.HorizontalPodAutoscaler {
|
||||
h := &hpav2.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: hpav2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: hpav2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: hpav2.CrossVersionObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Metrics: []hpav2.MetricSpec{
|
||||
{
|
||||
Type: "Resource",
|
||||
Resource: &hpav2.ResourceMetricSource{
|
||||
Name: "cpu",
|
||||
TargetAverageUtilization: int32p(99),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_Sync(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
depPrimary, err := kubeClient.AppsV1().Deployments("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
primaryImage := depPrimary.Spec.Template.Spec.Containers[0].Image
|
||||
sourceImage := dep.Spec.Template.Spec.Containers[0].Image
|
||||
if primaryImage != sourceImage {
|
||||
t.Errorf("Got image %s wanted %s", primaryImage, sourceImage)
|
||||
}
|
||||
|
||||
hpaPrimary, err := kubeClient.AutoscalingV2beta1().HorizontalPodAutoscalers("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if hpaPrimary.Spec.ScaleTargetRef.Name != depPrimary.Name {
|
||||
t.Errorf("Got HPA target %s wanted %s", hpaPrimary.Spec.ScaleTargetRef.Name, depPrimary.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_IsNewSpec(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
dep2 := newTestDeploymentUpdated()
|
||||
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
_, err = kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
isNew, err := deployer.IsNewSpec(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if !isNew {
|
||||
t.Errorf("Got %v wanted %v", isNew, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_Promote(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
dep2 := newTestDeploymentUpdated()
|
||||
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
_, err = kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
err = deployer.Promote(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
depPrimary, err := kubeClient.AppsV1().Deployments("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
primaryImage := depPrimary.Spec.Template.Spec.Containers[0].Image
|
||||
sourceImage := dep2.Spec.Template.Spec.Containers[0].Image
|
||||
if primaryImage != sourceImage {
|
||||
t.Errorf("Got image %s wanted %s", primaryImage, sourceImage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_IsReady(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
err = deployer.IsReady(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_SetFailedChecks(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
err = deployer.SetFailedChecks(canary, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
res, err := flaggerClient.FlaggerV1alpha1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if res.Status.FailedChecks != 1 {
|
||||
t.Errorf("Got %v wanted %v", res.Status.FailedChecks, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_SetState(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
err = deployer.SetState(canary, "running")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
res, err := flaggerClient.FlaggerV1alpha1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if res.Status.State != "running" {
|
||||
t.Errorf("Got %v wanted %v", res.Status.State, "running")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_SyncStatus(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
status := v1alpha1.CanaryStatus{
|
||||
State: "running",
|
||||
FailedChecks: 2,
|
||||
}
|
||||
err = deployer.SyncStatus(canary, status)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
res, err := flaggerClient.FlaggerV1alpha1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if res.Status.State != status.State {
|
||||
t.Errorf("Got state %v wanted %v", res.Status.State, status.State)
|
||||
}
|
||||
|
||||
if res.Status.FailedChecks != status.FailedChecks {
|
||||
t.Errorf("Got failed checks %v wanted %v", res.Status.FailedChecks, status.FailedChecks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_Scale(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := &CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := deployer.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
err = deployer.Scale(canary, 2)
|
||||
|
||||
c, err := kubeClient.AppsV1().Deployments("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if *c.Spec.Replicas != 2 {
|
||||
t.Errorf("Got replicas %v wanted %v", *c.Spec.Replicas, 2)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (c *Controller) doRollouts() {
|
||||
c.rollouts.Range(func(key interface{}, value interface{}) bool {
|
||||
r := value.(*flaggerv1.Canary)
|
||||
if r.Spec.TargetRef.Kind == "Deployment" {
|
||||
go c.advanceDeploymentRollout(r.Name, r.Namespace)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Controller) advanceDeploymentRollout(name string, namespace string) {
|
||||
// gate stage: check if the rollout exists
|
||||
r, ok := c.getRollout(name, namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := c.bootstrapDeployment(r)
|
||||
if err != nil {
|
||||
c.recordEventWarningf(r, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// set max weight default value to 100%
|
||||
maxWeight := 100
|
||||
if r.Spec.CanaryAnalysis.MaxWeight > 0 {
|
||||
maxWeight = r.Spec.CanaryAnalysis.MaxWeight
|
||||
}
|
||||
|
||||
// gate stage: check if canary deployment exists and is healthy
|
||||
canary, ok := c.getCanaryDeployment(r, r.Spec.TargetRef.Name, r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if primary deployment exists and is healthy
|
||||
primary, ok := c.getDeployment(r, fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name), r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if virtual service exists
|
||||
// and if it contains weighted destination routes to the primary and canary services
|
||||
vs, primaryRoute, canaryRoute, ok := c.getVirtualService(r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if rollout should start (canary revision has changes) or continue
|
||||
if ok := c.checkRolloutStatus(r, canary); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if the number of failed checks reached the threshold
|
||||
if r.Status.State == "running" && r.Status.FailedChecks >= r.Spec.CanaryAnalysis.Threshold {
|
||||
c.recordEventWarningf(r, "Rolling back %s.%s failed checks threshold reached %v",
|
||||
r.Name, r.Namespace, r.Status.FailedChecks)
|
||||
|
||||
// route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
canaryRoute.Weight = 0
|
||||
if ok := c.updateVirtualServiceRoutes(r, vs, primaryRoute, canaryRoute); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.recordEventWarningf(r, "Canary failed! Scaling down %s.%s",
|
||||
canary.GetName(), canary.Namespace)
|
||||
|
||||
// shutdown canary
|
||||
c.scaleToZeroCanary(r)
|
||||
|
||||
// mark rollout as failed
|
||||
c.updateRolloutStatus(r, "promotion-failed")
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if the canary success rate is above the threshold
|
||||
// skip check if no traffic is routed to canary
|
||||
if canaryRoute.Weight == 0 {
|
||||
c.recordEventInfof(r, "Starting canary deployment for %s.%s", r.Name, r.Namespace)
|
||||
} else {
|
||||
if ok := c.checkDeploymentMetrics(r); !ok {
|
||||
c.updateRolloutFailedChecks(r, r.Status.FailedChecks+1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// routing stage: increase canary traffic percentage
|
||||
if canaryRoute.Weight < maxWeight {
|
||||
primaryRoute.Weight -= r.Spec.CanaryAnalysis.StepWeight
|
||||
if primaryRoute.Weight < 0 {
|
||||
primaryRoute.Weight = 0
|
||||
}
|
||||
canaryRoute.Weight += r.Spec.CanaryAnalysis.StepWeight
|
||||
if primaryRoute.Weight > 100 {
|
||||
primaryRoute.Weight = 100
|
||||
}
|
||||
|
||||
if ok := c.updateVirtualServiceRoutes(r, vs, primaryRoute, canaryRoute); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.recordEventInfof(r, "Advance %s.%s canary weight %v", r.Name, r.Namespace, canaryRoute.Weight)
|
||||
|
||||
// promotion stage: override primary.template.spec with the canary spec
|
||||
if canaryRoute.Weight == maxWeight {
|
||||
c.recordEventInfof(r, "Copying %s.%s template spec to %s.%s",
|
||||
canary.GetName(), canary.Namespace, primary.GetName(), primary.Namespace)
|
||||
|
||||
primary.Spec.Template.Spec = canary.Spec.Template.Spec
|
||||
_, err := c.kubeClient.AppsV1().Deployments(primary.Namespace).Update(primary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Updating template spec %s.%s failed: %v", primary.GetName(), primary.Namespace, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// final stage: route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
canaryRoute.Weight = 0
|
||||
if ok := c.updateVirtualServiceRoutes(r, vs, primaryRoute, canaryRoute); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// final stage: mark rollout as finished and scale canary to zero replicas
|
||||
c.recordEventInfof(r, "Scaling down %s.%s", canary.GetName(), canary.Namespace)
|
||||
c.scaleToZeroCanary(r)
|
||||
c.updateRolloutStatus(r, "promotion-finished")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getRollout(name string, namespace string) (*flaggerv1.Canary, bool) {
|
||||
r, err := c.rolloutClient.FlaggerV1alpha1().Canaries(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return r, true
|
||||
}
|
||||
|
||||
func (c *Controller) checkRolloutStatus(r *flaggerv1.Canary, canary *appsv1.Deployment) bool {
|
||||
canaryRevision, err := c.getDeploymentSpecEnc(canary)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s not found: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "" {
|
||||
r.Status = flaggerv1.CanaryStatus{
|
||||
State: "initialized",
|
||||
CanaryRevision: canaryRevision,
|
||||
FailedChecks: 0,
|
||||
}
|
||||
r, err = c.rolloutClient.FlaggerV1alpha1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
c.recordEventInfof(r, "Initialization done! %s.%s", canary.GetName(), canary.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "running" {
|
||||
return true
|
||||
}
|
||||
|
||||
if r.Status.State == "promotion-finished" {
|
||||
c.setCanaryRevision(r, canary, "finished")
|
||||
c.logger.Infof("Promotion completed! %s.%s", r.Name, r.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "promotion-failed" {
|
||||
c.setCanaryRevision(r, canary, "failed")
|
||||
c.logger.Infof("Promotion failed! %s.%s", r.Name, r.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if diff, err := c.diffDeploymentSpec(r, canary); diff {
|
||||
c.recordEventInfof(r, "New revision detected %s.%s",
|
||||
canary.GetName(), canary.Namespace)
|
||||
canary.Spec.Replicas = int32p(1)
|
||||
canary, err = c.kubeClient.AppsV1().Deployments(canary.Namespace).Update(canary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Scaling up %s.%s failed: %v", canary.GetName(), canary.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
r.Status = flaggerv1.CanaryStatus{
|
||||
FailedChecks: 0,
|
||||
}
|
||||
c.setCanaryRevision(r, canary, "running")
|
||||
c.recordEventInfof(r, "Scaling up %s.%s", canary.GetName(), canary.Namespace)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Controller) updateRolloutStatus(r *flaggerv1.Canary, status string) bool {
|
||||
var err error
|
||||
r.Status.State = status
|
||||
r, err = c.rolloutClient.FlaggerV1alpha1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) updateRolloutFailedChecks(r *flaggerv1.Canary, val int) bool {
|
||||
var err error
|
||||
r.Status.FailedChecks = val
|
||||
r, err = c.rolloutClient.FlaggerV1alpha1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) getDeployment(r *flaggerv1.Canary, name string, namespace string) (*appsv1.Deployment, bool) {
|
||||
dep, err := c.kubeClient.AppsV1().Deployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if msg, healthy := getDeploymentStatus(dep); !healthy {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement %s", dep.GetName(), dep.Namespace, msg)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if dep.Spec.Replicas == nil || *dep.Spec.Replicas == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return dep, true
|
||||
}
|
||||
|
||||
func (c *Controller) getCanaryDeployment(r *flaggerv1.Canary, name string, namespace string) (*appsv1.Deployment, bool) {
|
||||
dep, err := c.kubeClient.AppsV1().Deployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if msg, healthy := getDeploymentStatus(dep); !healthy {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement %s", dep.GetName(), dep.Namespace, msg)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return dep, true
|
||||
}
|
||||
|
||||
func (c *Controller) checkDeploymentMetrics(r *flaggerv1.Canary) bool {
|
||||
for _, metric := range r.Spec.CanaryAnalysis.Metrics {
|
||||
if metric.Name == "istio_requests_total" {
|
||||
val, err := c.getDeploymentCounter(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.metricsServer, err)
|
||||
return false
|
||||
}
|
||||
if float64(metric.Threshold) > val {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement success rate %.2f%% < %v%%",
|
||||
r.Name, r.Namespace, val, metric.Threshold)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if metric.Name == "istio_request_duration_seconds_bucket" {
|
||||
val, err := c.GetDeploymentHistogram(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.metricsServer, err)
|
||||
return false
|
||||
}
|
||||
t := time.Duration(metric.Threshold) * time.Millisecond
|
||||
if val > t {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement request duration %v > %v",
|
||||
r.Name, r.Namespace, val, t)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) scaleToZeroCanary(r *flaggerv1.Canary) {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(r.Namespace).Get(r.Spec.TargetRef.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", r.Spec.TargetRef.Name, r.Namespace)
|
||||
return
|
||||
}
|
||||
//HPA https://github.com/kubernetes/kubernetes/pull/29212
|
||||
canary.Spec.Replicas = int32p(0)
|
||||
canary, err = c.kubeClient.AppsV1().Deployments(canary.Namespace).Update(canary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Scaling down %s.%s failed: %v", canary.GetName(), canary.Namespace, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) setCanaryRevision(r *flaggerv1.Canary, canary *appsv1.Deployment, status string) {
|
||||
r.Status = flaggerv1.CanaryStatus{
|
||||
State: status,
|
||||
FailedChecks: r.Status.FailedChecks,
|
||||
}
|
||||
err := c.saveDeploymentSpec(r, canary)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getVirtualService(r *flaggerv1.Canary) (
|
||||
vs *istiov1alpha3.VirtualService,
|
||||
primary istiov1alpha3.DestinationWeight,
|
||||
canary istiov1alpha3.DestinationWeight,
|
||||
ok bool,
|
||||
) {
|
||||
var err error
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Get(r.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s not found", r.Name, r.Namespace)
|
||||
return
|
||||
}
|
||||
|
||||
for _, http := range vs.Spec.Http {
|
||||
for _, route := range http.Route {
|
||||
if route.Destination.Host == fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name) {
|
||||
primary = route
|
||||
}
|
||||
if route.Destination.Host == r.Spec.TargetRef.Name {
|
||||
canary = route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if primary.Weight == 0 && canary.Weight == 0 {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s does not contain routes for %s and %s",
|
||||
r.Name, r.Namespace, fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name), r.Spec.TargetRef.Name)
|
||||
return
|
||||
}
|
||||
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Controller) updateVirtualServiceRoutes(
|
||||
r *flaggerv1.Canary,
|
||||
vs *istiov1alpha3.VirtualService,
|
||||
primary istiov1alpha3.DestinationWeight,
|
||||
canary istiov1alpha3.DestinationWeight,
|
||||
) bool {
|
||||
vs.Spec.Http = []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Route: []istiov1alpha3.DestinationWeight{primary, canary},
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Update(vs)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getDeploymentStatus(deployment *appsv1.Deployment) (string, bool) {
|
||||
if deployment.Generation <= deployment.Status.ObservedGeneration {
|
||||
cond := getDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)
|
||||
if cond != nil && cond.Reason == "ProgressDeadlineExceeded" {
|
||||
return fmt.Sprintf("deployment %q exceeded its progress deadline", deployment.GetName()), false
|
||||
} else if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d out of %d new replicas have been updated",
|
||||
deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false
|
||||
} else if deployment.Status.Replicas > deployment.Status.UpdatedReplicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d old replicas are pending termination",
|
||||
deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false
|
||||
} else if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d of %d updated replicas are available",
|
||||
deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false
|
||||
}
|
||||
} else {
|
||||
return "waiting for rollout to finish: observed deployment generation less then desired generation", false
|
||||
}
|
||||
|
||||
return "ready", true
|
||||
}
|
||||
|
||||
func getDeploymentCondition(
|
||||
status appsv1.DeploymentStatus,
|
||||
conditionType appsv1.DeploymentConditionType,
|
||||
) *appsv1.DeploymentCondition {
|
||||
for i := range status.Conditions {
|
||||
c := status.Conditions[i]
|
||||
if c.Type == conditionType {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func int32p(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
@@ -11,7 +11,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type VectorQueryResponse struct {
|
||||
// CanaryObserver is used to query the Istio Prometheus db
|
||||
type CanaryObserver struct {
|
||||
metricsServer string
|
||||
}
|
||||
|
||||
type vectorQueryResponse struct {
|
||||
Data struct {
|
||||
Result []struct {
|
||||
Metric struct {
|
||||
@@ -23,7 +28,7 @@ type VectorQueryResponse struct {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) queryMetric(query string) (*VectorQueryResponse, error) {
|
||||
func (c *CanaryObserver) queryMetric(query string) (*vectorQueryResponse, error) {
|
||||
promURL, err := url.Parse(c.metricsServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -59,7 +64,7 @@ func (c *Controller) queryMetric(query string) (*VectorQueryResponse, error) {
|
||||
return nil, fmt.Errorf("error response: %s", string(b))
|
||||
}
|
||||
|
||||
var values VectorQueryResponse
|
||||
var values vectorQueryResponse
|
||||
err = json.Unmarshal(b, &values)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling result: %s, '%s'", err.Error(), string(b))
|
||||
@@ -68,8 +73,12 @@ func (c *Controller) queryMetric(query string) (*VectorQueryResponse, error) {
|
||||
return &values, nil
|
||||
}
|
||||
|
||||
// istio_requests_total
|
||||
func (c *Controller) getDeploymentCounter(name string, namespace string, metric string, interval string) (float64, error) {
|
||||
// GetDeploymentCounter returns the requests success rate using istio_requests_total metric
|
||||
func (c *CanaryObserver) GetDeploymentCounter(name string, namespace string, metric string, interval string) (float64, error) {
|
||||
if c.metricsServer == "fake" {
|
||||
return 100, nil
|
||||
}
|
||||
|
||||
var rate *float64
|
||||
querySt := url.QueryEscape(`sum(rate(` +
|
||||
metric + `{reporter="destination",destination_workload_namespace=~"` +
|
||||
@@ -101,8 +110,11 @@ func (c *Controller) getDeploymentCounter(name string, namespace string, metric
|
||||
return *rate, nil
|
||||
}
|
||||
|
||||
// istio_request_duration_seconds_bucket
|
||||
func (c *Controller) GetDeploymentHistogram(name string, namespace string, metric string, interval string) (time.Duration, error) {
|
||||
// GetDeploymentHistogram returns the 99P requests delay using istio_request_duration_seconds_bucket metrics
|
||||
func (c *CanaryObserver) GetDeploymentHistogram(name string, namespace string, metric string, interval string) (time.Duration, error) {
|
||||
if c.metricsServer == "fake" {
|
||||
return 1, nil
|
||||
}
|
||||
var rate *float64
|
||||
querySt := url.QueryEscape(`histogram_quantile(0.99, sum(rate(` +
|
||||
metric + `{reporter="destination",destination_workload=~"` +
|
||||
@@ -132,6 +144,8 @@ func (c *Controller) GetDeploymentHistogram(name string, namespace string, metri
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
// CheckMetricsServer call Prometheus status endpoint and returns an error if
|
||||
// the API is unreachable
|
||||
func CheckMetricsServer(address string) (bool, error) {
|
||||
promURL, err := url.Parse(address)
|
||||
if err != nil {
|
||||
|
||||
90
pkg/controller/recorder.go
Normal file
90
pkg/controller/recorder.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
)
|
||||
|
||||
// CanaryRecorder records the canary analysis as Prometheus metrics
|
||||
type CanaryRecorder struct {
|
||||
duration *prometheus.HistogramVec
|
||||
total *prometheus.GaugeVec
|
||||
status *prometheus.GaugeVec
|
||||
weight *prometheus.GaugeVec
|
||||
}
|
||||
|
||||
// NewCanaryRecorder creates a new recorder and registers the Prometheus metrics
|
||||
func NewCanaryRecorder(register bool) CanaryRecorder {
|
||||
duration := prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Subsystem: controllerAgentName,
|
||||
Name: "canary_duration_seconds",
|
||||
Help: "Seconds spent performing canary analysis.",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
}, []string{"name", "namespace"})
|
||||
|
||||
total := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Subsystem: controllerAgentName,
|
||||
Name: "canary_total",
|
||||
Help: "Total number of canary object",
|
||||
}, []string{"namespace"})
|
||||
|
||||
// 0 - running, 1 - successful, 2 - failed
|
||||
status := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Subsystem: controllerAgentName,
|
||||
Name: "canary_status",
|
||||
Help: "Last canary analysis result",
|
||||
}, []string{"name", "namespace"})
|
||||
|
||||
weight := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Subsystem: controllerAgentName,
|
||||
Name: "canary_weight",
|
||||
Help: "The virtual service destination weight current value",
|
||||
}, []string{"workload", "namespace"})
|
||||
|
||||
if register {
|
||||
prometheus.MustRegister(duration)
|
||||
prometheus.MustRegister(total)
|
||||
prometheus.MustRegister(status)
|
||||
prometheus.MustRegister(weight)
|
||||
}
|
||||
|
||||
return CanaryRecorder{
|
||||
duration: duration,
|
||||
total: total,
|
||||
status: status,
|
||||
weight: weight,
|
||||
}
|
||||
}
|
||||
|
||||
// SetDuration sets the time spent in seconds performing canary analysis
|
||||
func (cr *CanaryRecorder) SetDuration(cd *flaggerv1.Canary, duration time.Duration) {
|
||||
cr.duration.WithLabelValues(cd.Spec.TargetRef.Name, cd.Namespace).Observe(duration.Seconds())
|
||||
}
|
||||
|
||||
// SetTotal sets the total number of canaries per namespace
|
||||
func (cr *CanaryRecorder) SetTotal(namespace string, total int) {
|
||||
cr.total.WithLabelValues(namespace).Set(float64(total))
|
||||
}
|
||||
|
||||
// SetStatus sets the last known canary analysis status
|
||||
func (cr *CanaryRecorder) SetStatus(cd *flaggerv1.Canary) {
|
||||
status := 1
|
||||
switch cd.Status.State {
|
||||
case "running":
|
||||
status = 0
|
||||
case "failed":
|
||||
status = 2
|
||||
default:
|
||||
status = 1
|
||||
}
|
||||
cr.status.WithLabelValues(cd.Spec.TargetRef.Name, cd.Namespace).Set(float64(status))
|
||||
}
|
||||
|
||||
// SetWeight sets the weight values for primary and canary destinations
|
||||
func (cr *CanaryRecorder) SetWeight(cd *flaggerv1.Canary, primary int, canary int) {
|
||||
cr.weight.WithLabelValues(fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name), cd.Namespace).Set(float64(primary))
|
||||
cr.weight.WithLabelValues(cd.Spec.TargetRef.Name, cd.Namespace).Set(float64(canary))
|
||||
}
|
||||
287
pkg/controller/router.go
Normal file
287
pkg/controller/router.go
Normal file
@@ -0,0 +1,287 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
istioclientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
"go.uber.org/zap"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// CanaryRouter is managing the operations for Kubernetes service kind
|
||||
// and Istio virtual services
|
||||
type CanaryRouter struct {
|
||||
kubeClient kubernetes.Interface
|
||||
istioClient istioclientset.Interface
|
||||
flaggerClient clientset.Interface
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
// Sync creates the primary and canary ClusterIP services
|
||||
// and sets up a virtual service with routes for the two services
|
||||
// all traffic goes to primary
|
||||
func (c *CanaryRouter) Sync(cd *flaggerv1.Canary) error {
|
||||
err := c.createServices(cd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.createVirtualService(cd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CanaryRouter) createServices(cd *flaggerv1.Canary) error {
|
||||
canaryName := cd.Spec.TargetRef.Name
|
||||
primaryName := fmt.Sprintf("%s-primary", canaryName)
|
||||
canaryService, err := c.kubeClient.CoreV1().Services(cd.Namespace).Get(canaryName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
canaryService = &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: canaryName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Selector: map[string]string{"app": canaryName},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
Port: cd.Spec.Service.Port,
|
||||
TargetPort: intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
IntVal: cd.Spec.Service.Port,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.CoreV1().Services(cd.Namespace).Create(canaryService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.logger.Infof("Service %s.%s created", canaryService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
canaryTestServiceName := fmt.Sprintf("%s-canary", cd.Spec.TargetRef.Name)
|
||||
canaryTestService, err := c.kubeClient.CoreV1().Services(cd.Namespace).Get(canaryTestServiceName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
canaryTestService = &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: canaryTestServiceName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Selector: map[string]string{"app": canaryName},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
Port: cd.Spec.Service.Port,
|
||||
TargetPort: intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
IntVal: cd.Spec.Service.Port,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.CoreV1().Services(cd.Namespace).Create(canaryTestService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.logger.Infof("Service %s.%s created", canaryTestService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
primaryService, err := c.kubeClient.CoreV1().Services(cd.Namespace).Get(primaryName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
primaryService = &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: primaryName,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Selector: map[string]string{"app": primaryName},
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
Port: cd.Spec.Service.Port,
|
||||
TargetPort: intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
IntVal: cd.Spec.Service.Port,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.kubeClient.CoreV1().Services(cd.Namespace).Create(primaryService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.logger.Infof("Service %s.%s created", primaryService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CanaryRouter) createVirtualService(cd *flaggerv1.Canary) error {
|
||||
canaryName := cd.Spec.TargetRef.Name
|
||||
primaryName := fmt.Sprintf("%s-primary", canaryName)
|
||||
hosts := append(cd.Spec.Service.Hosts, canaryName)
|
||||
gateways := append(cd.Spec.Service.Gateways, "mesh")
|
||||
virtualService, err := c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Get(canaryName, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
virtualService = &istiov1alpha3.VirtualService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: cd.Name,
|
||||
Namespace: cd.Namespace,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
Spec: istiov1alpha3.VirtualServiceSpec{
|
||||
Hosts: hosts,
|
||||
Gateways: gateways,
|
||||
Http: []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Route: []istiov1alpha3.DestinationWeight{
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: primaryName,
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(cd.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: canaryName,
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(cd.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Create(virtualService)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VirtualService %s.%s create error %v", cd.Name, cd.Namespace, err)
|
||||
}
|
||||
c.logger.Infof("VirtualService %s.%s created", virtualService.GetName(), cd.Namespace)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRoutes returns the destinations weight for primary and canary
|
||||
func (c *CanaryRouter) GetRoutes(cd *flaggerv1.Canary) (
|
||||
primary istiov1alpha3.DestinationWeight,
|
||||
canary istiov1alpha3.DestinationWeight,
|
||||
err error,
|
||||
) {
|
||||
vs := &istiov1alpha3.VirtualService{}
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Get(cd.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
err = fmt.Errorf("VirtualService %s.%s not found", cd.Name, cd.Namespace)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("VirtualService %s.%s query error %v", cd.Name, cd.Namespace, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, http := range vs.Spec.Http {
|
||||
for _, route := range http.Route {
|
||||
if route.Destination.Host == fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name) {
|
||||
primary = route
|
||||
}
|
||||
if route.Destination.Host == cd.Spec.TargetRef.Name {
|
||||
canary = route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if primary.Weight == 0 && canary.Weight == 0 {
|
||||
err = fmt.Errorf("VirtualService %s.%s does not contain routes for %s and %s",
|
||||
cd.Name, cd.Namespace, fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name), cd.Spec.TargetRef.Name)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetRoutes updates the destinations weight for primary and canary
|
||||
func (c *CanaryRouter) SetRoutes(
|
||||
cd *flaggerv1.Canary,
|
||||
primary istiov1alpha3.DestinationWeight,
|
||||
canary istiov1alpha3.DestinationWeight,
|
||||
) error {
|
||||
vs, err := c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Get(cd.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return fmt.Errorf("VirtualService %s.%s not found", cd.Name, cd.Namespace)
|
||||
|
||||
}
|
||||
return fmt.Errorf("VirtualService %s.%s query error %v", cd.Name, cd.Namespace, err)
|
||||
}
|
||||
vs.Spec.Http = []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Route: []istiov1alpha3.DestinationWeight{primary, canary},
|
||||
},
|
||||
}
|
||||
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Update(vs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VirtualService %s.%s update failed: %v", cd.Name, cd.Namespace, err)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
177
pkg/controller/router_test.go
Normal file
177
pkg/controller/router_test.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
fakeIstio "github.com/knative/pkg/client/clientset/versioned/fake"
|
||||
fakeFlagger "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/fake"
|
||||
"github.com/stefanprodan/flagger/pkg/logging"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func TestCanaryRouter_Sync(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
istioClient := fakeIstio.NewSimpleClientset()
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
|
||||
router := &CanaryRouter{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := router.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
canarySvc, err := kubeClient.CoreV1().Services("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if canarySvc.Spec.Ports[0].Name != "http" {
|
||||
t.Errorf("Got svc port name %s wanted %s", canarySvc.Spec.Ports[0].Name, "http")
|
||||
}
|
||||
|
||||
if canarySvc.Spec.Ports[0].Port != 9898 {
|
||||
t.Errorf("Got svc port %v wanted %v", canarySvc.Spec.Ports[0].Port, 9898)
|
||||
}
|
||||
|
||||
primarySvc, err := kubeClient.CoreV1().Services("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primarySvc.Spec.Ports[0].Name != "http" {
|
||||
t.Errorf("Got primary svc port name %s wanted %s", primarySvc.Spec.Ports[0].Name, "http")
|
||||
}
|
||||
|
||||
if primarySvc.Spec.Ports[0].Port != 9898 {
|
||||
t.Errorf("Got primary svc port %v wanted %v", primarySvc.Spec.Ports[0].Port, 9898)
|
||||
}
|
||||
|
||||
vs, err := istioClient.NetworkingV1alpha3().VirtualServices("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if len(vs.Spec.Http) != 1 {
|
||||
t.Errorf("Got Istio VS Http %v wanted %v", len(vs.Spec.Http), 1)
|
||||
}
|
||||
|
||||
if len(vs.Spec.Http[0].Route) != 2 {
|
||||
t.Errorf("Got Istio VS routes %v wanted %v", len(vs.Spec.Http[0].Route), 2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryRouter_GetRoutes(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
istioClient := fakeIstio.NewSimpleClientset()
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
|
||||
router := &CanaryRouter{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := router.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
p, c, err := router.GetRoutes(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if p.Weight != 100 {
|
||||
t.Errorf("Got primary weight %v wanted %v", p.Weight, 100)
|
||||
}
|
||||
|
||||
if c.Weight != 0 {
|
||||
t.Errorf("Got canary weight %v wanted %v", c.Weight, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryRouter_SetRoutes(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
istioClient := fakeIstio.NewSimpleClientset()
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
|
||||
router := &CanaryRouter{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
err := router.Sync(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
p, c, err := router.GetRoutes(canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
p.Weight = 50
|
||||
c.Weight = 50
|
||||
|
||||
err = router.SetRoutes(canary, p, c)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
vs, err := istioClient.NetworkingV1alpha3().VirtualServices("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
pRoute := istiov1alpha3.DestinationWeight{}
|
||||
cRoute := istiov1alpha3.DestinationWeight{}
|
||||
|
||||
for _, http := range vs.Spec.Http {
|
||||
for _, route := range http.Route {
|
||||
if route.Destination.Host == fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name) {
|
||||
pRoute = route
|
||||
}
|
||||
if route.Destination.Host == canary.Spec.TargetRef.Name {
|
||||
cRoute = route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if pRoute.Weight != p.Weight {
|
||||
t.Errorf("Got primary weight %v wanted %v", pRoute.Weight, c.Weight)
|
||||
}
|
||||
|
||||
if cRoute.Weight != c.Weight {
|
||||
t.Errorf("Got canary weight %v wanted %v", cRoute.Weight, c.Weight)
|
||||
}
|
||||
}
|
||||
249
pkg/controller/scheduler.go
Normal file
249
pkg/controller/scheduler.go
Normal file
@@ -0,0 +1,249 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (c *Controller) scheduleCanaries() {
|
||||
stats := make(map[string]int)
|
||||
c.canaries.Range(func(key interface{}, value interface{}) bool {
|
||||
r := value.(*flaggerv1.Canary)
|
||||
if r.Spec.TargetRef.Kind == "Deployment" {
|
||||
go c.advanceCanary(r.Name, r.Namespace)
|
||||
}
|
||||
|
||||
t, ok := stats[r.Namespace]
|
||||
if !ok {
|
||||
stats[r.Namespace] = 1
|
||||
} else {
|
||||
stats[r.Namespace] = t + 1
|
||||
}
|
||||
return true
|
||||
})
|
||||
for k, v := range stats {
|
||||
c.recorder.SetTotal(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) advanceCanary(name string, namespace string) {
|
||||
begin := time.Now()
|
||||
// check if the canary exists
|
||||
cd, err := c.flaggerClient.FlaggerV1alpha1().Canaries(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s not found", name, namespace)
|
||||
return
|
||||
}
|
||||
|
||||
// create primary deployment and hpa if needed
|
||||
if err := c.deployer.Sync(cd); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// create ClusterIP services and virtual service if needed
|
||||
if err := c.router.Sync(cd); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// set max weight default value to 100%
|
||||
maxWeight := 100
|
||||
if cd.Spec.CanaryAnalysis.MaxWeight > 0 {
|
||||
maxWeight = cd.Spec.CanaryAnalysis.MaxWeight
|
||||
}
|
||||
|
||||
// check primary and canary deployments status
|
||||
if err := c.deployer.IsReady(cd); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// check if virtual service exists
|
||||
// and if it contains weighted destination routes to the primary and canary services
|
||||
primaryRoute, canaryRoute, err := c.router.GetRoutes(cd)
|
||||
if err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.recorder.SetWeight(cd, primaryRoute.Weight, canaryRoute.Weight)
|
||||
|
||||
// check if canary analysis should start (canary revision has changes) or continue
|
||||
if ok := c.checkCanaryStatus(cd, c.deployer); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
c.recorder.SetDuration(cd, time.Since(begin))
|
||||
}()
|
||||
|
||||
// check if the number of failed checks reached the threshold
|
||||
if cd.Status.State == "running" && cd.Status.FailedChecks >= cd.Spec.CanaryAnalysis.Threshold {
|
||||
c.recordEventWarningf(cd, "Rolling back %s.%s failed checks threshold reached %v",
|
||||
cd.Name, cd.Namespace, cd.Status.FailedChecks)
|
||||
|
||||
// route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
canaryRoute.Weight = 0
|
||||
if err := c.router.SetRoutes(cd, primaryRoute, canaryRoute); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.recorder.SetWeight(cd, primaryRoute.Weight, canaryRoute.Weight)
|
||||
c.recordEventWarningf(cd, "Canary failed! Scaling down %s.%s",
|
||||
cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
|
||||
// shutdown canary
|
||||
if err := c.deployer.Scale(cd, 0); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// mark canary as failed
|
||||
if err := c.deployer.SetState(cd, "failed"); err != nil {
|
||||
c.logger.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
c.recorder.SetStatus(cd)
|
||||
return
|
||||
}
|
||||
|
||||
// check if the canary success rate is above the threshold
|
||||
// skip check if no traffic is routed to canary
|
||||
if canaryRoute.Weight == 0 {
|
||||
c.recordEventInfof(cd, "Starting canary deployment for %s.%s", cd.Name, cd.Namespace)
|
||||
} else {
|
||||
if ok := c.checkCanaryMetrics(cd); !ok {
|
||||
if err := c.deployer.SetFailedChecks(cd, cd.Status.FailedChecks+1); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// increase canary traffic percentage
|
||||
if canaryRoute.Weight < maxWeight {
|
||||
primaryRoute.Weight -= cd.Spec.CanaryAnalysis.StepWeight
|
||||
if primaryRoute.Weight < 0 {
|
||||
primaryRoute.Weight = 0
|
||||
}
|
||||
canaryRoute.Weight += cd.Spec.CanaryAnalysis.StepWeight
|
||||
if primaryRoute.Weight > 100 {
|
||||
primaryRoute.Weight = 100
|
||||
}
|
||||
|
||||
if err := c.router.SetRoutes(cd, primaryRoute, canaryRoute); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.recorder.SetWeight(cd, primaryRoute.Weight, canaryRoute.Weight)
|
||||
c.recordEventInfof(cd, "Advance %s.%s canary weight %v", cd.Name, cd.Namespace, canaryRoute.Weight)
|
||||
|
||||
// promote canary
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
if canaryRoute.Weight == maxWeight {
|
||||
c.recordEventInfof(cd, "Copying %s.%s template spec to %s.%s",
|
||||
cd.Spec.TargetRef.Name, cd.Namespace, primaryName, cd.Namespace)
|
||||
if err := c.deployer.Promote(cd); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
canaryRoute.Weight = 0
|
||||
if err := c.router.SetRoutes(cd, primaryRoute, canaryRoute); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.recorder.SetWeight(cd, primaryRoute.Weight, canaryRoute.Weight)
|
||||
c.recordEventInfof(cd, "Promotion completed! Scaling down %s.%s", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
|
||||
// shutdown canary
|
||||
if err := c.deployer.Scale(cd, 0); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// update status
|
||||
if err := c.deployer.SetState(cd, "finished"); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
return
|
||||
}
|
||||
c.recorder.SetStatus(cd)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) checkCanaryStatus(cd *flaggerv1.Canary, deployer CanaryDeployer) bool {
|
||||
c.recorder.SetStatus(cd)
|
||||
if cd.Status.State == "running" {
|
||||
return true
|
||||
}
|
||||
|
||||
if cd.Status.State == "" {
|
||||
if err := deployer.SyncStatus(cd, flaggerv1.CanaryStatus{State: "initialized"}); err != nil {
|
||||
c.logger.Errorf("%v", err)
|
||||
return false
|
||||
}
|
||||
c.recorder.SetStatus(cd)
|
||||
c.recordEventInfof(cd, "Initialization done! %s.%s", cd.Name, cd.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if diff, err := deployer.IsNewSpec(cd); diff {
|
||||
c.recordEventInfof(cd, "New revision detected! Scaling up %s.%s", cd.Spec.TargetRef.Name, cd.Namespace)
|
||||
if err = deployer.Scale(cd, 1); err != nil {
|
||||
c.recordEventErrorf(cd, "%v", err)
|
||||
return false
|
||||
}
|
||||
if err := deployer.SyncStatus(cd, flaggerv1.CanaryStatus{State: "running"}); err != nil {
|
||||
c.logger.Errorf("%v", err)
|
||||
return false
|
||||
}
|
||||
c.recorder.SetStatus(cd)
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Controller) checkCanaryMetrics(r *flaggerv1.Canary) bool {
|
||||
for _, metric := range r.Spec.CanaryAnalysis.Metrics {
|
||||
if metric.Name == "istio_requests_total" {
|
||||
val, err := c.observer.GetDeploymentCounter(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.observer.metricsServer, err)
|
||||
return false
|
||||
}
|
||||
if float64(metric.Threshold) > val {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement success rate %.2f%% < %v%%",
|
||||
r.Name, r.Namespace, val, metric.Threshold)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if metric.Name == "istio_request_duration_seconds_bucket" {
|
||||
val, err := c.observer.GetDeploymentHistogram(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.observer.metricsServer, err)
|
||||
return false
|
||||
}
|
||||
t := time.Duration(metric.Threshold) * time.Millisecond
|
||||
if val > t {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement request duration %v > %v",
|
||||
r.Name, r.Namespace, val, t)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
144
pkg/controller/scheduler_test.go
Normal file
144
pkg/controller/scheduler_test.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
fakeIstio "github.com/knative/pkg/client/clientset/versioned/fake"
|
||||
fakeFlagger "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/fake"
|
||||
informers "github.com/stefanprodan/flagger/pkg/client/informers/externalversions"
|
||||
"github.com/stefanprodan/flagger/pkg/logging"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
|
||||
var (
|
||||
alwaysReady = func() bool { return true }
|
||||
noResyncPeriodFunc = func() time.Duration { return 0 }
|
||||
)
|
||||
|
||||
func TestScheduler_Init(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
istioClient := fakeIstio.NewSimpleClientset()
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
router := CanaryRouter{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
logger: logger,
|
||||
}
|
||||
observer := CanaryObserver{
|
||||
metricsServer: "fake",
|
||||
}
|
||||
|
||||
flaggerInformerFactory := informers.NewSharedInformerFactory(flaggerClient, noResyncPeriodFunc())
|
||||
flaggerInformer := flaggerInformerFactory.Flagger().V1alpha1().Canaries()
|
||||
|
||||
ctrl := &Controller{
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
flaggerClient: flaggerClient,
|
||||
flaggerLister: flaggerInformer.Lister(),
|
||||
flaggerSynced: flaggerInformer.Informer().HasSynced,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), controllerAgentName),
|
||||
eventRecorder: &record.FakeRecorder{},
|
||||
logger: logger,
|
||||
canaries: new(sync.Map),
|
||||
flaggerWindow: time.Second,
|
||||
deployer: deployer,
|
||||
router: router,
|
||||
observer: observer,
|
||||
recorder: NewCanaryRecorder(false),
|
||||
}
|
||||
ctrl.flaggerSynced = alwaysReady
|
||||
|
||||
ctrl.advanceCanary("podinfo", "default")
|
||||
|
||||
_, err := kubeClient.AppsV1().Deployments("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_NewRevision(t *testing.T) {
|
||||
canary := newTestCanary()
|
||||
dep := newTestDeployment()
|
||||
hpa := newTestHPA()
|
||||
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
kubeClient := fake.NewSimpleClientset(dep, hpa)
|
||||
istioClient := fakeIstio.NewSimpleClientset()
|
||||
|
||||
logger, _ := logging.NewLogger("debug")
|
||||
deployer := CanaryDeployer{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
logger: logger,
|
||||
}
|
||||
router := CanaryRouter{
|
||||
flaggerClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
logger: logger,
|
||||
}
|
||||
observer := CanaryObserver{
|
||||
metricsServer: "fake",
|
||||
}
|
||||
|
||||
flaggerInformerFactory := informers.NewSharedInformerFactory(flaggerClient, noResyncPeriodFunc())
|
||||
flaggerInformer := flaggerInformerFactory.Flagger().V1alpha1().Canaries()
|
||||
|
||||
ctrl := &Controller{
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
flaggerClient: flaggerClient,
|
||||
flaggerLister: flaggerInformer.Lister(),
|
||||
flaggerSynced: flaggerInformer.Informer().HasSynced,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), controllerAgentName),
|
||||
eventRecorder: &record.FakeRecorder{},
|
||||
logger: logger,
|
||||
canaries: new(sync.Map),
|
||||
flaggerWindow: time.Second,
|
||||
deployer: deployer,
|
||||
router: router,
|
||||
observer: observer,
|
||||
recorder: NewCanaryRecorder(false),
|
||||
}
|
||||
ctrl.flaggerSynced = alwaysReady
|
||||
|
||||
// init
|
||||
ctrl.advanceCanary("podinfo", "default")
|
||||
|
||||
// update
|
||||
dep2 := newTestDeploymentUpdated()
|
||||
_, err := kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect changes
|
||||
ctrl.advanceCanary("podinfo", "default")
|
||||
|
||||
c, err := kubeClient.AppsV1().Deployments("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if *c.Spec.Replicas != 1 {
|
||||
t.Errorf("Got canary replicas %v wanted %v", *c.Spec.Replicas, 1)
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (c *Controller) saveDeploymentSpec(cd *flaggerv1.Canary, dep *appsv1.Deployment) error {
|
||||
specJson, err := json.Marshal(dep.Spec.Template.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specEnc := base64.StdEncoding.EncodeToString(specJson)
|
||||
cd.Status.CanaryRevision = specEnc
|
||||
cd, err = c.rolloutClient.FlaggerV1alpha1().Canaries(cd.Namespace).Update(cd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) diffDeploymentSpec(cd *flaggerv1.Canary, dep *appsv1.Deployment) (bool, error) {
|
||||
if cd.Status.CanaryRevision == "" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
newSpec := &dep.Spec.Template.Spec
|
||||
oldSpecJson, err := base64.StdEncoding.DecodeString(cd.Status.CanaryRevision)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
oldSpec := &corev1.PodSpec{}
|
||||
err = json.Unmarshal(oldSpecJson, oldSpec)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(*newSpec, *oldSpec, cmpopts.IgnoreUnexported(resource.Quantity{})); diff != "" {
|
||||
fmt.Println(diff)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getDeploymentSpec(name string, namespace string) (string, error) {
|
||||
dep, err := c.kubeClient.AppsV1().Deployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
specJson, err := json.Marshal(dep.Spec.Template.Spec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
specEnc := base64.StdEncoding.EncodeToString(specJson)
|
||||
return specEnc, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getDeploymentSpecEnc(dep *appsv1.Deployment) (string, error) {
|
||||
specJson, err := json.Marshal(dep.Spec.Template.Spec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
specEnc := base64.StdEncoding.EncodeToString(specJson)
|
||||
return specEnc, nil
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// NewLogger returns a zap sugared logger configured with json format and caller id
|
||||
func NewLogger(logLevel string) (*zap.SugaredLogger, error) {
|
||||
level := zap.NewAtomicLevelAt(zapcore.InfoLevel)
|
||||
switch logLevel {
|
||||
@@ -59,6 +60,7 @@ func NewLogger(logLevel string) (*zap.SugaredLogger, error) {
|
||||
return logger.Sugar(), nil
|
||||
}
|
||||
|
||||
// Console writes to stdout if the console env var exists
|
||||
func Console(a ...interface{}) (n int, err error) {
|
||||
if os.Getenv("console") != "" {
|
||||
return fmt.Fprintln(os.Stdout, a...)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ListenAndServe starts a web server and waits for SIGTERM
|
||||
func ListenAndServe(port string, timeout time.Duration, logger *zap.SugaredLogger, stopCh <-chan struct{}) {
|
||||
mux := http.DefaultServeMux
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
var VERSION = "0.1.0-alpha.1"
|
||||
var VERSION = "0.1.0-beta.6"
|
||||
var REVISION = "unknown"
|
||||
|
||||
106
vendor/github.com/knative/pkg/client/clientset/versioned/fake/clientset_generated.go
generated
vendored
Normal file
106
vendor/github.com/knative/pkg/client/clientset/versioned/fake/clientset_generated.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
authenticationv1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1"
|
||||
fakeauthenticationv1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake"
|
||||
duckv1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1"
|
||||
fakeduckv1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake"
|
||||
networkingv1alpha3 "github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3"
|
||||
fakenetworkingv1alpha3 "github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// AuthenticationV1alpha1 retrieves the AuthenticationV1alpha1Client
|
||||
func (c *Clientset) AuthenticationV1alpha1() authenticationv1alpha1.AuthenticationV1alpha1Interface {
|
||||
return &fakeauthenticationv1alpha1.FakeAuthenticationV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Authentication retrieves the AuthenticationV1alpha1Client
|
||||
func (c *Clientset) Authentication() authenticationv1alpha1.AuthenticationV1alpha1Interface {
|
||||
return &fakeauthenticationv1alpha1.FakeAuthenticationV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// DuckV1alpha1 retrieves the DuckV1alpha1Client
|
||||
func (c *Clientset) DuckV1alpha1() duckv1alpha1.DuckV1alpha1Interface {
|
||||
return &fakeduckv1alpha1.FakeDuckV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Duck retrieves the DuckV1alpha1Client
|
||||
func (c *Clientset) Duck() duckv1alpha1.DuckV1alpha1Interface {
|
||||
return &fakeduckv1alpha1.FakeDuckV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// NetworkingV1alpha3 retrieves the NetworkingV1alpha3Client
|
||||
func (c *Clientset) NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface {
|
||||
return &fakenetworkingv1alpha3.FakeNetworkingV1alpha3{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Networking retrieves the NetworkingV1alpha3Client
|
||||
func (c *Clientset) Networking() networkingv1alpha3.NetworkingV1alpha3Interface {
|
||||
return &fakenetworkingv1alpha3.FakeNetworkingV1alpha3{Fake: &c.Fake}
|
||||
}
|
||||
20
vendor/github.com/knative/pkg/client/clientset/versioned/fake/doc.go
generated
vendored
Normal file
20
vendor/github.com/knative/pkg/client/clientset/versioned/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
58
vendor/github.com/knative/pkg/client/clientset/versioned/fake/register.go
generated
vendored
Normal file
58
vendor/github.com/knative/pkg/client/clientset/versioned/fake/register.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
duckv1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
|
||||
authenticationv1alpha1 "github.com/knative/pkg/apis/istio/authentication/v1alpha1"
|
||||
networkingv1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(scheme)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
authenticationv1alpha1.AddToScheme(scheme)
|
||||
duckv1alpha1.AddToScheme(scheme)
|
||||
networkingv1alpha3.AddToScheme(scheme)
|
||||
}
|
||||
20
vendor/github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake/doc.go
generated
vendored
Normal file
20
vendor/github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
40
vendor/github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake/fake_authentication_client.go
generated
vendored
Normal file
40
vendor/github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake/fake_authentication_client.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeAuthenticationV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAuthenticationV1alpha1) Policies(namespace string) v1alpha1.PolicyInterface {
|
||||
return &FakePolicies{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeAuthenticationV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake/fake_policy.go
generated
vendored
Normal file
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1/fake/fake_policy.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/apis/istio/authentication/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakePolicies implements PolicyInterface
|
||||
type FakePolicies struct {
|
||||
Fake *FakeAuthenticationV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var policiesResource = schema.GroupVersionResource{Group: "authentication.istio.io", Version: "v1alpha1", Resource: "policies"}
|
||||
|
||||
var policiesKind = schema.GroupVersionKind{Group: "authentication.istio.io", Version: "v1alpha1", Kind: "Policy"}
|
||||
|
||||
// Get takes name of the policy, and returns the corresponding policy object, and an error if there is any.
|
||||
func (c *FakePolicies) Get(name string, options v1.GetOptions) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(policiesResource, c.ns, name), &v1alpha1.Policy{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Policies that match those selectors.
|
||||
func (c *FakePolicies) List(opts v1.ListOptions) (result *v1alpha1.PolicyList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(policiesResource, policiesKind, c.ns, opts), &v1alpha1.PolicyList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.PolicyList{ListMeta: obj.(*v1alpha1.PolicyList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.PolicyList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested policies.
|
||||
func (c *FakePolicies) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(policiesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a policy and creates it. Returns the server's representation of the policy, and an error, if there is any.
|
||||
func (c *FakePolicies) Create(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(policiesResource, c.ns, policy), &v1alpha1.Policy{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a policy and updates it. Returns the server's representation of the policy, and an error, if there is any.
|
||||
func (c *FakePolicies) Update(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(policiesResource, c.ns, policy), &v1alpha1.Policy{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// Delete takes name of the policy and deletes it. Returns an error if one occurs.
|
||||
func (c *FakePolicies) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(policiesResource, c.ns, name), &v1alpha1.Policy{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakePolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(policiesResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.PolicyList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched policy.
|
||||
func (c *FakePolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(policiesResource, c.ns, name, data, subresources...), &v1alpha1.Policy{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
20
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/doc.go
generated
vendored
Normal file
20
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
52
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_duck_client.go
generated
vendored
Normal file
52
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_duck_client.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeDuckV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeDuckV1alpha1) Generationals(namespace string) v1alpha1.GenerationalInterface {
|
||||
return &FakeGenerationals{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeDuckV1alpha1) KResources(namespace string) v1alpha1.KResourceInterface {
|
||||
return &FakeKResources{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeDuckV1alpha1) Targets(namespace string) v1alpha1.TargetInterface {
|
||||
return &FakeTargets{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeDuckV1alpha1) Topics(namespace string) v1alpha1.TopicInterface {
|
||||
return &FakeTopics{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeDuckV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_generational.go
generated
vendored
Normal file
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_generational.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeGenerationals implements GenerationalInterface
|
||||
type FakeGenerationals struct {
|
||||
Fake *FakeDuckV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var generationalsResource = schema.GroupVersionResource{Group: "duck.knative.dev", Version: "v1alpha1", Resource: "generationals"}
|
||||
|
||||
var generationalsKind = schema.GroupVersionKind{Group: "duck.knative.dev", Version: "v1alpha1", Kind: "Generational"}
|
||||
|
||||
// Get takes name of the generational, and returns the corresponding generational object, and an error if there is any.
|
||||
func (c *FakeGenerationals) Get(name string, options v1.GetOptions) (result *v1alpha1.Generational, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(generationalsResource, c.ns, name), &v1alpha1.Generational{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Generational), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Generationals that match those selectors.
|
||||
func (c *FakeGenerationals) List(opts v1.ListOptions) (result *v1alpha1.GenerationalList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(generationalsResource, generationalsKind, c.ns, opts), &v1alpha1.GenerationalList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.GenerationalList{ListMeta: obj.(*v1alpha1.GenerationalList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.GenerationalList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested generationals.
|
||||
func (c *FakeGenerationals) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(generationalsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a generational and creates it. Returns the server's representation of the generational, and an error, if there is any.
|
||||
func (c *FakeGenerationals) Create(generational *v1alpha1.Generational) (result *v1alpha1.Generational, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(generationalsResource, c.ns, generational), &v1alpha1.Generational{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Generational), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a generational and updates it. Returns the server's representation of the generational, and an error, if there is any.
|
||||
func (c *FakeGenerationals) Update(generational *v1alpha1.Generational) (result *v1alpha1.Generational, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(generationalsResource, c.ns, generational), &v1alpha1.Generational{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Generational), err
|
||||
}
|
||||
|
||||
// Delete takes name of the generational and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeGenerationals) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(generationalsResource, c.ns, name), &v1alpha1.Generational{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeGenerationals) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(generationalsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.GenerationalList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched generational.
|
||||
func (c *FakeGenerationals) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Generational, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(generationalsResource, c.ns, name, data, subresources...), &v1alpha1.Generational{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Generational), err
|
||||
}
|
||||
140
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_kresource.go
generated
vendored
Normal file
140
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_kresource.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeKResources implements KResourceInterface
|
||||
type FakeKResources struct {
|
||||
Fake *FakeDuckV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var kresourcesResource = schema.GroupVersionResource{Group: "duck.knative.dev", Version: "v1alpha1", Resource: "kresources"}
|
||||
|
||||
var kresourcesKind = schema.GroupVersionKind{Group: "duck.knative.dev", Version: "v1alpha1", Kind: "KResource"}
|
||||
|
||||
// Get takes name of the kResource, and returns the corresponding kResource object, and an error if there is any.
|
||||
func (c *FakeKResources) Get(name string, options v1.GetOptions) (result *v1alpha1.KResource, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(kresourcesResource, c.ns, name), &v1alpha1.KResource{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.KResource), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of KResources that match those selectors.
|
||||
func (c *FakeKResources) List(opts v1.ListOptions) (result *v1alpha1.KResourceList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(kresourcesResource, kresourcesKind, c.ns, opts), &v1alpha1.KResourceList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.KResourceList{ListMeta: obj.(*v1alpha1.KResourceList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.KResourceList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested kResources.
|
||||
func (c *FakeKResources) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(kresourcesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a kResource and creates it. Returns the server's representation of the kResource, and an error, if there is any.
|
||||
func (c *FakeKResources) Create(kResource *v1alpha1.KResource) (result *v1alpha1.KResource, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(kresourcesResource, c.ns, kResource), &v1alpha1.KResource{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.KResource), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a kResource and updates it. Returns the server's representation of the kResource, and an error, if there is any.
|
||||
func (c *FakeKResources) Update(kResource *v1alpha1.KResource) (result *v1alpha1.KResource, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(kresourcesResource, c.ns, kResource), &v1alpha1.KResource{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.KResource), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeKResources) UpdateStatus(kResource *v1alpha1.KResource) (*v1alpha1.KResource, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(kresourcesResource, "status", c.ns, kResource), &v1alpha1.KResource{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.KResource), err
|
||||
}
|
||||
|
||||
// Delete takes name of the kResource and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeKResources) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(kresourcesResource, c.ns, name), &v1alpha1.KResource{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeKResources) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(kresourcesResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.KResourceList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched kResource.
|
||||
func (c *FakeKResources) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.KResource, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(kresourcesResource, c.ns, name, data, subresources...), &v1alpha1.KResource{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.KResource), err
|
||||
}
|
||||
140
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_target.go
generated
vendored
Normal file
140
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_target.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeTargets implements TargetInterface
|
||||
type FakeTargets struct {
|
||||
Fake *FakeDuckV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var targetsResource = schema.GroupVersionResource{Group: "duck.knative.dev", Version: "v1alpha1", Resource: "targets"}
|
||||
|
||||
var targetsKind = schema.GroupVersionKind{Group: "duck.knative.dev", Version: "v1alpha1", Kind: "Target"}
|
||||
|
||||
// Get takes name of the target, and returns the corresponding target object, and an error if there is any.
|
||||
func (c *FakeTargets) Get(name string, options v1.GetOptions) (result *v1alpha1.Target, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(targetsResource, c.ns, name), &v1alpha1.Target{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Target), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Targets that match those selectors.
|
||||
func (c *FakeTargets) List(opts v1.ListOptions) (result *v1alpha1.TargetList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(targetsResource, targetsKind, c.ns, opts), &v1alpha1.TargetList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.TargetList{ListMeta: obj.(*v1alpha1.TargetList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.TargetList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested targets.
|
||||
func (c *FakeTargets) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(targetsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a target and creates it. Returns the server's representation of the target, and an error, if there is any.
|
||||
func (c *FakeTargets) Create(target *v1alpha1.Target) (result *v1alpha1.Target, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(targetsResource, c.ns, target), &v1alpha1.Target{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Target), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a target and updates it. Returns the server's representation of the target, and an error, if there is any.
|
||||
func (c *FakeTargets) Update(target *v1alpha1.Target) (result *v1alpha1.Target, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(targetsResource, c.ns, target), &v1alpha1.Target{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Target), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeTargets) UpdateStatus(target *v1alpha1.Target) (*v1alpha1.Target, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(targetsResource, "status", c.ns, target), &v1alpha1.Target{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Target), err
|
||||
}
|
||||
|
||||
// Delete takes name of the target and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeTargets) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(targetsResource, c.ns, name), &v1alpha1.Target{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeTargets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(targetsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.TargetList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched target.
|
||||
func (c *FakeTargets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Target, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(targetsResource, c.ns, name, data, subresources...), &v1alpha1.Target{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Target), err
|
||||
}
|
||||
140
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_topic.go
generated
vendored
Normal file
140
vendor/github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1/fake/fake_topic.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeTopics implements TopicInterface
|
||||
type FakeTopics struct {
|
||||
Fake *FakeDuckV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var topicsResource = schema.GroupVersionResource{Group: "duck.knative.dev", Version: "v1alpha1", Resource: "topics"}
|
||||
|
||||
var topicsKind = schema.GroupVersionKind{Group: "duck.knative.dev", Version: "v1alpha1", Kind: "Topic"}
|
||||
|
||||
// Get takes name of the topic, and returns the corresponding topic object, and an error if there is any.
|
||||
func (c *FakeTopics) Get(name string, options v1.GetOptions) (result *v1alpha1.Topic, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(topicsResource, c.ns, name), &v1alpha1.Topic{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Topic), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Topics that match those selectors.
|
||||
func (c *FakeTopics) List(opts v1.ListOptions) (result *v1alpha1.TopicList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(topicsResource, topicsKind, c.ns, opts), &v1alpha1.TopicList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.TopicList{ListMeta: obj.(*v1alpha1.TopicList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.TopicList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested topics.
|
||||
func (c *FakeTopics) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(topicsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a topic and creates it. Returns the server's representation of the topic, and an error, if there is any.
|
||||
func (c *FakeTopics) Create(topic *v1alpha1.Topic) (result *v1alpha1.Topic, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(topicsResource, c.ns, topic), &v1alpha1.Topic{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Topic), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a topic and updates it. Returns the server's representation of the topic, and an error, if there is any.
|
||||
func (c *FakeTopics) Update(topic *v1alpha1.Topic) (result *v1alpha1.Topic, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(topicsResource, c.ns, topic), &v1alpha1.Topic{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Topic), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeTopics) UpdateStatus(topic *v1alpha1.Topic) (*v1alpha1.Topic, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(topicsResource, "status", c.ns, topic), &v1alpha1.Topic{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Topic), err
|
||||
}
|
||||
|
||||
// Delete takes name of the topic and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeTopics) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(topicsResource, c.ns, name), &v1alpha1.Topic{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeTopics) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(topicsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.TopicList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched topic.
|
||||
func (c *FakeTopics) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Topic, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(topicsResource, c.ns, name, data, subresources...), &v1alpha1.Topic{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Topic), err
|
||||
}
|
||||
20
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/doc.go
generated
vendored
Normal file
20
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_destinationrule.go
generated
vendored
Normal file
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_destinationrule.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeDestinationRules implements DestinationRuleInterface
|
||||
type FakeDestinationRules struct {
|
||||
Fake *FakeNetworkingV1alpha3
|
||||
ns string
|
||||
}
|
||||
|
||||
var destinationrulesResource = schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1alpha3", Resource: "destinationrules"}
|
||||
|
||||
var destinationrulesKind = schema.GroupVersionKind{Group: "networking.istio.io", Version: "v1alpha3", Kind: "DestinationRule"}
|
||||
|
||||
// Get takes name of the destinationRule, and returns the corresponding destinationRule object, and an error if there is any.
|
||||
func (c *FakeDestinationRules) Get(name string, options v1.GetOptions) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(destinationrulesResource, c.ns, name), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of DestinationRules that match those selectors.
|
||||
func (c *FakeDestinationRules) List(opts v1.ListOptions) (result *v1alpha3.DestinationRuleList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(destinationrulesResource, destinationrulesKind, c.ns, opts), &v1alpha3.DestinationRuleList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha3.DestinationRuleList{ListMeta: obj.(*v1alpha3.DestinationRuleList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha3.DestinationRuleList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested destinationRules.
|
||||
func (c *FakeDestinationRules) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(destinationrulesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a destinationRule and creates it. Returns the server's representation of the destinationRule, and an error, if there is any.
|
||||
func (c *FakeDestinationRules) Create(destinationRule *v1alpha3.DestinationRule) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(destinationrulesResource, c.ns, destinationRule), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a destinationRule and updates it. Returns the server's representation of the destinationRule, and an error, if there is any.
|
||||
func (c *FakeDestinationRules) Update(destinationRule *v1alpha3.DestinationRule) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(destinationrulesResource, c.ns, destinationRule), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
|
||||
// Delete takes name of the destinationRule and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeDestinationRules) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(destinationrulesResource, c.ns, name), &v1alpha3.DestinationRule{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeDestinationRules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(destinationrulesResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha3.DestinationRuleList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched destinationRule.
|
||||
func (c *FakeDestinationRules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(destinationrulesResource, c.ns, name, data, subresources...), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_gateway.go
generated
vendored
Normal file
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_gateway.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeGateways implements GatewayInterface
|
||||
type FakeGateways struct {
|
||||
Fake *FakeNetworkingV1alpha3
|
||||
ns string
|
||||
}
|
||||
|
||||
var gatewaysResource = schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1alpha3", Resource: "gateways"}
|
||||
|
||||
var gatewaysKind = schema.GroupVersionKind{Group: "networking.istio.io", Version: "v1alpha3", Kind: "Gateway"}
|
||||
|
||||
// Get takes name of the gateway, and returns the corresponding gateway object, and an error if there is any.
|
||||
func (c *FakeGateways) Get(name string, options v1.GetOptions) (result *v1alpha3.Gateway, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(gatewaysResource, c.ns, name), &v1alpha3.Gateway{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.Gateway), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Gateways that match those selectors.
|
||||
func (c *FakeGateways) List(opts v1.ListOptions) (result *v1alpha3.GatewayList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(gatewaysResource, gatewaysKind, c.ns, opts), &v1alpha3.GatewayList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha3.GatewayList{ListMeta: obj.(*v1alpha3.GatewayList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha3.GatewayList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested gateways.
|
||||
func (c *FakeGateways) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(gatewaysResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a gateway and creates it. Returns the server's representation of the gateway, and an error, if there is any.
|
||||
func (c *FakeGateways) Create(gateway *v1alpha3.Gateway) (result *v1alpha3.Gateway, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(gatewaysResource, c.ns, gateway), &v1alpha3.Gateway{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.Gateway), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a gateway and updates it. Returns the server's representation of the gateway, and an error, if there is any.
|
||||
func (c *FakeGateways) Update(gateway *v1alpha3.Gateway) (result *v1alpha3.Gateway, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(gatewaysResource, c.ns, gateway), &v1alpha3.Gateway{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.Gateway), err
|
||||
}
|
||||
|
||||
// Delete takes name of the gateway and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeGateways) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(gatewaysResource, c.ns, name), &v1alpha3.Gateway{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeGateways) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(gatewaysResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha3.GatewayList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched gateway.
|
||||
func (c *FakeGateways) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha3.Gateway, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(gatewaysResource, c.ns, name, data, subresources...), &v1alpha3.Gateway{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.Gateway), err
|
||||
}
|
||||
48
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_istio_client.go
generated
vendored
Normal file
48
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_istio_client.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha3 "github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeNetworkingV1alpha3 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeNetworkingV1alpha3) DestinationRules(namespace string) v1alpha3.DestinationRuleInterface {
|
||||
return &FakeDestinationRules{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeNetworkingV1alpha3) Gateways(namespace string) v1alpha3.GatewayInterface {
|
||||
return &FakeGateways{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeNetworkingV1alpha3) VirtualServices(namespace string) v1alpha3.VirtualServiceInterface {
|
||||
return &FakeVirtualServices{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeNetworkingV1alpha3) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_virtualservice.go
generated
vendored
Normal file
128
vendor/github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake/fake_virtualservice.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2018 The Knative 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeVirtualServices implements VirtualServiceInterface
|
||||
type FakeVirtualServices struct {
|
||||
Fake *FakeNetworkingV1alpha3
|
||||
ns string
|
||||
}
|
||||
|
||||
var virtualservicesResource = schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1alpha3", Resource: "virtualservices"}
|
||||
|
||||
var virtualservicesKind = schema.GroupVersionKind{Group: "networking.istio.io", Version: "v1alpha3", Kind: "VirtualService"}
|
||||
|
||||
// Get takes name of the virtualService, and returns the corresponding virtualService object, and an error if there is any.
|
||||
func (c *FakeVirtualServices) Get(name string, options v1.GetOptions) (result *v1alpha3.VirtualService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(virtualservicesResource, c.ns, name), &v1alpha3.VirtualService{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.VirtualService), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of VirtualServices that match those selectors.
|
||||
func (c *FakeVirtualServices) List(opts v1.ListOptions) (result *v1alpha3.VirtualServiceList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(virtualservicesResource, virtualservicesKind, c.ns, opts), &v1alpha3.VirtualServiceList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha3.VirtualServiceList{ListMeta: obj.(*v1alpha3.VirtualServiceList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha3.VirtualServiceList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested virtualServices.
|
||||
func (c *FakeVirtualServices) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(virtualservicesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a virtualService and creates it. Returns the server's representation of the virtualService, and an error, if there is any.
|
||||
func (c *FakeVirtualServices) Create(virtualService *v1alpha3.VirtualService) (result *v1alpha3.VirtualService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(virtualservicesResource, c.ns, virtualService), &v1alpha3.VirtualService{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.VirtualService), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a virtualService and updates it. Returns the server's representation of the virtualService, and an error, if there is any.
|
||||
func (c *FakeVirtualServices) Update(virtualService *v1alpha3.VirtualService) (result *v1alpha3.VirtualService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(virtualservicesResource, c.ns, virtualService), &v1alpha3.VirtualService{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.VirtualService), err
|
||||
}
|
||||
|
||||
// Delete takes name of the virtualService and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeVirtualServices) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(virtualservicesResource, c.ns, name), &v1alpha3.VirtualService{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeVirtualServices) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(virtualservicesResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha3.VirtualServiceList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched virtualService.
|
||||
func (c *FakeVirtualServices) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha3.VirtualService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(virtualservicesResource, c.ns, name, data, subresources...), &v1alpha3.VirtualService{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.VirtualService), err
|
||||
}
|
||||
353
vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go
generated
vendored
Normal file
353
vendor/k8s.io/client-go/kubernetes/fake/clientset_generated.go
generated
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
admissionregistrationv1alpha1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1"
|
||||
fakeadmissionregistrationv1alpha1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake"
|
||||
admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
|
||||
fakeadmissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake"
|
||||
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
fakeappsv1 "k8s.io/client-go/kubernetes/typed/apps/v1/fake"
|
||||
appsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
|
||||
fakeappsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake"
|
||||
appsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2"
|
||||
fakeappsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2/fake"
|
||||
authenticationv1 "k8s.io/client-go/kubernetes/typed/authentication/v1"
|
||||
fakeauthenticationv1 "k8s.io/client-go/kubernetes/typed/authentication/v1/fake"
|
||||
authenticationv1beta1 "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
|
||||
fakeauthenticationv1beta1 "k8s.io/client-go/kubernetes/typed/authentication/v1beta1/fake"
|
||||
authorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
|
||||
fakeauthorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1/fake"
|
||||
authorizationv1beta1 "k8s.io/client-go/kubernetes/typed/authorization/v1beta1"
|
||||
fakeauthorizationv1beta1 "k8s.io/client-go/kubernetes/typed/authorization/v1beta1/fake"
|
||||
autoscalingv1 "k8s.io/client-go/kubernetes/typed/autoscaling/v1"
|
||||
fakeautoscalingv1 "k8s.io/client-go/kubernetes/typed/autoscaling/v1/fake"
|
||||
autoscalingv2beta1 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1"
|
||||
fakeautoscalingv2beta1 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1/fake"
|
||||
batchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
|
||||
fakebatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1/fake"
|
||||
batchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1"
|
||||
fakebatchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake"
|
||||
batchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1"
|
||||
fakebatchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake"
|
||||
certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
|
||||
fakecertificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake"
|
||||
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
fakecorev1 "k8s.io/client-go/kubernetes/typed/core/v1/fake"
|
||||
eventsv1beta1 "k8s.io/client-go/kubernetes/typed/events/v1beta1"
|
||||
fakeeventsv1beta1 "k8s.io/client-go/kubernetes/typed/events/v1beta1/fake"
|
||||
extensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
|
||||
fakeextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1/fake"
|
||||
networkingv1 "k8s.io/client-go/kubernetes/typed/networking/v1"
|
||||
fakenetworkingv1 "k8s.io/client-go/kubernetes/typed/networking/v1/fake"
|
||||
policyv1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
|
||||
fakepolicyv1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake"
|
||||
rbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||
fakerbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1/fake"
|
||||
rbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1"
|
||||
fakerbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake"
|
||||
rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1"
|
||||
fakerbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake"
|
||||
schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
|
||||
fakeschedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake"
|
||||
schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
|
||||
fakeschedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake"
|
||||
settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1"
|
||||
fakesettingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake"
|
||||
storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1"
|
||||
fakestoragev1 "k8s.io/client-go/kubernetes/typed/storage/v1/fake"
|
||||
storagev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
|
||||
fakestoragev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake"
|
||||
storagev1beta1 "k8s.io/client-go/kubernetes/typed/storage/v1beta1"
|
||||
fakestoragev1beta1 "k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// AdmissionregistrationV1alpha1 retrieves the AdmissionregistrationV1alpha1Client
|
||||
func (c *Clientset) AdmissionregistrationV1alpha1() admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface {
|
||||
return &fakeadmissionregistrationv1alpha1.FakeAdmissionregistrationV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AdmissionregistrationV1beta1 retrieves the AdmissionregistrationV1beta1Client
|
||||
func (c *Clientset) AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface {
|
||||
return &fakeadmissionregistrationv1beta1.FakeAdmissionregistrationV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Admissionregistration retrieves the AdmissionregistrationV1beta1Client
|
||||
func (c *Clientset) Admissionregistration() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface {
|
||||
return &fakeadmissionregistrationv1beta1.FakeAdmissionregistrationV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AppsV1beta1 retrieves the AppsV1beta1Client
|
||||
func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface {
|
||||
return &fakeappsv1beta1.FakeAppsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AppsV1beta2 retrieves the AppsV1beta2Client
|
||||
func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface {
|
||||
return &fakeappsv1beta2.FakeAppsV1beta2{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AppsV1 retrieves the AppsV1Client
|
||||
func (c *Clientset) AppsV1() appsv1.AppsV1Interface {
|
||||
return &fakeappsv1.FakeAppsV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Apps retrieves the AppsV1Client
|
||||
func (c *Clientset) Apps() appsv1.AppsV1Interface {
|
||||
return &fakeappsv1.FakeAppsV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AuthenticationV1 retrieves the AuthenticationV1Client
|
||||
func (c *Clientset) AuthenticationV1() authenticationv1.AuthenticationV1Interface {
|
||||
return &fakeauthenticationv1.FakeAuthenticationV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Authentication retrieves the AuthenticationV1Client
|
||||
func (c *Clientset) Authentication() authenticationv1.AuthenticationV1Interface {
|
||||
return &fakeauthenticationv1.FakeAuthenticationV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AuthenticationV1beta1 retrieves the AuthenticationV1beta1Client
|
||||
func (c *Clientset) AuthenticationV1beta1() authenticationv1beta1.AuthenticationV1beta1Interface {
|
||||
return &fakeauthenticationv1beta1.FakeAuthenticationV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AuthorizationV1 retrieves the AuthorizationV1Client
|
||||
func (c *Clientset) AuthorizationV1() authorizationv1.AuthorizationV1Interface {
|
||||
return &fakeauthorizationv1.FakeAuthorizationV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Authorization retrieves the AuthorizationV1Client
|
||||
func (c *Clientset) Authorization() authorizationv1.AuthorizationV1Interface {
|
||||
return &fakeauthorizationv1.FakeAuthorizationV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AuthorizationV1beta1 retrieves the AuthorizationV1beta1Client
|
||||
func (c *Clientset) AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface {
|
||||
return &fakeauthorizationv1beta1.FakeAuthorizationV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AutoscalingV1 retrieves the AutoscalingV1Client
|
||||
func (c *Clientset) AutoscalingV1() autoscalingv1.AutoscalingV1Interface {
|
||||
return &fakeautoscalingv1.FakeAutoscalingV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Autoscaling retrieves the AutoscalingV1Client
|
||||
func (c *Clientset) Autoscaling() autoscalingv1.AutoscalingV1Interface {
|
||||
return &fakeautoscalingv1.FakeAutoscalingV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AutoscalingV2beta1 retrieves the AutoscalingV2beta1Client
|
||||
func (c *Clientset) AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface {
|
||||
return &fakeautoscalingv2beta1.FakeAutoscalingV2beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// BatchV1 retrieves the BatchV1Client
|
||||
func (c *Clientset) BatchV1() batchv1.BatchV1Interface {
|
||||
return &fakebatchv1.FakeBatchV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Batch retrieves the BatchV1Client
|
||||
func (c *Clientset) Batch() batchv1.BatchV1Interface {
|
||||
return &fakebatchv1.FakeBatchV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// BatchV1beta1 retrieves the BatchV1beta1Client
|
||||
func (c *Clientset) BatchV1beta1() batchv1beta1.BatchV1beta1Interface {
|
||||
return &fakebatchv1beta1.FakeBatchV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// BatchV2alpha1 retrieves the BatchV2alpha1Client
|
||||
func (c *Clientset) BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface {
|
||||
return &fakebatchv2alpha1.FakeBatchV2alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// CertificatesV1beta1 retrieves the CertificatesV1beta1Client
|
||||
func (c *Clientset) CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface {
|
||||
return &fakecertificatesv1beta1.FakeCertificatesV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Certificates retrieves the CertificatesV1beta1Client
|
||||
func (c *Clientset) Certificates() certificatesv1beta1.CertificatesV1beta1Interface {
|
||||
return &fakecertificatesv1beta1.FakeCertificatesV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// CoreV1 retrieves the CoreV1Client
|
||||
func (c *Clientset) CoreV1() corev1.CoreV1Interface {
|
||||
return &fakecorev1.FakeCoreV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Core retrieves the CoreV1Client
|
||||
func (c *Clientset) Core() corev1.CoreV1Interface {
|
||||
return &fakecorev1.FakeCoreV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// EventsV1beta1 retrieves the EventsV1beta1Client
|
||||
func (c *Clientset) EventsV1beta1() eventsv1beta1.EventsV1beta1Interface {
|
||||
return &fakeeventsv1beta1.FakeEventsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Events retrieves the EventsV1beta1Client
|
||||
func (c *Clientset) Events() eventsv1beta1.EventsV1beta1Interface {
|
||||
return &fakeeventsv1beta1.FakeEventsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// ExtensionsV1beta1 retrieves the ExtensionsV1beta1Client
|
||||
func (c *Clientset) ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface {
|
||||
return &fakeextensionsv1beta1.FakeExtensionsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Extensions retrieves the ExtensionsV1beta1Client
|
||||
func (c *Clientset) Extensions() extensionsv1beta1.ExtensionsV1beta1Interface {
|
||||
return &fakeextensionsv1beta1.FakeExtensionsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// NetworkingV1 retrieves the NetworkingV1Client
|
||||
func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface {
|
||||
return &fakenetworkingv1.FakeNetworkingV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Networking retrieves the NetworkingV1Client
|
||||
func (c *Clientset) Networking() networkingv1.NetworkingV1Interface {
|
||||
return &fakenetworkingv1.FakeNetworkingV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// PolicyV1beta1 retrieves the PolicyV1beta1Client
|
||||
func (c *Clientset) PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface {
|
||||
return &fakepolicyv1beta1.FakePolicyV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Policy retrieves the PolicyV1beta1Client
|
||||
func (c *Clientset) Policy() policyv1beta1.PolicyV1beta1Interface {
|
||||
return &fakepolicyv1beta1.FakePolicyV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// RbacV1 retrieves the RbacV1Client
|
||||
func (c *Clientset) RbacV1() rbacv1.RbacV1Interface {
|
||||
return &fakerbacv1.FakeRbacV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Rbac retrieves the RbacV1Client
|
||||
func (c *Clientset) Rbac() rbacv1.RbacV1Interface {
|
||||
return &fakerbacv1.FakeRbacV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// RbacV1beta1 retrieves the RbacV1beta1Client
|
||||
func (c *Clientset) RbacV1beta1() rbacv1beta1.RbacV1beta1Interface {
|
||||
return &fakerbacv1beta1.FakeRbacV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// RbacV1alpha1 retrieves the RbacV1alpha1Client
|
||||
func (c *Clientset) RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface {
|
||||
return &fakerbacv1alpha1.FakeRbacV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// SchedulingV1alpha1 retrieves the SchedulingV1alpha1Client
|
||||
func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface {
|
||||
return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// SchedulingV1beta1 retrieves the SchedulingV1beta1Client
|
||||
func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface {
|
||||
return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Scheduling retrieves the SchedulingV1beta1Client
|
||||
func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface {
|
||||
return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// SettingsV1alpha1 retrieves the SettingsV1alpha1Client
|
||||
func (c *Clientset) SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface {
|
||||
return &fakesettingsv1alpha1.FakeSettingsV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Settings retrieves the SettingsV1alpha1Client
|
||||
func (c *Clientset) Settings() settingsv1alpha1.SettingsV1alpha1Interface {
|
||||
return &fakesettingsv1alpha1.FakeSettingsV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// StorageV1beta1 retrieves the StorageV1beta1Client
|
||||
func (c *Clientset) StorageV1beta1() storagev1beta1.StorageV1beta1Interface {
|
||||
return &fakestoragev1beta1.FakeStorageV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// StorageV1 retrieves the StorageV1Client
|
||||
func (c *Clientset) StorageV1() storagev1.StorageV1Interface {
|
||||
return &fakestoragev1.FakeStorageV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Storage retrieves the StorageV1Client
|
||||
func (c *Clientset) Storage() storagev1.StorageV1Interface {
|
||||
return &fakestoragev1.FakeStorageV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// StorageV1alpha1 retrieves the StorageV1alpha1Client
|
||||
func (c *Clientset) StorageV1alpha1() storagev1alpha1.StorageV1alpha1Interface {
|
||||
return &fakestoragev1alpha1.FakeStorageV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
20
vendor/k8s.io/client-go/kubernetes/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/client-go/kubernetes/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
110
vendor/k8s.io/client-go/kubernetes/fake/register.go
generated
vendored
Normal file
110
vendor/k8s.io/client-go/kubernetes/fake/register.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
authenticationv1beta1 "k8s.io/api/authentication/v1beta1"
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
authorizationv1beta1 "k8s.io/api/authorization/v1beta1"
|
||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
||||
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
|
||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
eventsv1beta1 "k8s.io/api/events/v1beta1"
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
policyv1beta1 "k8s.io/api/policy/v1beta1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
rbacv1alpha1 "k8s.io/api/rbac/v1alpha1"
|
||||
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
|
||||
schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1"
|
||||
schedulingv1beta1 "k8s.io/api/scheduling/v1beta1"
|
||||
settingsv1alpha1 "k8s.io/api/settings/v1alpha1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
storagev1alpha1 "k8s.io/api/storage/v1alpha1"
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(scheme)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
admissionregistrationv1alpha1.AddToScheme(scheme)
|
||||
admissionregistrationv1beta1.AddToScheme(scheme)
|
||||
appsv1beta1.AddToScheme(scheme)
|
||||
appsv1beta2.AddToScheme(scheme)
|
||||
appsv1.AddToScheme(scheme)
|
||||
authenticationv1.AddToScheme(scheme)
|
||||
authenticationv1beta1.AddToScheme(scheme)
|
||||
authorizationv1.AddToScheme(scheme)
|
||||
authorizationv1beta1.AddToScheme(scheme)
|
||||
autoscalingv1.AddToScheme(scheme)
|
||||
autoscalingv2beta1.AddToScheme(scheme)
|
||||
batchv1.AddToScheme(scheme)
|
||||
batchv1beta1.AddToScheme(scheme)
|
||||
batchv2alpha1.AddToScheme(scheme)
|
||||
certificatesv1beta1.AddToScheme(scheme)
|
||||
corev1.AddToScheme(scheme)
|
||||
eventsv1beta1.AddToScheme(scheme)
|
||||
extensionsv1beta1.AddToScheme(scheme)
|
||||
networkingv1.AddToScheme(scheme)
|
||||
policyv1beta1.AddToScheme(scheme)
|
||||
rbacv1.AddToScheme(scheme)
|
||||
rbacv1beta1.AddToScheme(scheme)
|
||||
rbacv1alpha1.AddToScheme(scheme)
|
||||
schedulingv1alpha1.AddToScheme(scheme)
|
||||
schedulingv1beta1.AddToScheme(scheme)
|
||||
settingsv1alpha1.AddToScheme(scheme)
|
||||
storagev1beta1.AddToScheme(scheme)
|
||||
storagev1.AddToScheme(scheme)
|
||||
storagev1alpha1.AddToScheme(scheme)
|
||||
}
|
||||
20
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
40
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go
generated
vendored
Normal file
40
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_admissionregistration_client.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeAdmissionregistrationV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAdmissionregistrationV1alpha1) InitializerConfigurations() v1alpha1.InitializerConfigurationInterface {
|
||||
return &FakeInitializerConfigurations{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeAdmissionregistrationV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
120
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go
generated
vendored
Normal file
120
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeInitializerConfigurations implements InitializerConfigurationInterface
|
||||
type FakeInitializerConfigurations struct {
|
||||
Fake *FakeAdmissionregistrationV1alpha1
|
||||
}
|
||||
|
||||
var initializerconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Resource: "initializerconfigurations"}
|
||||
|
||||
var initializerconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "InitializerConfiguration"}
|
||||
|
||||
// Get takes name of the initializerConfiguration, and returns the corresponding initializerConfiguration object, and an error if there is any.
|
||||
func (c *FakeInitializerConfigurations) Get(name string, options v1.GetOptions) (result *v1alpha1.InitializerConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(initializerconfigurationsResource, name), &v1alpha1.InitializerConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.InitializerConfiguration), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of InitializerConfigurations that match those selectors.
|
||||
func (c *FakeInitializerConfigurations) List(opts v1.ListOptions) (result *v1alpha1.InitializerConfigurationList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(initializerconfigurationsResource, initializerconfigurationsKind, opts), &v1alpha1.InitializerConfigurationList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.InitializerConfigurationList{ListMeta: obj.(*v1alpha1.InitializerConfigurationList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.InitializerConfigurationList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested initializerConfigurations.
|
||||
func (c *FakeInitializerConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(initializerconfigurationsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a initializerConfiguration and creates it. Returns the server's representation of the initializerConfiguration, and an error, if there is any.
|
||||
func (c *FakeInitializerConfigurations) Create(initializerConfiguration *v1alpha1.InitializerConfiguration) (result *v1alpha1.InitializerConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(initializerconfigurationsResource, initializerConfiguration), &v1alpha1.InitializerConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.InitializerConfiguration), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a initializerConfiguration and updates it. Returns the server's representation of the initializerConfiguration, and an error, if there is any.
|
||||
func (c *FakeInitializerConfigurations) Update(initializerConfiguration *v1alpha1.InitializerConfiguration) (result *v1alpha1.InitializerConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(initializerconfigurationsResource, initializerConfiguration), &v1alpha1.InitializerConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.InitializerConfiguration), err
|
||||
}
|
||||
|
||||
// Delete takes name of the initializerConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeInitializerConfigurations) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(initializerconfigurationsResource, name), &v1alpha1.InitializerConfiguration{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeInitializerConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(initializerconfigurationsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.InitializerConfigurationList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched initializerConfiguration.
|
||||
func (c *FakeInitializerConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.InitializerConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(initializerconfigurationsResource, name, data, subresources...), &v1alpha1.InitializerConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.InitializerConfiguration), err
|
||||
}
|
||||
20
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
44
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go
generated
vendored
Normal file
44
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_admissionregistration_client.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeAdmissionregistrationV1beta1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAdmissionregistrationV1beta1) MutatingWebhookConfigurations() v1beta1.MutatingWebhookConfigurationInterface {
|
||||
return &FakeMutatingWebhookConfigurations{c}
|
||||
}
|
||||
|
||||
func (c *FakeAdmissionregistrationV1beta1) ValidatingWebhookConfigurations() v1beta1.ValidatingWebhookConfigurationInterface {
|
||||
return &FakeValidatingWebhookConfigurations{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeAdmissionregistrationV1beta1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
120
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go
generated
vendored
Normal file
120
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeMutatingWebhookConfigurations implements MutatingWebhookConfigurationInterface
|
||||
type FakeMutatingWebhookConfigurations struct {
|
||||
Fake *FakeAdmissionregistrationV1beta1
|
||||
}
|
||||
|
||||
var mutatingwebhookconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "mutatingwebhookconfigurations"}
|
||||
|
||||
var mutatingwebhookconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "MutatingWebhookConfiguration"}
|
||||
|
||||
// Get takes name of the mutatingWebhookConfiguration, and returns the corresponding mutatingWebhookConfiguration object, and an error if there is any.
|
||||
func (c *FakeMutatingWebhookConfigurations) Get(name string, options v1.GetOptions) (result *v1beta1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(mutatingwebhookconfigurationsResource, name), &v1beta1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of MutatingWebhookConfigurations that match those selectors.
|
||||
func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *v1beta1.MutatingWebhookConfigurationList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(mutatingwebhookconfigurationsResource, mutatingwebhookconfigurationsKind, opts), &v1beta1.MutatingWebhookConfigurationList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.MutatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.MutatingWebhookConfigurationList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.MutatingWebhookConfigurationList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested mutatingWebhookConfigurations.
|
||||
func (c *FakeMutatingWebhookConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(mutatingwebhookconfigurationsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a mutatingWebhookConfiguration and creates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeMutatingWebhookConfigurations) Create(mutatingWebhookConfiguration *v1beta1.MutatingWebhookConfiguration) (result *v1beta1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(mutatingwebhookconfigurationsResource, mutatingWebhookConfiguration), &v1beta1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a mutatingWebhookConfiguration and updates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeMutatingWebhookConfigurations) Update(mutatingWebhookConfiguration *v1beta1.MutatingWebhookConfiguration) (result *v1beta1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(mutatingwebhookconfigurationsResource, mutatingWebhookConfiguration), &v1beta1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Delete takes name of the mutatingWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeMutatingWebhookConfigurations) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(mutatingwebhookconfigurationsResource, name), &v1beta1.MutatingWebhookConfiguration{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeMutatingWebhookConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(mutatingwebhookconfigurationsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.MutatingWebhookConfigurationList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched mutatingWebhookConfiguration.
|
||||
func (c *FakeMutatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(mutatingwebhookconfigurationsResource, name, data, subresources...), &v1beta1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
120
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go
generated
vendored
Normal file
120
vendor/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeValidatingWebhookConfigurations implements ValidatingWebhookConfigurationInterface
|
||||
type FakeValidatingWebhookConfigurations struct {
|
||||
Fake *FakeAdmissionregistrationV1beta1
|
||||
}
|
||||
|
||||
var validatingwebhookconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "validatingwebhookconfigurations"}
|
||||
|
||||
var validatingwebhookconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "ValidatingWebhookConfiguration"}
|
||||
|
||||
// Get takes name of the validatingWebhookConfiguration, and returns the corresponding validatingWebhookConfiguration object, and an error if there is any.
|
||||
func (c *FakeValidatingWebhookConfigurations) Get(name string, options v1.GetOptions) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(validatingwebhookconfigurationsResource, name), &v1beta1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ValidatingWebhookConfigurations that match those selectors.
|
||||
func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result *v1beta1.ValidatingWebhookConfigurationList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(validatingwebhookconfigurationsResource, validatingwebhookconfigurationsKind, opts), &v1beta1.ValidatingWebhookConfigurationList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.ValidatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.ValidatingWebhookConfigurationList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.ValidatingWebhookConfigurationList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested validatingWebhookConfigurations.
|
||||
func (c *FakeValidatingWebhookConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(validatingwebhookconfigurationsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a validatingWebhookConfiguration and creates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeValidatingWebhookConfigurations) Create(validatingWebhookConfiguration *v1beta1.ValidatingWebhookConfiguration) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(validatingwebhookconfigurationsResource, validatingWebhookConfiguration), &v1beta1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a validatingWebhookConfiguration and updates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeValidatingWebhookConfigurations) Update(validatingWebhookConfiguration *v1beta1.ValidatingWebhookConfiguration) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(validatingwebhookconfigurationsResource, validatingWebhookConfiguration), &v1beta1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Delete takes name of the validatingWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeValidatingWebhookConfigurations) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(validatingwebhookconfigurationsResource, name), &v1beta1.ValidatingWebhookConfiguration{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeValidatingWebhookConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(validatingwebhookconfigurationsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.ValidatingWebhookConfigurationList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched validatingWebhookConfiguration.
|
||||
func (c *FakeValidatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(validatingwebhookconfigurationsResource, name, data, subresources...), &v1beta1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
20
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
56
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go
generated
vendored
Normal file
56
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_apps_client.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeAppsV1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1) ControllerRevisions(namespace string) v1.ControllerRevisionInterface {
|
||||
return &FakeControllerRevisions{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1) DaemonSets(namespace string) v1.DaemonSetInterface {
|
||||
return &FakeDaemonSets{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1) Deployments(namespace string) v1.DeploymentInterface {
|
||||
return &FakeDeployments{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1) ReplicaSets(namespace string) v1.ReplicaSetInterface {
|
||||
return &FakeReplicaSets{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1) StatefulSets(namespace string) v1.StatefulSetInterface {
|
||||
return &FakeStatefulSets{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeAppsV1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
128
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go
generated
vendored
Normal file
128
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeControllerRevisions implements ControllerRevisionInterface
|
||||
type FakeControllerRevisions struct {
|
||||
Fake *FakeAppsV1
|
||||
ns string
|
||||
}
|
||||
|
||||
var controllerrevisionsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "controllerrevisions"}
|
||||
|
||||
var controllerrevisionsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ControllerRevision"}
|
||||
|
||||
// Get takes name of the controllerRevision, and returns the corresponding controllerRevision object, and an error if there is any.
|
||||
func (c *FakeControllerRevisions) Get(name string, options v1.GetOptions) (result *apps_v1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(controllerrevisionsResource, c.ns, name), &apps_v1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ControllerRevision), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ControllerRevisions that match those selectors.
|
||||
func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *apps_v1.ControllerRevisionList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(controllerrevisionsResource, controllerrevisionsKind, c.ns, opts), &apps_v1.ControllerRevisionList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apps_v1.ControllerRevisionList{ListMeta: obj.(*apps_v1.ControllerRevisionList).ListMeta}
|
||||
for _, item := range obj.(*apps_v1.ControllerRevisionList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested controllerRevisions.
|
||||
func (c *FakeControllerRevisions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(controllerrevisionsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a controllerRevision and creates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
|
||||
func (c *FakeControllerRevisions) Create(controllerRevision *apps_v1.ControllerRevision) (result *apps_v1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(controllerrevisionsResource, c.ns, controllerRevision), &apps_v1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ControllerRevision), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a controllerRevision and updates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
|
||||
func (c *FakeControllerRevisions) Update(controllerRevision *apps_v1.ControllerRevision) (result *apps_v1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(controllerrevisionsResource, c.ns, controllerRevision), &apps_v1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ControllerRevision), err
|
||||
}
|
||||
|
||||
// Delete takes name of the controllerRevision and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeControllerRevisions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(controllerrevisionsResource, c.ns, name), &apps_v1.ControllerRevision{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(controllerrevisionsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apps_v1.ControllerRevisionList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched controllerRevision.
|
||||
func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apps_v1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, data, subresources...), &apps_v1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ControllerRevision), err
|
||||
}
|
||||
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go
generated
vendored
Normal file
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_daemonset.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeDaemonSets implements DaemonSetInterface
|
||||
type FakeDaemonSets struct {
|
||||
Fake *FakeAppsV1
|
||||
ns string
|
||||
}
|
||||
|
||||
var daemonsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}
|
||||
|
||||
var daemonsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "DaemonSet"}
|
||||
|
||||
// Get takes name of the daemonSet, and returns the corresponding daemonSet object, and an error if there is any.
|
||||
func (c *FakeDaemonSets) Get(name string, options v1.GetOptions) (result *apps_v1.DaemonSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(daemonsetsResource, c.ns, name), &apps_v1.DaemonSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.DaemonSet), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of DaemonSets that match those selectors.
|
||||
func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *apps_v1.DaemonSetList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(daemonsetsResource, daemonsetsKind, c.ns, opts), &apps_v1.DaemonSetList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apps_v1.DaemonSetList{ListMeta: obj.(*apps_v1.DaemonSetList).ListMeta}
|
||||
for _, item := range obj.(*apps_v1.DaemonSetList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested daemonSets.
|
||||
func (c *FakeDaemonSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(daemonsetsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a daemonSet and creates it. Returns the server's representation of the daemonSet, and an error, if there is any.
|
||||
func (c *FakeDaemonSets) Create(daemonSet *apps_v1.DaemonSet) (result *apps_v1.DaemonSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(daemonsetsResource, c.ns, daemonSet), &apps_v1.DaemonSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.DaemonSet), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a daemonSet and updates it. Returns the server's representation of the daemonSet, and an error, if there is any.
|
||||
func (c *FakeDaemonSets) Update(daemonSet *apps_v1.DaemonSet) (result *apps_v1.DaemonSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(daemonsetsResource, c.ns, daemonSet), &apps_v1.DaemonSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.DaemonSet), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeDaemonSets) UpdateStatus(daemonSet *apps_v1.DaemonSet) (*apps_v1.DaemonSet, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(daemonsetsResource, "status", c.ns, daemonSet), &apps_v1.DaemonSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.DaemonSet), err
|
||||
}
|
||||
|
||||
// Delete takes name of the daemonSet and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeDaemonSets) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(daemonsetsResource, c.ns, name), &apps_v1.DaemonSet{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(daemonsetsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apps_v1.DaemonSetList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched daemonSet.
|
||||
func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apps_v1.DaemonSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, data, subresources...), &apps_v1.DaemonSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.DaemonSet), err
|
||||
}
|
||||
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go
generated
vendored
Normal file
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_deployment.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeDeployments implements DeploymentInterface
|
||||
type FakeDeployments struct {
|
||||
Fake *FakeAppsV1
|
||||
ns string
|
||||
}
|
||||
|
||||
var deploymentsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
|
||||
|
||||
var deploymentsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}
|
||||
|
||||
// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.
|
||||
func (c *FakeDeployments) Get(name string, options v1.GetOptions) (result *apps_v1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(deploymentsResource, c.ns, name), &apps_v1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.Deployment), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Deployments that match those selectors.
|
||||
func (c *FakeDeployments) List(opts v1.ListOptions) (result *apps_v1.DeploymentList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(deploymentsResource, deploymentsKind, c.ns, opts), &apps_v1.DeploymentList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apps_v1.DeploymentList{ListMeta: obj.(*apps_v1.DeploymentList).ListMeta}
|
||||
for _, item := range obj.(*apps_v1.DeploymentList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested deployments.
|
||||
func (c *FakeDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(deploymentsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a deployment and creates it. Returns the server's representation of the deployment, and an error, if there is any.
|
||||
func (c *FakeDeployments) Create(deployment *apps_v1.Deployment) (result *apps_v1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(deploymentsResource, c.ns, deployment), &apps_v1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.Deployment), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a deployment and updates it. Returns the server's representation of the deployment, and an error, if there is any.
|
||||
func (c *FakeDeployments) Update(deployment *apps_v1.Deployment) (result *apps_v1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(deploymentsResource, c.ns, deployment), &apps_v1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.Deployment), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeDeployments) UpdateStatus(deployment *apps_v1.Deployment) (*apps_v1.Deployment, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &apps_v1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.Deployment), err
|
||||
}
|
||||
|
||||
// Delete takes name of the deployment and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeDeployments) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(deploymentsResource, c.ns, name), &apps_v1.Deployment{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apps_v1.DeploymentList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched deployment.
|
||||
func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apps_v1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, data, subresources...), &apps_v1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.Deployment), err
|
||||
}
|
||||
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go
generated
vendored
Normal file
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_replicaset.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeReplicaSets implements ReplicaSetInterface
|
||||
type FakeReplicaSets struct {
|
||||
Fake *FakeAppsV1
|
||||
ns string
|
||||
}
|
||||
|
||||
var replicasetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "replicasets"}
|
||||
|
||||
var replicasetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ReplicaSet"}
|
||||
|
||||
// Get takes name of the replicaSet, and returns the corresponding replicaSet object, and an error if there is any.
|
||||
func (c *FakeReplicaSets) Get(name string, options v1.GetOptions) (result *apps_v1.ReplicaSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(replicasetsResource, c.ns, name), &apps_v1.ReplicaSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ReplicaSet), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ReplicaSets that match those selectors.
|
||||
func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *apps_v1.ReplicaSetList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(replicasetsResource, replicasetsKind, c.ns, opts), &apps_v1.ReplicaSetList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apps_v1.ReplicaSetList{ListMeta: obj.(*apps_v1.ReplicaSetList).ListMeta}
|
||||
for _, item := range obj.(*apps_v1.ReplicaSetList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested replicaSets.
|
||||
func (c *FakeReplicaSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(replicasetsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a replicaSet and creates it. Returns the server's representation of the replicaSet, and an error, if there is any.
|
||||
func (c *FakeReplicaSets) Create(replicaSet *apps_v1.ReplicaSet) (result *apps_v1.ReplicaSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(replicasetsResource, c.ns, replicaSet), &apps_v1.ReplicaSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ReplicaSet), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a replicaSet and updates it. Returns the server's representation of the replicaSet, and an error, if there is any.
|
||||
func (c *FakeReplicaSets) Update(replicaSet *apps_v1.ReplicaSet) (result *apps_v1.ReplicaSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(replicasetsResource, c.ns, replicaSet), &apps_v1.ReplicaSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ReplicaSet), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeReplicaSets) UpdateStatus(replicaSet *apps_v1.ReplicaSet) (*apps_v1.ReplicaSet, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(replicasetsResource, "status", c.ns, replicaSet), &apps_v1.ReplicaSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ReplicaSet), err
|
||||
}
|
||||
|
||||
// Delete takes name of the replicaSet and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeReplicaSets) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(replicasetsResource, c.ns, name), &apps_v1.ReplicaSet{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(replicasetsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apps_v1.ReplicaSetList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched replicaSet.
|
||||
func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apps_v1.ReplicaSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, data, subresources...), &apps_v1.ReplicaSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.ReplicaSet), err
|
||||
}
|
||||
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go
generated
vendored
Normal file
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1/fake/fake_statefulset.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeStatefulSets implements StatefulSetInterface
|
||||
type FakeStatefulSets struct {
|
||||
Fake *FakeAppsV1
|
||||
ns string
|
||||
}
|
||||
|
||||
var statefulsetsResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"}
|
||||
|
||||
var statefulsetsKind = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"}
|
||||
|
||||
// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
|
||||
func (c *FakeStatefulSets) Get(name string, options v1.GetOptions) (result *apps_v1.StatefulSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(statefulsetsResource, c.ns, name), &apps_v1.StatefulSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.StatefulSet), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
|
||||
func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *apps_v1.StatefulSetList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(statefulsetsResource, statefulsetsKind, c.ns, opts), &apps_v1.StatefulSetList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apps_v1.StatefulSetList{ListMeta: obj.(*apps_v1.StatefulSetList).ListMeta}
|
||||
for _, item := range obj.(*apps_v1.StatefulSetList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested statefulSets.
|
||||
func (c *FakeStatefulSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(statefulsetsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a statefulSet and creates it. Returns the server's representation of the statefulSet, and an error, if there is any.
|
||||
func (c *FakeStatefulSets) Create(statefulSet *apps_v1.StatefulSet) (result *apps_v1.StatefulSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(statefulsetsResource, c.ns, statefulSet), &apps_v1.StatefulSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.StatefulSet), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a statefulSet and updates it. Returns the server's representation of the statefulSet, and an error, if there is any.
|
||||
func (c *FakeStatefulSets) Update(statefulSet *apps_v1.StatefulSet) (result *apps_v1.StatefulSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(statefulsetsResource, c.ns, statefulSet), &apps_v1.StatefulSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.StatefulSet), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeStatefulSets) UpdateStatus(statefulSet *apps_v1.StatefulSet) (*apps_v1.StatefulSet, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "status", c.ns, statefulSet), &apps_v1.StatefulSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.StatefulSet), err
|
||||
}
|
||||
|
||||
// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeStatefulSets) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(statefulsetsResource, c.ns, name), &apps_v1.StatefulSet{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(statefulsetsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apps_v1.StatefulSetList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched statefulSet.
|
||||
func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apps_v1.StatefulSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, data, subresources...), &apps_v1.StatefulSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apps_v1.StatefulSet), err
|
||||
}
|
||||
20
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
52
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go
generated
vendored
Normal file
52
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_apps_client.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeAppsV1beta1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1beta1) ControllerRevisions(namespace string) v1beta1.ControllerRevisionInterface {
|
||||
return &FakeControllerRevisions{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1beta1) Deployments(namespace string) v1beta1.DeploymentInterface {
|
||||
return &FakeDeployments{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1beta1) Scales(namespace string) v1beta1.ScaleInterface {
|
||||
return &FakeScales{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeAppsV1beta1) StatefulSets(namespace string) v1beta1.StatefulSetInterface {
|
||||
return &FakeStatefulSets{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeAppsV1beta1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
128
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go
generated
vendored
Normal file
128
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/api/apps/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeControllerRevisions implements ControllerRevisionInterface
|
||||
type FakeControllerRevisions struct {
|
||||
Fake *FakeAppsV1beta1
|
||||
ns string
|
||||
}
|
||||
|
||||
var controllerrevisionsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta1", Resource: "controllerrevisions"}
|
||||
|
||||
var controllerrevisionsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "ControllerRevision"}
|
||||
|
||||
// Get takes name of the controllerRevision, and returns the corresponding controllerRevision object, and an error if there is any.
|
||||
func (c *FakeControllerRevisions) Get(name string, options v1.GetOptions) (result *v1beta1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(controllerrevisionsResource, c.ns, name), &v1beta1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ControllerRevision), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ControllerRevisions that match those selectors.
|
||||
func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta1.ControllerRevisionList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(controllerrevisionsResource, controllerrevisionsKind, c.ns, opts), &v1beta1.ControllerRevisionList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.ControllerRevisionList{ListMeta: obj.(*v1beta1.ControllerRevisionList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.ControllerRevisionList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested controllerRevisions.
|
||||
func (c *FakeControllerRevisions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(controllerrevisionsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a controllerRevision and creates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
|
||||
func (c *FakeControllerRevisions) Create(controllerRevision *v1beta1.ControllerRevision) (result *v1beta1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(controllerrevisionsResource, c.ns, controllerRevision), &v1beta1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ControllerRevision), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a controllerRevision and updates it. Returns the server's representation of the controllerRevision, and an error, if there is any.
|
||||
func (c *FakeControllerRevisions) Update(controllerRevision *v1beta1.ControllerRevision) (result *v1beta1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(controllerrevisionsResource, c.ns, controllerRevision), &v1beta1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ControllerRevision), err
|
||||
}
|
||||
|
||||
// Delete takes name of the controllerRevision and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeControllerRevisions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(controllerrevisionsResource, c.ns, name), &v1beta1.ControllerRevision{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(controllerrevisionsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.ControllerRevisionList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched controllerRevision.
|
||||
func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ControllerRevision, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, data, subresources...), &v1beta1.ControllerRevision{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.ControllerRevision), err
|
||||
}
|
||||
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go
generated
vendored
Normal file
140
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/api/apps/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeDeployments implements DeploymentInterface
|
||||
type FakeDeployments struct {
|
||||
Fake *FakeAppsV1beta1
|
||||
ns string
|
||||
}
|
||||
|
||||
var deploymentsResource = schema.GroupVersionResource{Group: "apps", Version: "v1beta1", Resource: "deployments"}
|
||||
|
||||
var deploymentsKind = schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "Deployment"}
|
||||
|
||||
// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.
|
||||
func (c *FakeDeployments) Get(name string, options v1.GetOptions) (result *v1beta1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(deploymentsResource, c.ns, name), &v1beta1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Deployment), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Deployments that match those selectors.
|
||||
func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(deploymentsResource, deploymentsKind, c.ns, opts), &v1beta1.DeploymentList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.DeploymentList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested deployments.
|
||||
func (c *FakeDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(deploymentsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a deployment and creates it. Returns the server's representation of the deployment, and an error, if there is any.
|
||||
func (c *FakeDeployments) Create(deployment *v1beta1.Deployment) (result *v1beta1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(deploymentsResource, c.ns, deployment), &v1beta1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Deployment), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a deployment and updates it. Returns the server's representation of the deployment, and an error, if there is any.
|
||||
func (c *FakeDeployments) Update(deployment *v1beta1.Deployment) (result *v1beta1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(deploymentsResource, c.ns, deployment), &v1beta1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Deployment), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeDeployments) UpdateStatus(deployment *v1beta1.Deployment) (*v1beta1.Deployment, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &v1beta1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Deployment), err
|
||||
}
|
||||
|
||||
// Delete takes name of the deployment and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeDeployments) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(deploymentsResource, c.ns, name), &v1beta1.Deployment{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.DeploymentList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched deployment.
|
||||
func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Deployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, data, subresources...), &v1beta1.Deployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Deployment), err
|
||||
}
|
||||
25
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go
generated
vendored
Normal file
25
vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1/fake/fake_scale.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
// FakeScales implements ScaleInterface
|
||||
type FakeScales struct {
|
||||
Fake *FakeAppsV1beta1
|
||||
ns string
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user