Compare commits

...

49 Commits
0.5.1 ... 0.7.0

Author SHA1 Message Date
Stefan Prodan
1140af8dc7 Merge pull request #63 from stefanprodan/release-0.7.0
Release v0.7.0
2019-02-28 17:12:27 +02:00
stefanprodan
a2688c3910 Add link to custom metrics docs 2019-02-28 16:58:26 +02:00
stefanprodan
75b27ab3f3 Add change log for v0.7.0 2019-02-28 16:56:49 +02:00
stefanprodan
59d3f55fb2 Release v0.7.0 2019-02-28 16:05:48 +02:00
Stefan Prodan
f34739f334 Merge pull request #62 from stefanprodan/retries
Add timeout and retries
2019-02-28 15:36:46 +02:00
stefanprodan
90c71ec18f Update roadmap with alternatives to Istio 2019-02-28 15:09:24 +02:00
stefanprodan
395234d7c8 Add promql custom check to readme 2019-02-28 00:33:47 +02:00
stefanprodan
e322ba0065 Add timeout and retries to router 2019-02-28 00:05:40 +02:00
stefanprodan
6db8b96f72 Add timeout and retries example to docs 2019-02-28 00:02:48 +02:00
stefanprodan
44d7e96e96 Add timeout and retries fields to Canary CRD 2019-02-28 00:02:01 +02:00
Stefan Prodan
1662479c8d Merge pull request #60 from stefanprodan/custom-metrics
Add support for custom metrics
2019-02-27 23:31:05 +02:00
stefanprodan
2e351fcf0d Add a custom metric example to docs 2019-02-27 16:37:42 +02:00
stefanprodan
5d81876d07 Make the metric interval optional
- set default value to 1m
2019-02-27 16:03:56 +02:00
stefanprodan
c81e6989ec Add e2e tests for custom metrics 2019-02-27 15:49:09 +02:00
stefanprodan
4d61a896c3 Add custom promql queries support 2019-02-27 15:48:31 +02:00
stefanprodan
d148933ab3 Add metric query field to Canary CRD 2019-02-27 15:46:09 +02:00
Stefan Prodan
04a56a3591 Merge pull request #57 from stefanprodan/release-0.6.0
Release v0.6.0
2019-02-26 01:45:10 +02:00
stefanprodan
4a354e74d4 Update roadmap 2019-02-25 23:45:54 +02:00
stefanprodan
1e3e6427d5 Add link to virtual service docs 2019-02-25 23:22:49 +02:00
stefanprodan
38826108c8 Add changelog for v0.6.0 2019-02-25 23:01:35 +02:00
stefanprodan
4c4752f907 Release v0.6.0 2019-02-25 20:10:33 +02:00
Stefan Prodan
94dcd6c94d Merge pull request #55 from stefanprodan/http-match
Add HTTP match and rewrite to Canary service spec
2019-02-25 20:04:12 +02:00
stefanprodan
eabef3db30 Router improvements
- change virtual service route to canary service
- keep the existing destination weights on virtual service updates
- set the match conditions and URI rewrite when changing the traffic weight
2019-02-25 03:14:45 +02:00
stefanprodan
6750f10ffa Add HTTP match and rewrite docs 2019-02-25 03:07:39 +02:00
stefanprodan
56cb888cbf Add HTTP match and rewrite to virtual service 2019-02-25 00:08:06 +02:00
stefanprodan
b3e7fb3417 Add HTTP match and rewrite to Canary service spec 2019-02-25 00:06:14 +02:00
stefanprodan
2c6e1baca2 Update istio client 2019-02-25 00:05:09 +02:00
Stefan Prodan
c8358929d1 Merge pull request #54 from stefanprodan/vsvc
Refactor virtual service sync
2019-02-24 21:18:01 +02:00
stefanprodan
1dc7677dfb Add tests for virtual service sync 2019-02-24 19:58:01 +02:00
stefanprodan
8e699a7543 Detect changes in virtual service
- ignore destination weight when comparing the two specs
2019-02-24 18:25:12 +02:00
Stefan Prodan
cbbabdfac0 Merge pull request #53 from stefanprodan/kind
Add CircleCI workflow for end-to-end testing with Kubernetes Kind
2019-02-24 12:44:20 +02:00
stefanprodan
9d92de234c Increase promotion e2e wait time to 10s 2019-02-24 11:55:37 +02:00
stefanprodan
ba65975fb5 Add e2e testing docs 2019-02-24 11:41:22 +02:00
stefanprodan
ef423b2078 Move Flagger e2e build to a dedicated job 2019-02-24 03:10:50 +02:00
stefanprodan
f451b4e36c Split e2e prerequisites 2019-02-24 02:52:25 +02:00
stefanprodan
0856e13ee6 Use kind kubeconfig 2019-02-24 02:35:36 +02:00
stefanprodan
87b9fa8ca7 Move cluster init to prerequisites 2019-02-24 02:24:23 +02:00
stefanprodan
5b43d3d314 Use local docker image for e2e testing 2019-02-24 02:11:32 +02:00
stefanprodan
ac4972dd8d Fix e2e paths 2019-02-24 02:09:45 +02:00
stefanprodan
8a8f68af5d Test CircleCI 2019-02-24 02:02:37 +02:00
stefanprodan
c669dc0c4b Run e2e tests with CircleCI 2019-02-24 01:58:18 +02:00
stefanprodan
863a5466cc Add e2e prerequisites 2019-02-24 01:58:03 +02:00
stefanprodan
e2347c84e3 Use absolute paths in e2e tests 2019-02-24 01:11:04 +02:00
stefanprodan
e0e673f565 Install e2e deps and run tests 2019-02-24 01:03:39 +02:00
stefanprodan
30cbf2a741 Add e2e tests
- create Kubernetes cluster with Kind
- install Istio and Prometheus
- install Flagger
- test canary init and promotion
2019-02-24 01:02:15 +02:00
stefanprodan
f58de3801c Add Istio install values for e2e testing 2019-02-24 01:00:03 +02:00
Stefan Prodan
7c6b88d4c1 Merge pull request #51 from carlossg/update-virtualservice
Update VirtualService when the Canary service spec changes
2019-02-20 09:07:27 +00:00
Carlos Sanchez
0c0ebaecd5 Compare only hosts and gateways 2019-02-19 19:54:38 +01:00
Carlos Sanchez
1925f99118 If generated VirtualService already exists update it
Only if spec has changed
2019-02-19 19:40:46 +01:00
68 changed files with 955 additions and 3313 deletions

16
.circleci/config.yml Normal file
View File

@@ -0,0 +1,16 @@
version: 2.1
jobs:
e2e-testing:
machine: true
steps:
- checkout
- run: test/e2e-kind.sh
- run: test/e2e-istio.sh
- run: test/e2e-build.sh
- run: test/e2e-tests.sh
workflows:
version: 2
build-and-test:
jobs:
- e2e-testing

1
.gitignore vendored
View File

@@ -12,4 +12,5 @@
*.out
.DS_Store
bin/
artifacts/gcloud/

View File

@@ -12,12 +12,17 @@ addons:
packages:
- docker-ce
#before_script:
# - go get -u sigs.k8s.io/kind
# - curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
# - curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
script:
- set -e
- make test-fmt
- make test-codegen
- go test -race -coverprofile=coverage.txt -covermode=atomic ./pkg/controller/
- make build
- set -e
- make test-fmt
- make test-codegen
- go test -race -coverprofile=coverage.txt -covermode=atomic ./pkg/controller/
- make build
after_success:
- if [ -z "$DOCKER_USER" ]; then

View File

@@ -2,6 +2,33 @@
All notable changes to this project are documented in this file.
## 0.7.0 (2019-02-28)
Adds support for custom metric checks, HTTP timeouts and HTTP retries
#### Features
- Allow custom promql queries in the canary analysis spec [##60](https://github.com/stefanprodan/flagger/pull/#60)
- Add HTTP timeout and retries to canary service spec [##62](https://github.com/stefanprodan/flagger/pull/#62)
## 0.6.0 (2019-02-25)
Allows for [HTTPMatchRequests](https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPMatchRequest)
and [HTTPRewrite](https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPRewrite)
to be customized in the service spec of the canary custom resource.
#### Features
- Add HTTP match conditions and URI rewrite to the canary service spec [#55](https://github.com/stefanprodan/flagger/pull/55)
- Update virtual service when the canary service spec changes
[#54](https://github.com/stefanprodan/flagger/pull/54)
[#51](https://github.com/stefanprodan/flagger/pull/51)
#### Improvements
- Run e2e testing on [Kubernetes Kind](https://github.com/kubernetes-sigs/kind) for canary promotion
[#53](https://github.com/stefanprodan/flagger/pull/53)
## 0.5.1 (2019-02-14)
Allows skipping the analysis phase to ship changes directly to production

13
Gopkg.lock generated
View File

@@ -163,12 +163,9 @@
revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682"
[[projects]]
digest = "1:03a74b0d86021c8269b52b7c908eb9bb3852ff590b363dad0a807cf58cec2f89"
digest = "1:05ddd9088c0cfb8eaa3adf3626977caa6d96b3959a3bd8c91fef932fd1696c34"
name = "github.com/knative/pkg"
packages = [
"apis",
"apis/duck",
"apis/duck/v1alpha1",
"apis/istio",
"apis/istio/authentication",
"apis/istio/authentication/v1alpha1",
@@ -179,14 +176,12 @@
"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"
revision = "c15d7c8f2220a7578b33504df6edefa948c845ae"
revision = "f9612ef73847258e381e749c4f45b0f5e03b66e9"
[[projects]]
digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6"
@@ -476,10 +471,9 @@
version = "kubernetes-1.11.0"
[[projects]]
digest = "1:4b0d523ee389c762d02febbcfa0734c4530ebe87abe925db18f05422adcb33e8"
digest = "1:83b01e3d6f85c4e911de84febd69a2d3ece614c5a4a518fbc2b5d59000645980"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/equality",
"pkg/api/errors",
"pkg/api/meta",
"pkg/api/resource",
@@ -693,6 +687,7 @@
"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",
"github.com/prometheus/client_golang/prometheus/promhttp",
"go.uber.org/zap",
"go.uber.org/zap/zapcore",

View File

@@ -47,7 +47,7 @@ required = [
[[constraint]]
name = "github.com/knative/pkg"
revision = "c15d7c8f2220a7578b33504df6edefa948c845ae"
revision = "f9612ef73847258e381e749c4f45b0f5e03b66e9"
[[override]]
name = "github.com/golang/glog"

View File

@@ -26,9 +26,11 @@ Flagger documentation can be found at [docs.flagger.app](https://docs.flagger.ap
* [Flagger install on GKE](https://docs.flagger.app/install/flagger-install-on-google-cloud)
* How it works
* [Canary custom resource](https://docs.flagger.app/how-it-works#canary-custom-resource)
* [Virtual Service](https://docs.flagger.app/how-it-works#virtual-service)
* [Canary deployment stages](https://docs.flagger.app/how-it-works#canary-deployment)
* [Canary analysis](https://docs.flagger.app/how-it-works#canary-analysis)
* [HTTP metrics](https://docs.flagger.app/how-it-works#http-metrics)
* [Custom metrics](https://docs.flagger.app/how-it-works#custom-metrics)
* [Webhooks](https://docs.flagger.app/how-it-works#webhooks)
* [Load testing](https://docs.flagger.app/how-it-works#load-testing)
* Usage
@@ -97,9 +99,21 @@ spec:
# Istio virtual service host names (optional)
hosts:
- podinfo.example.com
# for emergency cases when you want to ship changes
# in production without analysing the canary
# HTTP match conditions (optional)
match:
- uri:
prefix: /
# HTTP rewrite (optional)
rewrite:
uri: /
# timeout for HTTP requests (optional)
timeout: 5s
# retry policy when a HTTP request fails (optional)
retries:
attempts: 3
# promote the canary without analysing it (default false)
skipAnalysis: false
# define the canary analysis timing and KPIs
canaryAnalysis:
# schedule interval (default 60s)
interval: 1m
@@ -113,6 +127,7 @@ spec:
stepWeight: 5
# Istio Prometheus checks
metrics:
# builtin Istio checks
- name: istio_requests_total
# minimum req success rate (non 5xx responses)
# percentage (0-100)
@@ -123,6 +138,16 @@ spec:
# milliseconds
threshold: 500
interval: 30s
# custom check
- name: "kafka lag"
threshold: 100
query: |
avg_over_time(
kafka_consumergroup_lag{
consumergroup=~"podinfo-consumer-.*",
topic="podinfo"
}[1m]
)
# external checks (optional)
webhooks:
- name: load-test
@@ -136,9 +161,9 @@ For more details on how the canary analysis and promotion works please [read the
### Roadmap
* Extend the validation mechanism to support other metrics than HTTP success rate and latency
* Add A/B testing capabilities using fixed routing based on HTTP headers and cookies match conditions
* Integrate with other service mesh technologies like AWS AppMesh and Linkerd v2
* Add support for comparing the canary metrics to the primary ones and do the validation based on the derivation between the two
* Extend the canary analysis and promotion to other types than Kubernetes deployments such as Flux Helm releases or OpenFaaS functions
### Contributing

View File

@@ -26,6 +26,13 @@ spec:
# Istio virtual service host names (optional)
hosts:
- app.istio.weavedx.com
# Istio virtual service HTTP match conditions (optional)
match:
- uri:
prefix: /
# Istio virtual service HTTP rewrite (optional)
rewrite:
uri: /
# for emergency cases when you want to ship changes
# in production without analysing the canary
skipAnalysis: false

View File

@@ -73,6 +73,8 @@ spec:
properties:
port:
type: number
timeout:
type: string
skipAnalysis:
type: boolean
canaryAnalysis:
@@ -91,7 +93,7 @@ spec:
properties:
items:
type: object
required: ['name', 'interval', 'threshold']
required: ['name', 'threshold']
properties:
name:
type: string
@@ -100,6 +102,8 @@ spec:
pattern: "^[0-9]+(m|s)"
threshold:
type: number
query:
type: string
webhooks:
type: array
properties:

View File

@@ -22,8 +22,8 @@ spec:
serviceAccountName: flagger
containers:
- name: flagger
image: quay.io/stefanprodan/flagger:0.5.1
imagePullPolicy: Always
image: quay.io/stefanprodan/flagger:0.7.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080

View File

@@ -1,7 +1,7 @@
apiVersion: v1
name: flagger
version: 0.5.1
appVersion: 0.5.1
version: 0.7.0
appVersion: 0.7.0
kubeVersion: ">=1.11.0-0"
engine: gotpl
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.

View File

@@ -74,6 +74,8 @@ spec:
properties:
port:
type: number
timeout:
type: string
skipAnalysis:
type: boolean
canaryAnalysis:
@@ -92,7 +94,7 @@ spec:
properties:
items:
type: object
required: ['name', 'interval', 'threshold']
required: ['name', 'threshold']
properties:
name:
type: string
@@ -101,6 +103,8 @@ spec:
pattern: "^[0-9]+(m|s)"
threshold:
type: number
query:
type: string
webhooks:
type: array
properties:

View File

@@ -2,7 +2,7 @@
image:
repository: quay.io/stefanprodan/flagger
tag: 0.5.1
tag: 0.7.0
pullPolicy: IfNotPresent
metricsServer: "http://prometheus.istio-system.svc.cluster.local:9090"

View File

@@ -39,9 +39,22 @@ spec:
# Istio virtual service host names (optional)
hosts:
- podinfo.example.com
# for emergency cases when you want to ship changes
# in production without analysing the canary
# HTTP match conditions (optional)
match:
- uri:
prefix: /
# HTTP rewrite (optional)
rewrite:
uri: /
# timeout for HTTP requests (optional)
timeout: 5s
# retry policy when a HTTP request fails (optional)
retries:
attempts: 3
perTryTimeout: 3s
# promote the canary without analysing it (default false)
skipAnalysis: false
# define the canary analysis timing and KPIs
canaryAnalysis:
# schedule interval (default 60s)
interval: 1m
@@ -96,7 +109,124 @@ spec:
The target deployment should expose a TCP port that will be used by Flagger to create the ClusterIP Service and
the Istio Virtual Service. The container port from the target deployment should match the `service.port` value.
### Canary Deployment
### Virtual Service
Flagger creates an Istio Virtual Service based on the Canary service spec.
The following spec exposes the `frontend` workload inside the mesh on `frontend.test.svc.cluster.local:9898`
and outside the mesh on `frontend.example.com`. You'll have to specify an Istio ingress gateway for external hosts.
```yaml
apiVersion: flagger.app/v1alpha3
kind: Canary
metadata:
name: frontend
namespace: test
service:
# container port
port: 9898
# Istio gateways (optional)
gateways:
- public-gateway.istio-system.svc.cluster.local
# Istio virtual service host names (optional)
hosts:
- frontend.example.com
# Istio virtual service HTTP match conditions (optional)
match:
- uri:
prefix: /
# Istio virtual service HTTP rewrite (optional)
rewrite:
uri: /
```
For the above spec Flagger will generate the following virtual service:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend
namespace: test
ownerReferences:
- apiVersion: flagger.app/v1alpha3
blockOwnerDeletion: true
controller: true
kind: Canary
name: podinfo
uid: 3a4a40dd-3875-11e9-8e1d-42010a9c0fd1
spec:
gateways:
- public-gateway.istio-system.svc.cluster.local
- mesh
hosts:
- frontend.example.com
- frontend
http:
- match:
- uri:
prefix: /
rewrite:
uri: /
route:
- destination:
host: frontend-primary
port:
number: 9898
weight: 100
- destination:
host: frontend-canary
port:
number: 9898
weight: 0
```
Flagger keeps in sync the virtual service with the canary service spec. Any direct modification of the virtual
service spec will be overwritten.
To expose a workload inside the mesh on `http://backend.test.svc.cluster.local:9898`,
the service spec can contain only the container port:
```yaml
apiVersion: flagger.app/v1alpha3
kind: Canary
metadata:
name: backend
namespace: test
spec:
service:
port: 9898
```
Based on the above spec, Flagger will create several ClusterIP services like:
```yaml
apiVersion: v1
kind: Service
metadata:
name: backend-primary
ownerReferences:
- apiVersion: flagger.app/v1alpha3
blockOwnerDeletion: true
controller: true
kind: Canary
name: backend
uid: 2ca1a9c7-2ef6-11e9-bd01-42010a9c0145
spec:
type: ClusterIP
ports:
- name: http
port: 9898
protocol: TCP
targetPort: 9898
selector:
app: backend-primary
```
Flagger works for user facing apps exposed outside the cluster via an ingress gateway
and for backend HTTP APIs that are accessible only from inside the mesh.
### Canary Stages
![Flagger Canary Stages](https://raw.githubusercontent.com/stefanprodan/flagger/master/docs/diagrams/flagger-canary-steps.png)
@@ -155,6 +285,9 @@ Spec:
# canary increment step
# percentage (0-100)
stepWeight: 2
# deploy straight to production without
# the metrics and webhook checks
skipAnalysis: false
```
The above analysis, if it succeeds, will run for 25 minutes while validating the HTTP metrics and webhooks every minute.
@@ -250,6 +383,49 @@ histogram_quantile(0.99,
> **Note** that the metric interval should be lower or equal to the control loop interval.
### Custom Metrics
The canary analysis can be extended with custom Prometheus queries.
```yaml
canaryAnalysis:
threshold: 1
maxWeight: 50
stepWeight: 5
metrics:
- name: "404s percentage"
threshold: 5
query: |
100 - sum(
rate(
istio_requests_total{
reporter="destination",
destination_workload_namespace="test",
destination_workload="podinfo",
response_code!="404"
}[1m]
)
)
/
sum(
rate(
istio_requests_total{
reporter="destination",
destination_workload_namespace="test",
destination_workload="podinfo"
}[1m]
)
) * 100
```
The above configuration validates the canary by checking
if the HTTP 404 req/sec percentage is below 5 percent of the total traffic.
If the 404s rate reaches the 5% threshold, then the canary fails.
When specifying a query, Flagger will run the promql query and convert the result to float64.
Then it compares the query result value with the metric threshold value.
### Webhooks
The canary analysis can be extended with webhooks.

View File

@@ -113,7 +113,7 @@ Trigger a canary deployment by updating the container image:
```bash
kubectl -n test set image deployment/podinfo \
podinfod=quay.io/stefanprodan/podinfo:1.4.0
podinfod=quay.io/stefanprodan/podinfo:1.4.1
```
Flagger detects that the deployment revision changed and starts a new rollout:

View File

@@ -17,6 +17,7 @@ limitations under the License.
package v1alpha3
import (
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
hpav1 "k8s.io/api/autoscaling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"time"
@@ -26,6 +27,7 @@ const (
CanaryKind = "Canary"
ProgressDeadlineSeconds = 600
AnalysisInterval = 60 * time.Second
MetricInterval = "1m"
)
// +genclient
@@ -107,9 +109,13 @@ type CanaryStatus struct {
// 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"`
Port int32 `json:"port"`
Gateways []string `json:"gateways"`
Hosts []string `json:"hosts"`
Match []istiov1alpha3.HTTPMatchRequest `json:"match,omitempty"`
Rewrite *istiov1alpha3.HTTPRewrite `json:"rewrite,omitempty"`
Timeout string `json:"timeout,omitempty"`
Retries *istiov1alpha3.HTTPRetry `json:"retries,omitempty"`
}
// CanaryAnalysis is used to describe how the analysis should be done
@@ -124,9 +130,11 @@ type CanaryAnalysis struct {
// CanaryMetric holds the reference to Istio metrics used for canary analysis
type CanaryMetric struct {
Name string `json:"name"`
Interval string `json:"interval"`
Threshold int `json:"threshold"`
Name string `json:"name"`
Interval string `json:"interval,omitempty"`
Threshold float64 `json:"threshold"`
// +optional
Query string `json:"query,omitempty"`
}
// CanaryWebhook holds the reference to external checks used for canary analysis
@@ -167,3 +175,8 @@ func (c *Canary) GetAnalysisInterval() time.Duration {
return interval
}
// GetMetricInterval returns the metric interval default value (1m)
func (c *Canary) GetMetricInterval() string {
return MetricInterval
}

View File

@@ -21,6 +21,7 @@ limitations under the License.
package v1alpha3
import (
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
v1 "k8s.io/api/autoscaling/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -143,6 +144,23 @@ func (in *CanaryService) DeepCopyInto(out *CanaryService) {
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Match != nil {
in, out := &in.Match, &out.Match
*out = make([]istiov1alpha3.HTTPMatchRequest, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Rewrite != nil {
in, out := &in.Rewrite, &out.Rewrite
*out = new(istiov1alpha3.HTTPRewrite)
**out = **in
}
if in.Retries != nil {
in, out := &in.Retries, &out.Retries
*out = new(istiov1alpha3.HTTPRetry)
**out = **in
}
return
}

View File

@@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
@@ -73,6 +74,38 @@ func (c *CanaryObserver) queryMetric(query string) (*vectorQueryResponse, error)
return &values, nil
}
// GetScalar runs the promql query and returns the first value found
func (c *CanaryObserver) GetScalar(query string) (float64, error) {
if c.metricsServer == "fake" {
return 100, nil
}
query = strings.Replace(query, "\n", "", -1)
query = strings.Replace(query, " ", "", -1)
var value *float64
result, err := c.queryMetric(query)
if err != nil {
return 0, err
}
for _, v := range result.Data.Result {
metricValue := v.Value[1]
switch metricValue.(type) {
case string:
f, err := strconv.ParseFloat(metricValue.(string), 64)
if err != nil {
return 0, err
}
value = &f
}
}
if value == nil {
return 0, fmt.Errorf("no values found for query %s", query)
}
return *value, nil
}
// 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" {

View File

@@ -2,7 +2,8 @@ package controller
import (
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
istioclientset "github.com/knative/pkg/client/clientset/versioned"
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
@@ -26,15 +27,14 @@ type CanaryRouter struct {
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
// Sync creates or updates the primary and canary ClusterIP services
// and the Istio virtual service.
func (c *CanaryRouter) Sync(cd *flaggerv1.Canary) error {
err := c.createServices(cd)
if err != nil {
return err
}
err = c.createVirtualService(cd)
err = c.syncVirtualService(cd)
if err != nil {
return err
}
@@ -163,14 +163,48 @@ func (c *CanaryRouter) createServices(cd *flaggerv1.Canary) error {
return nil
}
func (c *CanaryRouter) createVirtualService(cd *flaggerv1.Canary) error {
func (c *CanaryRouter) syncVirtualService(cd *flaggerv1.Canary) error {
targetName := cd.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
hosts := append(cd.Spec.Service.Hosts, targetName)
gateways := append(cd.Spec.Service.Gateways, "mesh")
route := []istiov1alpha3.DestinationWeight{
{
Destination: istiov1alpha3.Destination{
Host: primaryName,
Port: istiov1alpha3.PortSelector{
Number: uint32(cd.Spec.Service.Port),
},
},
Weight: 100,
},
{
Destination: istiov1alpha3.Destination{
Host: fmt.Sprintf("%s-canary", targetName),
Port: istiov1alpha3.PortSelector{
Number: uint32(cd.Spec.Service.Port),
},
},
Weight: 0,
},
}
newSpec := istiov1alpha3.VirtualServiceSpec{
Hosts: hosts,
Gateways: gateways,
Http: []istiov1alpha3.HTTPRoute{
{
Match: cd.Spec.Service.Match,
Rewrite: cd.Spec.Service.Rewrite,
Timeout: cd.Spec.Service.Timeout,
Retries: cd.Spec.Service.Retries,
Route: route,
},
},
}
virtualService, err := c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Get(targetName, metav1.GetOptions{})
// insert
if errors.IsNotFound(err) {
c.logger.Debugf("VirtualService %s.%s not found", targetName, cd.Namespace)
virtualService = &istiov1alpha3.VirtualService{
ObjectMeta: metav1.ObjectMeta{
Name: targetName,
@@ -183,42 +217,37 @@ func (c *CanaryRouter) createVirtualService(cd *flaggerv1.Canary) error {
}),
},
},
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: targetName,
Port: istiov1alpha3.PortSelector{
Number: uint32(cd.Spec.Service.Port),
},
},
Weight: 0,
},
},
},
},
},
Spec: newSpec,
}
c.logger.Debugf("Creating VirtualService %s.%s", virtualService.GetName(), cd.Namespace)
_, err = c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Create(virtualService)
if err != nil {
return fmt.Errorf("VirtualService %s.%s create error %v", targetName, cd.Namespace, err)
}
c.logger.With("canary", fmt.Sprintf("%s.%s", cd.Name, cd.Namespace)).Infof("VirtualService %s.%s created", virtualService.GetName(), cd.Namespace)
c.logger.With("canary", fmt.Sprintf("%s.%s", cd.Name, cd.Namespace)).
Infof("VirtualService %s.%s created", virtualService.GetName(), cd.Namespace)
return nil
}
if err != nil {
return fmt.Errorf("VirtualService %s.%s query error %v", targetName, cd.Namespace, err)
}
// update service but keep the original destination weights
if virtualService != nil {
if diff := cmp.Diff(newSpec, virtualService.Spec, cmpopts.IgnoreTypes(istiov1alpha3.DestinationWeight{})); diff != "" {
//fmt.Println(diff)
vtClone := virtualService.DeepCopy()
vtClone.Spec = newSpec
if len(virtualService.Spec.Http) > 0 {
vtClone.Spec.Http[0].Route = virtualService.Spec.Http[0].Route
}
_, err = c.istioClient.NetworkingV1alpha3().VirtualServices(cd.Namespace).Update(vtClone)
if err != nil {
return fmt.Errorf("VirtualService %s.%s update error %v", targetName, cd.Namespace, err)
}
c.logger.With("canary", fmt.Sprintf("%s.%s", cd.Name, cd.Namespace)).
Infof("VirtualService %s.%s updated", virtualService.GetName(), cd.Namespace)
}
}
return nil
@@ -247,15 +276,15 @@ func (c *CanaryRouter) GetRoutes(cd *flaggerv1.Canary) (
if route.Destination.Host == fmt.Sprintf("%s-primary", targetName) {
primary = route
}
if route.Destination.Host == targetName {
if route.Destination.Host == fmt.Sprintf("%s-canary", targetName) {
canary = route
}
}
}
if primary.Weight == 0 && canary.Weight == 0 {
err = fmt.Errorf("VirtualService %s.%s does not contain routes for %s and %s",
targetName, cd.Namespace, fmt.Sprintf("%s-primary", targetName), targetName)
err = fmt.Errorf("VirtualService %s.%s does not contain routes for %s-primary and %s-canary",
targetName, cd.Namespace, targetName, targetName)
}
return
@@ -280,7 +309,11 @@ func (c *CanaryRouter) SetRoutes(
vsCopy := vs.DeepCopy()
vsCopy.Spec.Http = []istiov1alpha3.HTTPRoute{
{
Route: []istiov1alpha3.DestinationWeight{primary, canary},
Match: cd.Spec.Service.Match,
Rewrite: cd.Spec.Service.Rewrite,
Timeout: cd.Spec.Service.Timeout,
Retries: cd.Spec.Service.Retries,
Route: []istiov1alpha3.DestinationWeight{primary, canary},
},
}

View File

@@ -8,14 +8,14 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestCanaryRouter_Sync(t *testing.T) {
func TestCanaryRouter_SyncClusterIPServices(t *testing.T) {
mocks := SetupMocks()
err := mocks.router.Sync(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
canarySvc, err := mocks.kubeClient.CoreV1().Services("default").Get("podinfo", metav1.GetOptions{})
canarySvc, err := mocks.kubeClient.CoreV1().Services("default").Get("podinfo-canary", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
@@ -40,19 +40,6 @@ func TestCanaryRouter_Sync(t *testing.T) {
if primarySvc.Spec.Ports[0].Port != 9898 {
t.Errorf("Got primary svc port %v wanted %v", primarySvc.Spec.Ports[0].Port, 9898)
}
vs, err := mocks.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) {
@@ -76,6 +63,87 @@ func TestCanaryRouter_GetRoutes(t *testing.T) {
}
}
func TestCanaryRouter_SyncVirtualService(t *testing.T) {
mocks := SetupMocks()
err := mocks.router.Sync(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
// test insert
vs, err := mocks.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)
}
// test update
cd, err := mocks.flaggerClient.FlaggerV1alpha3().Canaries("default").Get("podinfo", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
cdClone := cd.DeepCopy()
hosts := cdClone.Spec.Service.Hosts
hosts = append(hosts, "test.example.com")
cdClone.Spec.Service.Hosts = hosts
canary, err := mocks.flaggerClient.FlaggerV1alpha3().Canaries("default").Update(cdClone)
if err != nil {
t.Fatal(err.Error())
}
// apply change
err = mocks.router.Sync(canary)
if err != nil {
t.Fatal(err.Error())
}
// verify
vs, err = mocks.istioClient.NetworkingV1alpha3().VirtualServices("default").Get("podinfo", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
if len(vs.Spec.Hosts) != 2 {
t.Errorf("Got Istio VS hosts %v wanted %v", vs.Spec.Hosts, 2)
}
// test drift
vsClone := vs.DeepCopy()
gateways := vsClone.Spec.Gateways
gateways = append(gateways, "test-gateway.istio-system")
vsClone.Spec.Gateways = gateways
vsGateways, err := mocks.istioClient.NetworkingV1alpha3().VirtualServices("default").Update(vsClone)
if err != nil {
t.Fatal(err.Error())
}
if len(vsGateways.Spec.Gateways) != 2 {
t.Errorf("Got Istio VS gateway %v wanted %v", vsGateways.Spec.Gateways, 2)
}
// undo change
err = mocks.router.Sync(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
// verify
vs, err = mocks.istioClient.NetworkingV1alpha3().VirtualServices("default").Get("podinfo", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
if len(vs.Spec.Gateways) != 1 {
t.Errorf("Got Istio VS gateways %v wanted %v", vs.Spec.Gateways, 1)
}
}
func TestCanaryRouter_SetRoutes(t *testing.T) {
mocks := SetupMocks()
err := mocks.router.Sync(mocks.canary)
@@ -109,7 +177,7 @@ func TestCanaryRouter_SetRoutes(t *testing.T) {
if route.Destination.Host == fmt.Sprintf("%s-primary", mocks.canary.Spec.TargetRef.Name) {
pRoute = route
}
if route.Destination.Host == mocks.canary.Spec.TargetRef.Name {
if route.Destination.Host == fmt.Sprintf("%s-canary", mocks.canary.Spec.TargetRef.Name) {
cRoute = route
}
}

View File

@@ -405,6 +405,10 @@ func (c *Controller) analyseCanary(r *flaggerv1.Canary) bool {
// run metrics checks
for _, metric := range r.Spec.CanaryAnalysis.Metrics {
if metric.Interval == "" {
metric.Interval = r.GetMetricInterval()
}
if metric.Name == "istio_requests_total" {
val, err := c.observer.GetDeploymentCounter(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
if err != nil {
@@ -436,6 +440,24 @@ func (c *Controller) analyseCanary(r *flaggerv1.Canary) bool {
return false
}
}
if metric.Query != "" {
val, err := c.observer.GetScalar(metric.Query)
if err != nil {
if strings.Contains(err.Error(), "no values found") {
c.recordEventWarningf(r, "Halt advancement no values found for metric %s probably %s.%s is not receiving traffic",
metric.Name, r.Spec.TargetRef.Name, r.Namespace)
} else {
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.observer.metricsServer, err)
}
return false
}
if val > float64(metric.Threshold) {
c.recordEventWarningf(r, "Halt %s.%s advancement %s %.2f > %v",
r.Name, r.Namespace, metric.Name, val, metric.Threshold)
return false
}
}
}
return true

View File

@@ -1,4 +1,4 @@
package version
var VERSION = "0.5.1"
var VERSION = "0.7.0"
var REVISION = "unknown"

4
test/Dockerfile.kind Normal file
View File

@@ -0,0 +1,4 @@
FROM golang:1.11
RUN go get -u sigs.k8s.io/kind

24
test/README.md Normal file
View File

@@ -0,0 +1,24 @@
# Flagger end-to-end testing
The e2e testing infrastructure is powered by CircleCI and [Kubernetes Kind](https://github.com/kubernetes-sigs/kind).
CircleCI e2e workflow:
* install latest stable kubectl [e2e-kind.sh](e2e-kind.sh)
* build Kubernetes Kind from master [e2e-kind.sh](e2e-kind.sh)
* create local Kubernetes cluster with kind [e2e-kind.sh](e2e-kind.sh)
* install latest stable Helm CLI [e2e-istio.sh](e2e-istio.sh)
* deploy Tiller on the local cluster [e2e-istio.sh](e2e-istio.sh)
* install Istio CRDs with Helm [e2e-istio.sh](e2e-istio.sh)
* install Istio control plane and Prometheus with Helm [e2e-istio.sh](e2e-istio.sh)
* build Flagger container image [e2e-build.sh](e2e-build.sh)
* load Flagger image onto the local cluster [e2e-build.sh](e2e-build.sh)
* deploy Flagger in the istio-system namespace [e2e-build.sh](e2e-build.sh)
* create a test namespace with Istio injection enabled [e2e-tests.sh](e2e-tests.sh)
* deploy the load tester in the test namespace [e2e-tests.sh](e2e-tests.sh)
* deploy a demo workload (podinfo) in the test namespace [e2e-tests.sh](e2e-tests.sh)
* test the canary initialization [e2e-tests.sh](e2e-tests.sh)
* test the canary analysis and promotion [e2e-tests.sh](e2e-tests.sh)

15
test/e2e-build.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
echo '>>> Building Flagger'
cd ${REPO_ROOT} && docker build -t test/flagger:latest . -f Dockerfile
echo '>>> Installing Flagger'
kind load docker-image test/flagger:latest
kubectl apply -f ${REPO_ROOT}/artifacts/flagger/
kubectl -n istio-system set image deployment/flagger flagger=test/flagger:latest
kubectl -n istio-system rollout status deployment/flagger

View File

@@ -0,0 +1,62 @@
#
# Minimal Istio Configuration required by Flagger
#
# pilot configuration
pilot:
enabled: true
sidecar: true
gateways:
enabled: false
istio-ingressgateway:
autoscaleMax: 1
# citadel configuration
security:
enabled: true
# sidecar-injector webhook configuration
sidecarInjectorWebhook:
enabled: true
# galley configuration
galley:
enabled: false
# mixer configuration
mixer:
policy:
enabled: false
replicaCount: 1
autoscaleEnabled: false
telemetry:
enabled: true
replicaCount: 1
autoscaleEnabled: false
resources:
requests:
cpu: 100m
memory: 128Mi
# addon prometheus configuration
prometheus:
enabled: true
scrapeInterval: 5s
# addon jaeger tracing configuration
tracing:
enabled: false
# Common settings.
global:
proxy:
# Resources for the sidecar.
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2000m
memory: 128Mi
useMCP: false

28
test/e2e-istio.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -o errexit
ISTIO_VER="1.1.0-rc.0"
REPO_ROOT=$(git rev-parse --show-toplevel)
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
echo ">>> Installing Helm"
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
echo '>>> Installing Tiller'
kubectl --namespace kube-system create sa tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
helm init --service-account tiller --upgrade --wait
echo ">>> Installing Istio ${ISTIO_VER}"
helm repo add istio.io https://storage.googleapis.com/istio-release/releases/${ISTIO_VER}/charts
echo '>>> Installing Istio CRDs'
helm upgrade -i istio-init istio.io/istio-init --wait --namespace istio-system
echo '>>> Waiting for Istio CRDs to be ready'
kubectl -n istio-system wait --for=condition=complete job/istio-init-crd-10
kubectl -n istio-system wait --for=condition=complete job/istio-init-crd-11
echo '>>> Installing Istio control plane'
helm upgrade -i istio istio.io/istio --wait --namespace istio-system -f ${REPO_ROOT}/test/e2e-istio-values.yaml

25
test/e2e-kind.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
echo ">>> Installing kubectl"
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
chmod +x kubectl && \
sudo mv kubectl /usr/local/bin/
echo ">>> Building sigs.k8s.io/kind"
docker build -t kind:src . -f ${REPO_ROOT}/test/Dockerfile.kind
docker create -ti --name dummy kind:src sh
docker cp dummy:/go/bin/kind ./kind
docker rm -f dummy
echo ">>> Installing kind"
chmod +x kind
sudo mv kind /usr/local/bin/
kind create cluster --wait 5m
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl get pods --all-namespaces

123
test/e2e-tests.sh Executable file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/env bash
# This script runs e2e tests for Canary initialization, analysis and promotion
# Prerequisites: Kubernetes Kind, Helm and Istio
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
echo '>>> Creating test namespace'
kubectl create namespace test
kubectl label namespace test istio-injection=enabled
echo '>>> Installing the load tester'
kubectl -n test apply -f ${REPO_ROOT}/artifacts/loadtester/
kubectl -n test rollout status deployment/flagger-loadtester
echo '>>> Initialising canary'
kubectl apply -f ${REPO_ROOT}/test/e2e-workload.yaml
cat <<EOF | kubectl apply -f -
apiVersion: flagger.app/v1alpha3
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
progressDeadlineSeconds: 60
service:
port: 9898
canaryAnalysis:
interval: 15s
threshold: 15
maxWeight: 50
stepWeight: 10
metrics:
- name: istio_requests_total
threshold: 99
interval: 1m
- name: istio_request_duration_seconds_bucket
threshold: 500
interval: 30s
- name: "404s percentage"
threshold: 5
interval: 1m
query: |
100 - sum(
rate(
istio_requests_total{
reporter="destination",
destination_workload_namespace=~"test",
destination_workload=~"podinfo",
response_code!="404"
}[1m]
)
)
/
sum(
rate(
istio_requests_total{
reporter="destination",
destination_workload_namespace=~"test",
destination_workload=~"podinfo"
}[1m]
)
) * 100
webhooks:
- name: load-test
url: http://flagger-loadtester.test/
timeout: 5s
metadata:
cmd: "hey -z 10m -q 10 -c 2 http://podinfo.test:9898/"
EOF
echo '>>> Waiting for primary to be ready'
retries=50
count=0
ok=false
until ${ok}; do
kubectl -n test get canary/podinfo | grep 'Initialized' && ok=true || ok=false
sleep 5
count=$(($count + 1))
if [[ ${count} -eq ${retries} ]]; then
kubectl -n istio-system logs deployment/flagger
echo "No more retries left"
exit 1
fi
done
echo '✔ Canary initialization test passed'
echo '>>> Triggering canary deployment'
kubectl -n test set image deployment/podinfo podinfod=quay.io/stefanprodan/podinfo:1.4.1
echo '>>> Waiting for canary promotion'
retries=50
count=0
ok=false
until ${ok}; do
kubectl -n test describe deployment/podinfo-primary | grep '1.4.1' && ok=true || ok=false
sleep 10
kubectl -n istio-system logs deployment/flagger --tail 1
count=$(($count + 1))
if [[ ${count} -eq ${retries} ]]; then
kubectl -n test describe deployment/podinfo
kubectl -n test describe deployment/podinfo-primary
kubectl -n istio-system logs deployment/flagger
echo "No more retries left"
exit 1
fi
done
echo '✔ Canary promotion test passed'
kubectl -n istio-system logs deployment/flagger
echo '✔ All tests passed'

67
test/e2e-workload.yaml Normal file
View File

@@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
namespace: test
labels:
app: podinfo
spec:
minReadySeconds: 5
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: podinfo
template:
metadata:
annotations:
prometheus.io/scrape: "true"
labels:
app: podinfo
spec:
containers:
- name: podinfod
image: quay.io/stefanprodan/podinfo:1.4.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9898
name: http
protocol: TCP
command:
- ./podinfo
- --port=9898
- --level=info
- --random-delay=false
- --random-error=false
env:
- name: PODINFO_UI_COLOR
value: blue
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 1000m
memory: 128Mi
requests:
cpu: 1m
memory: 16Mi

View File

@@ -1,18 +0,0 @@
/*
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.
*/
// +k8s:deepcopy-gen=package
package apis

View File

@@ -1,23 +0,0 @@
/*
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.
*/
// Package duck defines logic for defining and consuming "duck typed"
// Kubernetes resources. Producers define partial resource definitions
// that resource authors may choose to implement to interoperate with
// consumers of these "duck typed" interfaces.
// For more information see:
// TODO(mattmoor): Add link to doc.
package duck

View File

@@ -1,21 +0,0 @@
/*
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.
*/
package duck
const (
GroupName = "duck.knative.dev"
)

View File

@@ -1,280 +0,0 @@
/*
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.
*/
package v1alpha1
import (
"reflect"
"sort"
"time"
"fmt"
"github.com/knative/pkg/apis"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// Conditions is the interface for a Resource that implements the getter and
// setter for accessing a Condition collection.
// +k8s:deepcopy-gen=true
type ConditionsAccessor interface {
GetConditions() Conditions
SetConditions(Conditions)
}
// ConditionSet is an abstract collection of the possible ConditionType values
// that a particular resource might expose. It also holds the "happy condition"
// for that resource, which we define to be one of Ready or Succeeded depending
// on whether it is a Living or Batch process respectively.
// +k8s:deepcopy-gen=false
type ConditionSet struct {
happy ConditionType
dependents []ConditionType
}
// ConditionManager allows a resource to operate on its Conditions using higher
// order operations.
type ConditionManager interface {
// IsHappy looks at the happy condition and returns true if that condition is
// set to true.
IsHappy() bool
// GetCondition finds and returns the Condition that matches the ConditionType
// previously set on Conditions.
GetCondition(t ConditionType) *Condition
// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
SetCondition(new Condition)
// MarkTrue sets the status of t to true, and then marks the happy condition to
// true if all other dependents are also true.
MarkTrue(t ConditionType)
// MarkUnknown sets the status of t to Unknown and also sets the happy condition
// to Unknown if no other dependent condition is in an error state.
MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{})
// MarkFalse sets the status of t and the happy condition to False.
MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{})
// InitializeConditions updates all Conditions in the ConditionSet to Unknown
// if not set.
InitializeConditions()
// InitializeCondition updates a Condition to Unknown if not set.
InitializeCondition(t ConditionType)
}
// NewLivingConditionSet returns a ConditionSet to hold the conditions for the
// living resource. ConditionReady is used as the happy condition.
func NewLivingConditionSet(d ...ConditionType) ConditionSet {
return newConditionSet(ConditionReady, d...)
}
// NewBatchConditionSet returns a ConditionSet to hold the conditions for the
// batch resource. ConditionSucceeded is used as the happy condition.
func NewBatchConditionSet(d ...ConditionType) ConditionSet {
return newConditionSet(ConditionSucceeded, d...)
}
// newConditionSet returns a ConditionSet to hold the conditions that are
// important for the caller. The first ConditionType is the overarching status
// for that will be used to signal the resources' status is Ready or Succeeded.
func newConditionSet(happy ConditionType, dependents ...ConditionType) ConditionSet {
var deps []ConditionType
for _, d := range dependents {
// Skip duplicates
if d == happy || contains(deps, d) {
continue
}
deps = append(deps, d)
}
return ConditionSet{
happy: happy,
dependents: deps,
}
}
func contains(ct []ConditionType, t ConditionType) bool {
for _, c := range ct {
if c == t {
return true
}
}
return false
}
// Check that conditionsImpl implements ConditionManager.
var _ ConditionManager = (*conditionsImpl)(nil)
// conditionsImpl implements the helper methods for evaluating Conditions.
// +k8s:deepcopy-gen=false
type conditionsImpl struct {
ConditionSet
accessor ConditionsAccessor
}
// Manage creates a ConditionManager from an object that implements
// ConditionsAccessopr using the original ConditionSet as a reference.
func (r ConditionSet) Manage(accessor ConditionsAccessor) ConditionManager {
return conditionsImpl{
accessor: accessor,
ConditionSet: r,
}
}
// IsHappy looks at the happy condition and returns true if that condition is
// set to true.
func (r conditionsImpl) IsHappy() bool {
if c := r.GetCondition(r.happy); c == nil || !c.IsTrue() {
return false
}
return true
}
// GetCondition finds and returns the Condition that matches the ConditionType
// previously set on Conditions.
func (r conditionsImpl) GetCondition(t ConditionType) *Condition {
if r.accessor == nil {
return nil
}
for _, c := range r.accessor.GetConditions() {
if c.Type == t {
return &c
}
}
return nil
}
// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
func (r conditionsImpl) SetCondition(new Condition) {
if r.accessor == nil {
return
}
t := new.Type
var conditions Conditions
for _, c := range r.accessor.GetConditions() {
if c.Type != t {
conditions = append(conditions, c)
} else {
// If we'd only update the LastTransitionTime, then return.
new.LastTransitionTime = c.LastTransitionTime
if reflect.DeepEqual(&new, &c) {
return
}
}
}
new.LastTransitionTime = apis.VolatileTime{Inner: metav1.NewTime(time.Now())}
conditions = append(conditions, new)
// Sorted for convince of the consumer, i.e.: kubectl.
sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
r.accessor.SetConditions(conditions)
}
// MarkTrue sets the status of t to true, and then marks the happy condition to
// true if all other dependents are also true.
func (r conditionsImpl) MarkTrue(t ConditionType) {
// set the specified condition
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionTrue,
})
// check the dependents.
for _, cond := range r.dependents {
c := r.GetCondition(cond)
// Failed or Unknown conditions trump true conditions
if !c.IsTrue() {
return
}
}
// set the happy condition
r.SetCondition(Condition{
Type: r.happy,
Status: corev1.ConditionTrue,
})
}
// MarkUnknown sets the status of t to Unknown and also sets the happy condition
// to Unknown if no other dependent condition is in an error state.
func (r conditionsImpl) MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
// set the specified condition
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionUnknown,
Reason: reason,
Message: fmt.Sprintf(messageFormat, messageA...),
})
// check the dependents.
for _, cond := range r.dependents {
c := r.GetCondition(cond)
// Failed conditions trump Unknown conditions
if c.IsFalse() {
// Double check that the happy condition is also false.
happy := r.GetCondition(r.happy)
if !happy.IsFalse() {
r.MarkFalse(r.happy, reason, messageFormat, messageA)
}
return
}
}
// set the happy condition
r.SetCondition(Condition{
Type: r.happy,
Status: corev1.ConditionUnknown,
Reason: reason,
Message: fmt.Sprintf(messageFormat, messageA...),
})
}
// MarkFalse sets the status of t and the happy condition to False.
func (r conditionsImpl) MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
for _, t := range []ConditionType{
t,
r.happy,
} {
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionFalse,
Reason: reason,
Message: fmt.Sprintf(messageFormat, messageA...),
})
}
}
// InitializeConditions updates all Conditions in the ConditionSet to Unknown
// if not set.
func (r conditionsImpl) InitializeConditions() {
for _, t := range append(r.dependents, r.happy) {
r.InitializeCondition(t)
}
}
// InitializeCondition updates a Condition to Unknown if not set.
func (r conditionsImpl) InitializeCondition(t ConditionType) {
if c := r.GetCondition(t); c == nil {
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionUnknown,
})
}
}

View File

@@ -1,149 +0,0 @@
/*
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.
*/
package v1alpha1
import (
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/knative/pkg/apis"
"github.com/knative/pkg/apis/duck"
)
// Conditions is the schema for the conditions portion of the payload
type Conditions []Condition
// ConditionType is a camel-cased condition type.
type ConditionType string
const (
// ConditionReady specifies that the resource is ready.
// For long-running resources.
ConditionReady ConditionType = "Ready"
// ConditionSucceeded specifies that the resource has finished.
// For resource which run to completion.
ConditionSucceeded ConditionType = "Succeeded"
)
// Conditions defines a readiness condition for a Knative resource.
// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties
// +k8s:deepcopy-gen=true
type Condition struct {
// Type of condition.
// +required
Type ConditionType `json:"type" description:"type of status condition"`
// Status of the condition, one of True, False, Unknown.
// +required
Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"`
// LastTransitionTime is the last time the condition transitioned from one status to another.
// We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic
// differences (all other things held constant).
// +optional
LastTransitionTime apis.VolatileTime `json:"lastTransitionTime,omitempty" description:"last time the condition transit from one status to another"`
// The reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"`
// A human readable message indicating details about the transition.
// +optional
Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"`
}
// IsTrue is true if the condition is True
func (c *Condition) IsTrue() bool {
if c == nil {
return false
}
return c.Status == corev1.ConditionTrue
}
// IsFalse is true if the condition is False
func (c *Condition) IsFalse() bool {
if c == nil {
return false
}
return c.Status == corev1.ConditionFalse
}
// IsUnknown is true if the condition is Unknown
func (c *Condition) IsUnknown() bool {
if c == nil {
return true
}
return c.Status == corev1.ConditionUnknown
}
// Implementations can verify that they implement Conditions via:
var _ = duck.VerifyType(&KResource{}, &Conditions{})
// Conditions is an Implementable "duck type".
var _ duck.Implementable = (*Conditions)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// KResource is a skeleton type wrapping Conditions in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Conditions ObjectReferences and
// access the Conditions data. This is not a real resource.
type KResource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status KResourceStatus `json:"status"`
}
// KResourceStatus shows how we expect folks to embed Conditions in
// their Status field.
type KResourceStatus struct {
Conditions Conditions `json:"conditions,omitempty"`
}
// In order for Conditions to be Implementable, KResource must be Populatable.
var _ duck.Populatable = (*KResource)(nil)
// GetFullType implements duck.Implementable
func (_ *Conditions) GetFullType() duck.Populatable {
return &KResource{}
}
// Populate implements duck.Populatable
func (t *KResource) Populate() {
t.Status.Conditions = Conditions{{
// Populate ALL fields
Type: "Birthday",
Status: corev1.ConditionTrue,
LastTransitionTime: apis.VolatileTime{Inner: metav1.NewTime(time.Date(1984, 02, 28, 18, 52, 00, 00, time.UTC))},
Reason: "Celebrate",
Message: "n3wScott, find your party hat :tada:",
}}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// KResourceList is a list of KResource resources
type KResourceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []KResource `json:"items"`
}

View File

@@ -1,23 +0,0 @@
/*
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.
*/
// Api versions allow the api contract for a resource to be changed while keeping
// backward compatibility by support multiple concurrent versions
// of the same resource
// +k8s:deepcopy-gen=package
// +groupName=duck.knative.dev
package v1alpha1

View File

@@ -1,76 +0,0 @@
/*
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.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/knative/pkg/apis/duck"
)
// Generation is the schema for the generational portion of the payload
type Generation int64
// Implementations can verify that they implement Generation via:
var emptyGen Generation
var _ = duck.VerifyType(&Generational{}, &emptyGen)
// Generation is an Implementable "duck type".
var _ duck.Implementable = (*Generation)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Generational is a skeleton type wrapping Generation in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Generation ObjectReferences and
// access the Generation data. This is not a real resource.
type Generational struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec GenerationalSpec `json:"spec"`
}
// GenerationalSpec shows how we expect folks to embed Generation in
// their Spec field.
type GenerationalSpec struct {
Generation Generation `json:"generation,omitempty"`
}
// In order for Generation to be Implementable, Generational must be Populatable.
var _ duck.Populatable = (*Generational)(nil)
// GetFullType implements duck.Implementable
func (_ *Generation) GetFullType() duck.Populatable {
return &Generational{}
}
// Populate implements duck.Populatable
func (t *Generational) Populate() {
t.Spec.Generation = 1234
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// GenerationalList is a list of Generational resources
type GenerationalList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []Generational `json:"items"`
}

View File

@@ -1,53 +0,0 @@
/*
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.
*/
package v1alpha1
import (
"github.com/knative/pkg/apis/duck"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: duck.GroupName, Version: "v1alpha1"}
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(
SchemeGroupVersion,
// &VirtualService{},
// &VirtualServiceList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -1,81 +0,0 @@
/*
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.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/knative/pkg/apis/duck"
)
// Subscribable is the schema for the subscribable portion of the payload
type Subscribable struct {
// TODO(vaikas): Give me a schema!
Field string `json:"field,omitempty"`
}
// Implementations can verify that they implement Subscribable via:
var _ = duck.VerifyType(&Topic{}, &Subscribable{})
// Subscribable is an Implementable "duck type".
var _ duck.Implementable = (*Subscribable)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Topic is a skeleton type wrapping Subscribable in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Subscribable ObjectReferences and
// access the Subscribable data. This is not a real resource.
type Topic struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status TopicStatus `json:"status"`
}
// TopicStatus shows how we expect folks to embed Subscribable in
// their Status field.
type TopicStatus struct {
Subscribable *Subscribable `json:"subscribable,omitempty"`
}
// In order for Subscribable to be Implementable, Topic must be Populatable.
var _ duck.Populatable = (*Topic)(nil)
// GetFullType implements duck.Implementable
func (_ *Subscribable) GetFullType() duck.Populatable {
return &Topic{}
}
// Populate implements duck.Populatable
func (t *Topic) Populate() {
t.Status.Subscribable = &Subscribable{
// Populate ALL fields
Field: "this is not empty",
}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// TopicList is a list of Topic resources
type TopicList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []Topic `json:"items"`
}

View File

@@ -1,81 +0,0 @@
/*
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.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/knative/pkg/apis/duck"
)
// Targetable is the schema for the targetable portion of the payload
type Targetable struct {
// TODO(vaikas): Give me a schema!
Field string `json:"field,omitempty"`
}
// Implementations can verify that they implement Targetable via:
var _ = duck.VerifyType(&Target{}, &Targetable{})
// Targetable is an Implementable "duck type".
var _ duck.Implementable = (*Targetable)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Target is a skeleton type wrapping Targetable in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Targetable ObjectReferences and
// access the Targetable data. This is not a real resource.
type Target struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status TargetStatus `json:"status"`
}
// TargetStatus shows how we expect folks to embed Targetable in
// their Status field.
type TargetStatus struct {
Targetable *Targetable `json:"targetable,omitempty"`
}
// In order for Targetable to be Implementable, Target must be Populatable.
var _ duck.Populatable = (*Target)(nil)
// GetFullType implements duck.Implementable
func (_ *Targetable) GetFullType() duck.Populatable {
return &Target{}
}
// Populate implements duck.Populatable
func (t *Target) Populate() {
t.Status.Targetable = &Targetable{
// Populate ALL fields
Field: "this is not empty",
}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// TargetList is a list of Target resources
type TargetList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []Target `json:"items"`
}

View File

@@ -1,417 +0,0 @@
// +build !ignore_autogenerated
/*
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 deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Condition) DeepCopyInto(out *Condition) {
*out = *in
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
func (in *Condition) DeepCopy() *Condition {
if in == nil {
return nil
}
out := new(Condition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in Conditions) DeepCopyInto(out *Conditions) {
{
in := &in
*out = make(Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
return
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Conditions.
func (in Conditions) DeepCopy() Conditions {
if in == nil {
return nil
}
out := new(Conditions)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Generational) DeepCopyInto(out *Generational) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Generational.
func (in *Generational) DeepCopy() *Generational {
if in == nil {
return nil
}
out := new(Generational)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Generational) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GenerationalList) DeepCopyInto(out *GenerationalList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Generational, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerationalList.
func (in *GenerationalList) DeepCopy() *GenerationalList {
if in == nil {
return nil
}
out := new(GenerationalList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *GenerationalList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GenerationalSpec) DeepCopyInto(out *GenerationalSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerationalSpec.
func (in *GenerationalSpec) DeepCopy() *GenerationalSpec {
if in == nil {
return nil
}
out := new(GenerationalSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KResource) DeepCopyInto(out *KResource) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResource.
func (in *KResource) DeepCopy() *KResource {
if in == nil {
return nil
}
out := new(KResource)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KResource) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KResourceList) DeepCopyInto(out *KResourceList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KResource, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResourceList.
func (in *KResourceList) DeepCopy() *KResourceList {
if in == nil {
return nil
}
out := new(KResourceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KResourceList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KResourceStatus) DeepCopyInto(out *KResourceStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResourceStatus.
func (in *KResourceStatus) DeepCopy() *KResourceStatus {
if in == nil {
return nil
}
out := new(KResourceStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Subscribable) DeepCopyInto(out *Subscribable) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscribable.
func (in *Subscribable) DeepCopy() *Subscribable {
if in == nil {
return nil
}
out := new(Subscribable)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Target) DeepCopyInto(out *Target) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Target.
func (in *Target) DeepCopy() *Target {
if in == nil {
return nil
}
out := new(Target)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Target) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TargetList) DeepCopyInto(out *TargetList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Target, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetList.
func (in *TargetList) DeepCopy() *TargetList {
if in == nil {
return nil
}
out := new(TargetList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TargetList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TargetStatus) DeepCopyInto(out *TargetStatus) {
*out = *in
if in.Targetable != nil {
in, out := &in.Targetable, &out.Targetable
*out = new(Targetable)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetStatus.
func (in *TargetStatus) DeepCopy() *TargetStatus {
if in == nil {
return nil
}
out := new(TargetStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Targetable) DeepCopyInto(out *Targetable) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Targetable.
func (in *Targetable) DeepCopy() *Targetable {
if in == nil {
return nil
}
out := new(Targetable)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Topic) DeepCopyInto(out *Topic) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Topic.
func (in *Topic) DeepCopy() *Topic {
if in == nil {
return nil
}
out := new(Topic)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Topic) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TopicList) DeepCopyInto(out *TopicList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Topic, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopicList.
func (in *TopicList) DeepCopy() *TopicList {
if in == nil {
return nil
}
out := new(TopicList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TopicList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TopicStatus) DeepCopyInto(out *TopicStatus) {
*out = *in
if in.Subscribable != nil {
in, out := &in.Subscribable, &out.Subscribable
*out = new(Subscribable)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopicStatus.
func (in *TopicStatus) DeepCopy() *TopicStatus {
if in == nil {
return nil
}
out := new(TopicStatus)
in.DeepCopyInto(out)
return out
}

View File

@@ -1,86 +0,0 @@
/*
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.
*/
package duck
import (
"encoding/json"
"fmt"
"github.com/google/go-cmp/cmp"
)
// Implementable in implemented by the Fooable duck type that consumers
// are expected to embed as a `.status.fooable` field.
type Implementable interface {
// GetFullType returns an instance of a full resource wrapping
// an instance of this Implementable that can populate its fields
// to verify json roundtripping.
GetFullType() Populatable
}
// Populatable is implemented by a skeleton resource wrapping an Implementable
// duck type. It will generally have TypeMeta, ObjectMeta, and a Status field
// wrapping a Fooable field.
type Populatable interface {
// Populate fills in all possible fields, so that we can verify that
// they roundtrip properly through JSON.
Populate()
}
// VerifyType verifies that a particular concrete resource properly implements
// the provided Implementable duck type. It is expected that under the resource
// definition implementing a particular "Fooable" that one would write:
//
// type ConcreteResource struct { ... }
//
// // Check that ConcreteResource properly implement Fooable.
// var _ = duck.VerifyType(&ConcreteResource{}, &something.Fooable{})
//
// This will panic on startup if the duck typing is not satisfied. The return
// value is purely cosmetic to enable the `var _ = ...` shorthand.
func VerifyType(instance interface{}, iface Implementable) (nothing interface{}) {
// Create instances of the full resource for our input and ultimate result
// that we will compare at the end.
input, output := iface.GetFullType(), iface.GetFullType()
// Populate our input resource with values we will roundtrip.
input.Populate()
// Serialize the input to JSON and deserialize that into the provided instance
// of the type that we are checking.
if before, err := json.Marshal(input); err != nil {
panic(fmt.Sprintf("Error serializing duck type %T", input))
} else if err := json.Unmarshal(before, instance); err != nil {
panic(fmt.Sprintf("Error deserializing duck type %T into %T", input, instance))
}
// Serialize the instance we are checking to JSON and deserialize that into the
// output resource.
if after, err := json.Marshal(instance); err != nil {
panic(fmt.Sprintf("Error serializing %T", instance))
} else if err := json.Unmarshal(after, output); err != nil {
panic(fmt.Sprintf("Error deserializing %T into dock type %T", instance, output))
}
// Now verify that we were able to roundtrip all of our fields through the type
// we are checking.
if diff := cmp.Diff(input, output); diff != "" {
panic(fmt.Sprintf("%T does not implement the duck type %T, the following fields were lost: %s",
instance, iface, diff))
}
return
}

View File

@@ -1,186 +0,0 @@
/*
Copyright 2017 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.
*/
package apis
import (
"fmt"
"strings"
)
// CurrentField is a constant to supply as a fieldPath for when there is
// a problem with the current field itself.
const CurrentField = ""
// FieldError is used to propagate the context of errors pertaining to
// specific fields in a manner suitable for use in a recursive walk, so
// that errors contain the appropriate field context.
// +k8s:deepcopy-gen=false
type FieldError struct {
Message string
Paths []string
// Details contains an optional longer payload.
Details string
}
// FieldError implements error
var _ error = (*FieldError)(nil)
// ViaField is used to propagate a validation error along a field access.
// For example, if a type recursively validates its "spec" via:
// if err := foo.Spec.Validate(); err != nil {
// // Augment any field paths with the context that they were accessed
// // via "spec".
// return err.ViaField("spec")
// }
func (fe *FieldError) ViaField(prefix ...string) *FieldError {
if fe == nil {
return nil
}
var newPaths []string
for _, oldPath := range fe.Paths {
newPaths = append(newPaths, flatten(append(prefix, oldPath)))
}
fe.Paths = newPaths
return fe
}
// ViaIndex is used to attach an index to the next ViaField provided.
// For example, if a type recursively validates a parameter that has a collection:
// for i, c := range spec.Collection {
// if err := doValidation(c); err != nil {
// return err.ViaIndex(i).ViaField("collection")
// }
// }
func (fe *FieldError) ViaIndex(index int) *FieldError {
if fe == nil {
return nil
}
return fe.ViaField(fmt.Sprintf("[%d]", index))
}
// ViaFieldIndex is the short way to chain: err.ViaIndex(bar).ViaField(foo)
func (fe *FieldError) ViaFieldIndex(field string, index int) *FieldError {
return fe.ViaIndex(index).ViaField(field)
}
// ViaKey is used to attach a key to the next ViaField provided.
// For example, if a type recursively validates a parameter that has a collection:
// for k, v := range spec.Bag. {
// if err := doValidation(v); err != nil {
// return err.ViaKey(k).ViaField("bag")
// }
// }
func (fe *FieldError) ViaKey(key string) *FieldError {
if fe == nil {
return nil
}
return fe.ViaField(fmt.Sprintf("[%s]", key))
}
// ViaFieldKey is the short way to chain: err.ViaKey(bar).ViaField(foo)
func (fe *FieldError) ViaFieldKey(field string, key string) *FieldError {
return fe.ViaKey(key).ViaField(field)
}
// flatten takes in a array of path components and looks for chances to flatten
// objects that have index prefixes, examples:
// err([0]).ViaField(bar).ViaField(foo) -> foo.bar.[0] converts to foo.bar[0]
// err(bar).ViaIndex(0).ViaField(foo) -> foo.[0].bar converts to foo[0].bar
// err(bar).ViaField(foo).ViaIndex(0) -> [0].foo.bar converts to [0].foo.bar
// err(bar).ViaIndex(0).ViaIndex[1].ViaField(foo) -> foo.[1].[0].bar converts to foo[1][0].bar
func flatten(path []string) string {
var newPath []string
for _, part := range path {
for _, p := range strings.Split(part, ".") {
if p == CurrentField {
continue
} else if len(newPath) > 0 && isIndex(p) {
newPath[len(newPath)-1] = fmt.Sprintf("%s%s", newPath[len(newPath)-1], p)
} else {
newPath = append(newPath, p)
}
}
}
return strings.Join(newPath, ".")
}
func isIndex(part string) bool {
return strings.HasPrefix(part, "[") && strings.HasSuffix(part, "]")
}
// Error implements error
func (fe *FieldError) Error() string {
if fe.Details == "" {
return fmt.Sprintf("%v: %v", fe.Message, strings.Join(fe.Paths, ", "))
}
return fmt.Sprintf("%v: %v\n%v", fe.Message, strings.Join(fe.Paths, ", "), fe.Details)
}
// ErrMissingField is a variadic helper method for constructing a FieldError for
// a set of missing fields.
func ErrMissingField(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "missing field(s)",
Paths: fieldPaths,
}
}
// ErrDisallowedFields is a variadic helper method for constructing a FieldError
// for a set of disallowed fields.
func ErrDisallowedFields(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "must not set the field(s)",
Paths: fieldPaths,
}
}
// ErrInvalidValue constructs a FieldError for a field that has received an
// invalid string value.
func ErrInvalidValue(value, fieldPath string) *FieldError {
return &FieldError{
Message: fmt.Sprintf("invalid value %q", value),
Paths: []string{fieldPath},
}
}
// ErrMissingOneOf is a variadic helper method for constructing a FieldError for
// not having at least one field in a mutually exclusive field group.
func ErrMissingOneOf(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "expected exactly one, got neither",
Paths: fieldPaths,
}
}
// ErrMultipleOneOf is a variadic helper method for constructing a FieldError
// for having more than one field set in a mutually exclusive field group.
func ErrMultipleOneOf(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "expected exactly one, got both",
Paths: fieldPaths,
}
}
// ErrInvalidKeyName is a variadic helper method for constructing a
// FieldError that specifies a key name that is invalid.
func ErrInvalidKeyName(value, fieldPath string, details ...string) *FieldError {
return &FieldError{
Message: fmt.Sprintf("invalid key name %q", value),
Paths: []string{fieldPath},
Details: strings.Join(details, ", "),
}
}

View File

@@ -1,37 +0,0 @@
/*
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.
*/
package apis
// Defaultable defines an interface for setting the defaults for the
// uninitialized fields of this instance.
type Defaultable interface {
SetDefaults()
}
// Validatable indicates that a particular type may have its fields validated.
type Validatable interface {
// Validate checks the validity of this types fields.
Validate() *FieldError
}
// Immutable indicates that a particular type has fields that should
// not change after creation.
type Immutable interface {
// CheckImmutableFields checks that the current instance's immutable
// fields haven't changed from the provided original.
CheckImmutableFields(original Immutable) *FieldError
}

View File

@@ -17,8 +17,8 @@ limitations under the License.
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/knative/pkg/apis/istio/common/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
@@ -127,7 +127,7 @@ type PolicySpec struct {
// List rules to select destinations that the policy should be applied on.
// If empty, policy will be used on all destinations in the same namespace.
Targets []TargetSelector `json:"targets,omitempty"`
// List of authentication methods that can be used for peer authentication.
// They will be evaluated in order; the first validate one will be used to
// set peer identity (source.user) and other peer attributes. If none of
@@ -135,14 +135,14 @@ type PolicySpec struct {
// request will be rejected with authentication failed error (401).
// Leave the list empty if peer authentication is not required
Peers []PeerAuthenticationMethod `json:"peers,omitempty"`
// Set this flag to true to accept request (for peer authentication perspective),
// even when none of the peer authentication methods defined above satisfied.
// Typically, this is used to delay the rejection decision to next layer (e.g
// authorization).
// This flag is ignored if no authentication defined for peer (peers field is empty).
PeerIsOptional bool `json:"peerIsOptional,omitempty"`
// List of authentication methods that can be used for origin authentication.
// Similar to peers, these will be evaluated in order; the first validate one
// will be used to set origin identity and attributes (i.e request.auth.user,
@@ -151,17 +151,17 @@ type PolicySpec struct {
// error (401).
// Leave the list empty if origin authentication is not required.
Origins []OriginAuthenticationMethod `json:"origins,omitempty"`
// Set this flag to true to accept request (for origin authentication perspective),
// even when none of the origin authentication methods defined above satisfied.
// Typically, this is used to delay the rejection decision to next layer (e.g
// authorization).
// This flag is ignored if no authentication defined for origin (origins field is empty).
OriginIsOptional bool `json:"originIsOptional,omitempty"`
// Define whether peer or origin identity should be use for principal. Default
// value is USE_PEER.
// If peer (or orgin) identity is not available, either because of peer/origin
// If peer (or origin) identity is not available, either because of peer/origin
// authentication is not defined, or failed, principal will be left unset.
// In other words, binding rule does not affect the decision to accept or
// reject request.
@@ -173,7 +173,7 @@ type TargetSelector struct {
// REQUIRED. The name must be a short name from the service registry. The
// fully qualified domain name will be resolved in a platform specific manner.
Name string `json:"name"`
// Specifies the ports on the destination. Leave empty to match all ports
// that are exposed.
Ports []PortSelector `json:"ports,omitempty"`
@@ -183,12 +183,12 @@ type TargetSelector struct {
// matching targets for authenticationn policy. This is copied from
// networking API to avoid dependency.
type PortSelector struct {
// It is requred to specify exactly one of the fields:
// It is required to specify exactly one of the fields:
// Number or Name
// Valid port number
Number uint32 `json:"number,omitempty"`
// Port name
Name string `json:"name,omitempty"`
}
@@ -199,11 +199,11 @@ type PortSelector struct {
// The type can be progammatically determine by checking the type of the
// "params" field.
type PeerAuthenticationMethod struct {
// It is requred to specify exactly one of the fields:
// It is required to specify exactly one of the fields:
// Mtls or Jwt
// Set if mTLS is used.
Mtls *MutualTls `json:"mtls,omitempty"`
// Set if JWT is used. This option is not yet available.
Jwt *Jwt `json:"jwt,omitempty"`
}
@@ -214,7 +214,7 @@ type Mode string
const (
// Client cert must be presented, connection is in TLS.
ModeStrict Mode = "STRICT"
// Connection can be either plaintext or TLS, and client cert can be omitted.
ModePermissive Mode = "PERMISSIVE"
)
@@ -229,7 +229,7 @@ type MutualTls struct {
// be left unset.
// When the flag is false (default), request must have client certificate.
AllowTls bool `json:"allowTls,omitempty"`
// Defines the mode of mTLS authentication.
Mode Mode `json:"mode,omitempty"`
}
@@ -256,7 +256,7 @@ type Jwt struct {
// Example: https://securetoken.google.com
// Example: 1234567-compute@developer.gserviceaccount.com
Issuer string `json:"issuer,omitempty"`
// The list of JWT
// [audiences](https://tools.ietf.org/html/rfc7519#section-4.1.3).
// that are allowed to access. A JWT containing any of these
@@ -272,7 +272,7 @@ type Jwt struct {
// bookstore_web.apps.googleusercontent.com
// ```
Audiences []string `json:"audiences,omitempty"`
// URL of the provider's public key set to validate signature of the
// JWT. See [OpenID
// Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata).
@@ -285,7 +285,7 @@ type Jwt struct {
//
// Example: https://www.googleapis.com/oauth2/v1/certs
JwksUri string `json:"jwksUri,omitempty"`
// Two fields below define where to extract the JWT from an HTTP request.
//
// If no explicit location is specified the following default
@@ -304,7 +304,7 @@ type Jwt struct {
// For example, if `header=x-goog-iap-jwt-assertion`, the header
// format will be x-goog-iap-jwt-assertion: <JWT>.
JwtHeaders []string `json:"jwtHeaders,omitempty"`
// JWT is sent in a query parameter. `query` represents the
// query parameter name.
//
@@ -312,9 +312,9 @@ type Jwt struct {
JwtParams []string `json:"jwtParams,omitempty"`
// URL paths that should be excluded from the JWT validation. If the request path is matched,
// the JWT validation will be skipped and the request will proceed regardless.
// This is useful to keep a couple of URLs public for external health checks.
// Example: "/health_check", "/status/cpu_usage".
// the JWT validation will be skipped and the request will proceed regardless.
// This is useful to keep a couple of URLs public for external health checks.
// Example: "/health_check", "/status/cpu_usage".
ExcludedPaths []v1alpha1.StringMatch `json:"excludedPaths,omitempty"`
}

View File

@@ -19,17 +19,17 @@ package v1alpha1
// Describes how to match a given string in HTTP headers. Match is
// case-sensitive.
type StringMatch struct {
// Specified exactly one of the fields below.
// Specified exactly one of the fields below.
// exact string match
Exact string `json:"exact,omitempty"`
// exact string match
Exact string `json:"exact,omitempty"`
// prefix-based match
Prefix string `json:"prefix,omitempty"`
// prefix-based match
Prefix string `json:"prefix,omitempty"`
// suffix-based match.
Suffix string `json:"prefix,omitempty"`
// suffix-based match.
Suffix string `json:"suffix,omitempty"`
// ECMAscript style regex-based match
Regex string `json:"regex,omitempty"`
// ECMAscript style regex-based match
Regex string `json:"regex,omitempty"`
}

View File

@@ -117,11 +117,11 @@ type DestinationRuleSpec struct {
//
// Note that the host field applies to both HTTP and TCP services.
Host string `json:"host"`
// Traffic policies to apply (load balancing policy, connection pool
// sizes, outlier detection).
TrafficPolicy *TrafficPolicy `json:"trafficPolicy,omitempty"`
// One or more named sets that represent individual versions of a
// service. Traffic policies can be overridden at subset level.
Subsets []Subset `json:"subsets,omitempty"`
@@ -133,16 +133,16 @@ type TrafficPolicy struct {
// Settings controlling the load balancer algorithms.
LoadBalancer *LoadBalancerSettings `json:"loadBalancer,omitempty"`
// Settings controlling the volume of connections to an upstream service
ConnectionPool *ConnectionPoolSettings `json:"connectionPool,omitempty"`
// Settings controlling eviction of unhealthy hosts from the load balancing pool
OutlierDetection *OutlierDetection `json:"outlierDetection,omitempty"`
// TLS related settings for connections to the upstream service.
Tls *TLSSettings `json:"tls,omitempty"`
// Traffic policies specific to individual ports. Note that port level
// settings will override the destination-level settings. Traffic
// settings specified at the destination-level will not be inherited when
@@ -161,13 +161,13 @@ type PortTrafficPolicy struct {
// the same protocol the names should be of the form <protocol-name>-<DNS
// label>.
Port PortSelector `json:"port"`
// Settings controlling the load balancer algorithms.
LoadBalancer *LoadBalancerSettings `json:"loadBalancer,omitempty"`
// Settings controlling the volume of connections to an upstream service
ConnectionPool *ConnectionPoolSettings `json:"connectionPool,omitempty"`
// Settings controlling eviction of unhealthy hosts from the load balancing pool
OutlierDetection *OutlierDetection `json:"outlierDetection,omitempty"`
@@ -206,12 +206,12 @@ type PortTrafficPolicy struct {
type Subset struct {
// REQUIRED. Name of the subset. The service name and the subset name can
// be used for traffic splitting in a route rule.
Name string `json:"port"`
Name string `json:"name"`
// REQUIRED. Labels apply a filter over the endpoints of a service in the
// service registry. See route rules for examples of usage.
Labels map[string]string `json:"labels"`
// Traffic policies that apply to this subset. Subsets inherit the
// traffic policies specified at the DestinationRule level. Settings
// specified at the subset level will override the corresponding settings
@@ -254,7 +254,7 @@ type Subset struct {
// name: user
// ttl: 0s
type LoadBalancerSettings struct {
// It is requred to specify exactly one of the fields:
// It is required to specify exactly one of the fields:
// Simple or ConsistentHash
Simple SimpleLB `json:"simple,omitempty"`
ConsistentHash *ConsistentHashLB `json:"consistentHash,omitempty"`
@@ -266,17 +266,17 @@ type SimpleLB string
const (
// Round Robin policy. Default
SimpleLBRoundRobin SimpleLB = "ROUND_ROBIN"
// The least request load balancer uses an O(1) algorithm which selects
// two random healthy hosts and picks the host which has fewer active
// requests.
SimpleLBLeastConn SimpleLB = "LEAST_CONN"
// The random load balancer selects a random healthy host. The random
// load balancer generally performs better than round robin if no health
// checking policy is configured.
SimpleLBRandom SimpleLB = "RANDOM"
// This option will forward the connection to the original IP address
// requested by the caller without doing any form of load
// balancing. This option must be used with care. It is meant for
@@ -293,17 +293,17 @@ const (
// service.
type ConsistentHashLB struct {
// It is requred to specify exactly one of the fields as hash key:
// It is required to specify exactly one of the fields as hash key:
// HttpHeaderName, HttpCookie, or UseSourceIP.
// Hash based on a specific HTTP header.
HttpHeaderName string `json:"httpHeaderName,omitempty"`
// Hash based on HTTP cookie.
HttpCookie *HTTPCookie `json:"httpCookie,omitempty"`
// Hash based on the source IP address.
UseSourceIp bool `json:"useSourceIp,omitempty"`
// The minimum number of virtual nodes to use for the hash
// ring. Defaults to 1024. Larger ring sizes result in more granular
// load distributions. If the number of hosts in the load balancing
@@ -359,7 +359,7 @@ type ConnectionPoolSettings struct {
type TCPSettings struct {
// Maximum number of HTTP1 /TCP connections to a destination host.
MaxConnections int32 `json:"maxConnections,omitempty"`
// TCP connection timeout.
ConnectTimeout string `json:"connectTimeout,omitempty"`
}
@@ -368,14 +368,14 @@ type TCPSettings struct {
type HTTPSettings struct {
// Maximum number of pending HTTP requests to a destination. Default 1024.
Http1MaxPendingRequests int32 `json:"http1MaxPendingRequests,omitempty"`
// Maximum number of requests to a backend. Default 1024.
Http2MaxRequests int32 `json:"http2MaxRequests,omitempty"`
// Maximum number of requests per connection to a backend. Setting this
// parameter to 1 disables keep alive.
MaxRequestsPerConnection int32 `json:"maxRequestsPerConnection,omitempty"`
// Maximum number of retries that can be outstanding to all hosts in a
// cluster at a given time. Defaults to 3.
MaxRetries int32 `json:"maxRetries,omitempty"`
@@ -421,18 +421,18 @@ type OutlierDetection struct {
// accessed over an opaque TCP connection, connect timeouts and
// connection error/failure events qualify as an error.
ConsecutiveErrors int32 `json:"consecutiveErrors,omitempty"`
// Time interval between ejection sweep analysis. format:
// 1h/1m/1s/1ms. MUST BE >=1ms. Default is 10s.
Interval string `json:"interval,omitempty"`
// Minimum ejection duration. A host will remain ejected for a period
// equal to the product of minimum ejection duration and the number of
// times the host has been ejected. This technique allows the system to
// automatically increase the ejection period for unhealthy upstream
// servers. format: 1h/1m/1s/1ms. MUST BE >=1ms. Default is 30s.
BaseEjectionTime string `json:"baseEjectionTime,omitempty"`
// Maximum % of hosts in the load balancing pool for the upstream
// service that can be ejected. Defaults to 10%.
MaxEjectionPercent int32 `json:"maxEjectionPercent,omitempty"`
@@ -488,29 +488,29 @@ type TLSSettings struct {
// REQUIRED: Indicates whether connections to this port should be secured
// using TLS. The value of this field determines how TLS is enforced.
Mode TLSmode `json:"mode"`
// REQUIRED if mode is `MUTUAL`. The path to the file holding the
// client-side TLS certificate to use.
// Should be empty if mode is `ISTIO_MUTUAL`.
ClientCertificate string `json:"clientCertificate,omitempty"`
// REQUIRED if mode is `MUTUAL`. The path to the file holding the
// client's private key.
// Should be empty if mode is `ISTIO_MUTUAL`.
PrivateKey string `json:"privateKey,omitempty"`
// OPTIONAL: The path to the file containing certificate authority
// certificates to use in verifying a presented server certificate. If
// omitted, the proxy will not verify the server's certificate.
// Should be empty if mode is `ISTIO_MUTUAL`.
CaCertificates string `json:"caCertificates,omitempty"`
// A list of alternate names to verify the subject identity in the
// certificate. If specified, the proxy will verify that the server
// certificate's subject alt name matches one of the specified values.
// Should be empty if mode is `ISTIO_MUTUAL`.
SubjectAltNames []string `json:"subjectAltNames,omitempty"`
// SNI string to present to the server during TLS handshake.
// Should be empty if mode is `ISTIO_MUTUAL`.
Sni string `json:"sni,omitempty"`
@@ -525,11 +525,11 @@ const (
// Originate a TLS connection to the upstream endpoint.
TLSmodeSimple TLSmode = "SIMPLE"
// Secure connections to the upstream using mutual TLS by presenting
// client certificates for authentication.
TLSmodeMutual TLSmode = "MUTUAL"
// Secure connections to the upstream using mutual TLS by presenting
// client certificates for authentication.
// Compared to Mutual mode, this mode uses certificates generated

View File

@@ -17,8 +17,8 @@ limitations under the License.
package v1alpha3
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/knative/pkg/apis/istio/common/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient

View File

@@ -1,46 +0,0 @@
/*
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.
*/
package apis
import (
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// VolatileTime wraps metav1.Time
type VolatileTime struct {
Inner metav1.Time
}
// MarshalJSON implements the json.Marshaler interface.
func (t VolatileTime) MarshalJSON() ([]byte, error) {
return t.Inner.MarshalJSON()
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (t *VolatileTime) UnmarshalJSON(b []byte) error {
return t.Inner.UnmarshalJSON(b)
}
func init() {
equality.Semantic.AddFunc(
// Always treat VolatileTime fields as equivalent.
func(a, b VolatileTime) bool {
return true
},
)
}

View File

@@ -1,38 +0,0 @@
// +build !ignore_autogenerated
/*
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 deepcopy-gen. DO NOT EDIT.
package apis
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolatileTime) DeepCopyInto(out *VolatileTime) {
*out = *in
in.Inner.DeepCopyInto(&out.Inner)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolatileTime.
func (in *VolatileTime) DeepCopy() *VolatileTime {
if in == nil {
return nil
}
out := new(VolatileTime)
in.DeepCopyInto(out)
return out
}

View File

@@ -20,7 +20,6 @@ package versioned
import (
authenticationv1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/authentication/v1alpha1"
duckv1alpha1 "github.com/knative/pkg/client/clientset/versioned/typed/duck/v1alpha1"
networkingv1alpha3 "github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
@@ -32,9 +31,6 @@ type Interface interface {
AuthenticationV1alpha1() authenticationv1alpha1.AuthenticationV1alpha1Interface
// Deprecated: please explicitly pick a version if possible.
Authentication() authenticationv1alpha1.AuthenticationV1alpha1Interface
DuckV1alpha1() duckv1alpha1.DuckV1alpha1Interface
// Deprecated: please explicitly pick a version if possible.
Duck() duckv1alpha1.DuckV1alpha1Interface
NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface
// Deprecated: please explicitly pick a version if possible.
Networking() networkingv1alpha3.NetworkingV1alpha3Interface
@@ -45,7 +41,6 @@ type Interface interface {
type Clientset struct {
*discovery.DiscoveryClient
authenticationV1alpha1 *authenticationv1alpha1.AuthenticationV1alpha1Client
duckV1alpha1 *duckv1alpha1.DuckV1alpha1Client
networkingV1alpha3 *networkingv1alpha3.NetworkingV1alpha3Client
}
@@ -60,17 +55,6 @@ func (c *Clientset) Authentication() authenticationv1alpha1.AuthenticationV1alph
return c.authenticationV1alpha1
}
// DuckV1alpha1 retrieves the DuckV1alpha1Client
func (c *Clientset) DuckV1alpha1() duckv1alpha1.DuckV1alpha1Interface {
return c.duckV1alpha1
}
// Deprecated: Duck retrieves the default version of DuckClient.
// Please explicitly pick a version.
func (c *Clientset) Duck() duckv1alpha1.DuckV1alpha1Interface {
return c.duckV1alpha1
}
// NetworkingV1alpha3 retrieves the NetworkingV1alpha3Client
func (c *Clientset) NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface {
return c.networkingV1alpha3
@@ -102,10 +86,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.duckV1alpha1, err = duckv1alpha1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.networkingV1alpha3, err = networkingv1alpha3.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@@ -123,7 +103,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.authenticationV1alpha1 = authenticationv1alpha1.NewForConfigOrDie(c)
cs.duckV1alpha1 = duckv1alpha1.NewForConfigOrDie(c)
cs.networkingV1alpha3 = networkingv1alpha3.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
@@ -134,7 +113,6 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.authenticationV1alpha1 = authenticationv1alpha1.New(c)
cs.duckV1alpha1 = duckv1alpha1.New(c)
cs.networkingV1alpha3 = networkingv1alpha3.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)

View File

@@ -22,8 +22,6 @@ 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"
@@ -85,16 +83,6 @@ func (c *Clientset) Authentication() authenticationv1alpha1.AuthenticationV1alph
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}

View File

@@ -19,7 +19,6 @@ limitations under the License.
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"
@@ -53,6 +52,5 @@ func init() {
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
authenticationv1alpha1.AddToScheme(scheme)
duckv1alpha1.AddToScheme(scheme)
networkingv1alpha3.AddToScheme(scheme)
}

View File

@@ -19,7 +19,6 @@ limitations under the License.
package scheme
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"
@@ -53,6 +52,5 @@ func init() {
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
authenticationv1alpha1.AddToScheme(scheme)
duckv1alpha1.AddToScheme(scheme)
networkingv1alpha3.AddToScheme(scheme)
}

View File

@@ -1,20 +0,0 @@
/*
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 typed clients.
package v1alpha1

View File

@@ -1,105 +0,0 @@
/*
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 v1alpha1
import (
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
"github.com/knative/pkg/client/clientset/versioned/scheme"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
rest "k8s.io/client-go/rest"
)
type DuckV1alpha1Interface interface {
RESTClient() rest.Interface
GenerationalsGetter
KResourcesGetter
TargetsGetter
TopicsGetter
}
// DuckV1alpha1Client is used to interact with features provided by the duck.knative.dev group.
type DuckV1alpha1Client struct {
restClient rest.Interface
}
func (c *DuckV1alpha1Client) Generationals(namespace string) GenerationalInterface {
return newGenerationals(c, namespace)
}
func (c *DuckV1alpha1Client) KResources(namespace string) KResourceInterface {
return newKResources(c, namespace)
}
func (c *DuckV1alpha1Client) Targets(namespace string) TargetInterface {
return newTargets(c, namespace)
}
func (c *DuckV1alpha1Client) Topics(namespace string) TopicInterface {
return newTopics(c, namespace)
}
// NewForConfig creates a new DuckV1alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*DuckV1alpha1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &DuckV1alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new DuckV1alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *DuckV1alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new DuckV1alpha1Client for the given RESTClient.
func New(c rest.Interface) *DuckV1alpha1Client {
return &DuckV1alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *DuckV1alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@@ -1,20 +0,0 @@
/*
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

View File

@@ -1,52 +0,0 @@
/*
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
}

View File

@@ -1,128 +0,0 @@
/*
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
}

View File

@@ -1,140 +0,0 @@
/*
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
}

View File

@@ -1,140 +0,0 @@
/*
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
}

View File

@@ -1,140 +0,0 @@
/*
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
}

View File

@@ -1,27 +0,0 @@
/*
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 v1alpha1
type GenerationalExpansion interface{}
type KResourceExpansion interface{}
type TargetExpansion interface{}
type TopicExpansion interface{}

View File

@@ -1,157 +0,0 @@
/*
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 v1alpha1
import (
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
scheme "github.com/knative/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// GenerationalsGetter has a method to return a GenerationalInterface.
// A group's client should implement this interface.
type GenerationalsGetter interface {
Generationals(namespace string) GenerationalInterface
}
// GenerationalInterface has methods to work with Generational resources.
type GenerationalInterface interface {
Create(*v1alpha1.Generational) (*v1alpha1.Generational, error)
Update(*v1alpha1.Generational) (*v1alpha1.Generational, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha1.Generational, error)
List(opts v1.ListOptions) (*v1alpha1.GenerationalList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Generational, err error)
GenerationalExpansion
}
// generationals implements GenerationalInterface
type generationals struct {
client rest.Interface
ns string
}
// newGenerationals returns a Generationals
func newGenerationals(c *DuckV1alpha1Client, namespace string) *generationals {
return &generationals{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the generational, and returns the corresponding generational object, and an error if there is any.
func (c *generationals) Get(name string, options v1.GetOptions) (result *v1alpha1.Generational, err error) {
result = &v1alpha1.Generational{}
err = c.client.Get().
Namespace(c.ns).
Resource("generationals").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of Generationals that match those selectors.
func (c *generationals) List(opts v1.ListOptions) (result *v1alpha1.GenerationalList, err error) {
result = &v1alpha1.GenerationalList{}
err = c.client.Get().
Namespace(c.ns).
Resource("generationals").
VersionedParams(&opts, scheme.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested generationals.
func (c *generationals) Watch(opts v1.ListOptions) (watch.Interface, error) {
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("generationals").
VersionedParams(&opts, scheme.ParameterCodec).
Watch()
}
// 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 *generationals) Create(generational *v1alpha1.Generational) (result *v1alpha1.Generational, err error) {
result = &v1alpha1.Generational{}
err = c.client.Post().
Namespace(c.ns).
Resource("generationals").
Body(generational).
Do().
Into(result)
return
}
// 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 *generationals) Update(generational *v1alpha1.Generational) (result *v1alpha1.Generational, err error) {
result = &v1alpha1.Generational{}
err = c.client.Put().
Namespace(c.ns).
Resource("generationals").
Name(generational.Name).
Body(generational).
Do().
Into(result)
return
}
// Delete takes name of the generational and deletes it. Returns an error if one occurs.
func (c *generationals) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("generationals").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *generationals) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("generationals").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched generational.
func (c *generationals) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Generational, err error) {
result = &v1alpha1.Generational{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("generationals").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -1,174 +0,0 @@
/*
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 v1alpha1
import (
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
scheme "github.com/knative/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// KResourcesGetter has a method to return a KResourceInterface.
// A group's client should implement this interface.
type KResourcesGetter interface {
KResources(namespace string) KResourceInterface
}
// KResourceInterface has methods to work with KResource resources.
type KResourceInterface interface {
Create(*v1alpha1.KResource) (*v1alpha1.KResource, error)
Update(*v1alpha1.KResource) (*v1alpha1.KResource, error)
UpdateStatus(*v1alpha1.KResource) (*v1alpha1.KResource, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha1.KResource, error)
List(opts v1.ListOptions) (*v1alpha1.KResourceList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.KResource, err error)
KResourceExpansion
}
// kResources implements KResourceInterface
type kResources struct {
client rest.Interface
ns string
}
// newKResources returns a KResources
func newKResources(c *DuckV1alpha1Client, namespace string) *kResources {
return &kResources{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the kResource, and returns the corresponding kResource object, and an error if there is any.
func (c *kResources) Get(name string, options v1.GetOptions) (result *v1alpha1.KResource, err error) {
result = &v1alpha1.KResource{}
err = c.client.Get().
Namespace(c.ns).
Resource("kresources").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of KResources that match those selectors.
func (c *kResources) List(opts v1.ListOptions) (result *v1alpha1.KResourceList, err error) {
result = &v1alpha1.KResourceList{}
err = c.client.Get().
Namespace(c.ns).
Resource("kresources").
VersionedParams(&opts, scheme.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested kResources.
func (c *kResources) Watch(opts v1.ListOptions) (watch.Interface, error) {
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("kresources").
VersionedParams(&opts, scheme.ParameterCodec).
Watch()
}
// 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 *kResources) Create(kResource *v1alpha1.KResource) (result *v1alpha1.KResource, err error) {
result = &v1alpha1.KResource{}
err = c.client.Post().
Namespace(c.ns).
Resource("kresources").
Body(kResource).
Do().
Into(result)
return
}
// 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 *kResources) Update(kResource *v1alpha1.KResource) (result *v1alpha1.KResource, err error) {
result = &v1alpha1.KResource{}
err = c.client.Put().
Namespace(c.ns).
Resource("kresources").
Name(kResource.Name).
Body(kResource).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *kResources) UpdateStatus(kResource *v1alpha1.KResource) (result *v1alpha1.KResource, err error) {
result = &v1alpha1.KResource{}
err = c.client.Put().
Namespace(c.ns).
Resource("kresources").
Name(kResource.Name).
SubResource("status").
Body(kResource).
Do().
Into(result)
return
}
// Delete takes name of the kResource and deletes it. Returns an error if one occurs.
func (c *kResources) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("kresources").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *kResources) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("kresources").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched kResource.
func (c *kResources) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.KResource, err error) {
result = &v1alpha1.KResource{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("kresources").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -1,174 +0,0 @@
/*
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 v1alpha1
import (
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
scheme "github.com/knative/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// TargetsGetter has a method to return a TargetInterface.
// A group's client should implement this interface.
type TargetsGetter interface {
Targets(namespace string) TargetInterface
}
// TargetInterface has methods to work with Target resources.
type TargetInterface interface {
Create(*v1alpha1.Target) (*v1alpha1.Target, error)
Update(*v1alpha1.Target) (*v1alpha1.Target, error)
UpdateStatus(*v1alpha1.Target) (*v1alpha1.Target, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha1.Target, error)
List(opts v1.ListOptions) (*v1alpha1.TargetList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Target, err error)
TargetExpansion
}
// targets implements TargetInterface
type targets struct {
client rest.Interface
ns string
}
// newTargets returns a Targets
func newTargets(c *DuckV1alpha1Client, namespace string) *targets {
return &targets{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the target, and returns the corresponding target object, and an error if there is any.
func (c *targets) Get(name string, options v1.GetOptions) (result *v1alpha1.Target, err error) {
result = &v1alpha1.Target{}
err = c.client.Get().
Namespace(c.ns).
Resource("targets").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of Targets that match those selectors.
func (c *targets) List(opts v1.ListOptions) (result *v1alpha1.TargetList, err error) {
result = &v1alpha1.TargetList{}
err = c.client.Get().
Namespace(c.ns).
Resource("targets").
VersionedParams(&opts, scheme.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested targets.
func (c *targets) Watch(opts v1.ListOptions) (watch.Interface, error) {
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("targets").
VersionedParams(&opts, scheme.ParameterCodec).
Watch()
}
// 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 *targets) Create(target *v1alpha1.Target) (result *v1alpha1.Target, err error) {
result = &v1alpha1.Target{}
err = c.client.Post().
Namespace(c.ns).
Resource("targets").
Body(target).
Do().
Into(result)
return
}
// 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 *targets) Update(target *v1alpha1.Target) (result *v1alpha1.Target, err error) {
result = &v1alpha1.Target{}
err = c.client.Put().
Namespace(c.ns).
Resource("targets").
Name(target.Name).
Body(target).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *targets) UpdateStatus(target *v1alpha1.Target) (result *v1alpha1.Target, err error) {
result = &v1alpha1.Target{}
err = c.client.Put().
Namespace(c.ns).
Resource("targets").
Name(target.Name).
SubResource("status").
Body(target).
Do().
Into(result)
return
}
// Delete takes name of the target and deletes it. Returns an error if one occurs.
func (c *targets) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("targets").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *targets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("targets").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched target.
func (c *targets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Target, err error) {
result = &v1alpha1.Target{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("targets").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -1,174 +0,0 @@
/*
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 v1alpha1
import (
v1alpha1 "github.com/knative/pkg/apis/duck/v1alpha1"
scheme "github.com/knative/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// TopicsGetter has a method to return a TopicInterface.
// A group's client should implement this interface.
type TopicsGetter interface {
Topics(namespace string) TopicInterface
}
// TopicInterface has methods to work with Topic resources.
type TopicInterface interface {
Create(*v1alpha1.Topic) (*v1alpha1.Topic, error)
Update(*v1alpha1.Topic) (*v1alpha1.Topic, error)
UpdateStatus(*v1alpha1.Topic) (*v1alpha1.Topic, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha1.Topic, error)
List(opts v1.ListOptions) (*v1alpha1.TopicList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Topic, err error)
TopicExpansion
}
// topics implements TopicInterface
type topics struct {
client rest.Interface
ns string
}
// newTopics returns a Topics
func newTopics(c *DuckV1alpha1Client, namespace string) *topics {
return &topics{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the topic, and returns the corresponding topic object, and an error if there is any.
func (c *topics) Get(name string, options v1.GetOptions) (result *v1alpha1.Topic, err error) {
result = &v1alpha1.Topic{}
err = c.client.Get().
Namespace(c.ns).
Resource("topics").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of Topics that match those selectors.
func (c *topics) List(opts v1.ListOptions) (result *v1alpha1.TopicList, err error) {
result = &v1alpha1.TopicList{}
err = c.client.Get().
Namespace(c.ns).
Resource("topics").
VersionedParams(&opts, scheme.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested topics.
func (c *topics) Watch(opts v1.ListOptions) (watch.Interface, error) {
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("topics").
VersionedParams(&opts, scheme.ParameterCodec).
Watch()
}
// 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 *topics) Create(topic *v1alpha1.Topic) (result *v1alpha1.Topic, err error) {
result = &v1alpha1.Topic{}
err = c.client.Post().
Namespace(c.ns).
Resource("topics").
Body(topic).
Do().
Into(result)
return
}
// 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 *topics) Update(topic *v1alpha1.Topic) (result *v1alpha1.Topic, err error) {
result = &v1alpha1.Topic{}
err = c.client.Put().
Namespace(c.ns).
Resource("topics").
Name(topic.Name).
Body(topic).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *topics) UpdateStatus(topic *v1alpha1.Topic) (result *v1alpha1.Topic, err error) {
result = &v1alpha1.Topic{}
err = c.client.Put().
Namespace(c.ns).
Resource("topics").
Name(topic.Name).
SubResource("status").
Body(topic).
Do().
Into(result)
return
}
// Delete takes name of the topic and deletes it. Returns an error if one occurs.
func (c *topics) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("topics").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *topics) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("topics").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched topic.
func (c *topics) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Topic, err error) {
result = &v1alpha1.Topic{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("topics").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -1,49 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package equality
import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
)
// Semantic can do semantic deep equality checks for api objects.
// Example: apiequality.Semantic.DeepEqual(aPod, aPodWithNonNilButEmptyMaps) == true
var Semantic = conversion.EqualitiesOrDie(
func(a, b resource.Quantity) bool {
// Ignore formatting, only care that numeric value stayed the same.
// TODO: if we decide it's important, it should be safe to start comparing the format.
//
// Uninitialized quantities are equivalent to 0 quantities.
return a.Cmp(b) == 0
},
func(a, b metav1.MicroTime) bool {
return a.UTC() == b.UTC()
},
func(a, b metav1.Time) bool {
return a.UTC() == b.UTC()
},
func(a, b labels.Selector) bool {
return a.String() == b.String()
},
func(a, b fields.Selector) bool {
return a.String() == b.String()
},
)