Add Istio virtual service and signal packages

This commit is contained in:
stefanprodan 2019-03-06 01:43:09 +02:00
parent f7c4d5aa0b
commit b0b6198ec8
39 changed files with 1186 additions and 363 deletions

View File

@ -2,24 +2,22 @@ package main
import (
"flag"
"go.uber.org/zap"
"log"
"time"
_ "github.com/istio/glog"
istioclientset "github.com/knative/pkg/client/clientset/versioned"
"github.com/knative/pkg/signals"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
informers "github.com/stefanprodan/flagger/pkg/client/informers/externalversions"
"github.com/stefanprodan/flagger/pkg/controller"
"github.com/stefanprodan/flagger/pkg/logging"
"github.com/stefanprodan/flagger/pkg/notifier"
"github.com/stefanprodan/flagger/pkg/server"
"github.com/stefanprodan/flagger/pkg/signals"
"github.com/stefanprodan/flagger/pkg/version"
"go.uber.org/zap"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
"log"
"time"
)
var (
@ -77,7 +75,7 @@ func main() {
logger.Fatalf("Error building kubernetes clientset: %v", err)
}
istioClient, err := istioclientset.NewForConfig(cfg)
istioClient, err := clientset.NewForConfig(cfg)
if err != nil {
logger.Fatalf("Error building istio clientset: %v", err)
}

View File

@ -2,9 +2,9 @@ package main
import (
"flag"
"github.com/knative/pkg/signals"
"github.com/stefanprodan/flagger/pkg/loadtester"
"github.com/stefanprodan/flagger/pkg/logging"
"github.com/stefanprodan/flagger/pkg/signals"
"go.uber.org/zap"
"log"
"time"

View File

@ -23,6 +23,6 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-ge
${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \
github.com/stefanprodan/flagger/pkg/client github.com/stefanprodan/flagger/pkg/apis \
flagger:v1alpha3 \
"istio:v1alpha3 flagger:v1alpha3" \
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt

View File

@ -17,7 +17,7 @@ limitations under the License.
package v1alpha3
import (
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
istiov1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
hpav1 "k8s.io/api/autoscaling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"time"

View File

@ -21,7 +21,7 @@ limitations under the License.
package v1alpha3
import (
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
istiov1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
v1 "k8s.io/api/autoscaling/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)

View File

@ -0,0 +1,19 @@
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.
// exact string match
Exact string `json:"exact,omitempty"`
// prefix-based match
Prefix string `json:"prefix,omitempty"`
// suffix-based match.
Suffix string `json:"suffix,omitempty"`
// ECMAscript style regex-based match
Regex string `json:"regex,omitempty"`
}

View File

@ -0,0 +1,5 @@
package istio
const (
GroupName = "networking.istio.io"
)

View File

@ -0,0 +1,7 @@
// 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=networking.istio.io
package v1alpha3

View File

@ -1,23 +1,7 @@
/*
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 v1alpha3
import (
"github.com/knative/pkg/apis/istio"
"github.com/stefanprodan/flagger/pkg/apis/istio"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -45,11 +29,7 @@ var (
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&VirtualService{},
&Gateway{},
&DestinationRule{},
&VirtualServiceList{},
&GatewayList{},
&DestinationRuleList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil

View File

@ -1,23 +1,8 @@
/*
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.
*/
// proto: https://github.com/istio/api/blob/master/networking/v1alpha3/virtual_service.proto
package v1alpha3
import (
"github.com/knative/pkg/apis/istio/common/v1alpha1"
"github.com/stefanprodan/flagger/pkg/apis/istio/common/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -32,7 +17,7 @@ type VirtualService struct {
Spec VirtualServiceSpec `json:"spec"`
}
// A VirtualService defines a set of traffic routing rules to apply when a host is
// VirtualServiceSpec defines a set of traffic routing rules to apply when a host is
// addressed. Each routing rule defines matching criteria for traffic of a specific
// protocol. If the traffic is matched, then it is sent to a named destination service
// (or subset/version of it) defined in the registry.
@ -40,107 +25,264 @@ type VirtualService struct {
// The source of traffic can also be matched in a routing rule. This allows routing
// to be customized for specific client contexts.
//
// The following example routes all HTTP traffic by default to
// The following example on Kubernetes, routes all HTTP traffic by default to
// pods of the reviews service with label "version: v1". In addition,
// HTTP requests containing /wpcatalog/, /consumercatalog/ url prefixes will
// be rewritten to /newcatalog and sent to pods with label "version: v2". The
// rules will be applied at the gateway named "bookinfo" as well as at all
// the sidecars in the mesh (indicated by the reserved gateway name
// "mesh").
// HTTP requests with path starting with /wpcatalog/ or /consumercatalog/ will
// be rewritten to /newcatalog and sent to pods with label "version: v2".
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: reviews-route
// spec:
// hosts:
// - reviews
// gateways: # if omitted, defaults to "mesh"
// - bookinfo
// - mesh
// http:
// - match:
// - uri:
// prefix: "/wpcatalog"
// - uri:
// prefix: "/consumercatalog"
// rewrite:
// uri: "/newcatalog"
// route:
// - destination:
// host: reviews
// subset: v2
// - route:
// - destination:
// host: reviews
// subset: v1
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: reviews-route
// spec:
// hosts:
// - reviews.prod.svc.cluster.local
// http:
// - match:
// - uri:
// prefix: "/wpcatalog"
// - uri:
// prefix: "/consumercatalog"
// rewrite:
// uri: "/newcatalog"
// route:
// - destination:
// host: reviews.prod.svc.cluster.local
// subset: v2
// - route:
// - destination:
// host: reviews.prod.svc.cluster.local
// subset: v1
// ```
//
// A subset/version of a route destination is identified with a reference
// to a named service subset which must be declared in a corresponding
// DestinationRule.
// `DestinationRule`.
//
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
// name: reviews-destination
// spec:
// host: reviews
// subsets:
// - name: v1
// labels:
// version: v1
// - name: v2
// labels:
// version: v2
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
// name: reviews-destination
// spec:
// host: reviews.prod.svc.cluster.local
// subsets:
// - name: v1
// labels:
// version: v1
// - name: v2
// labels:
// version: v2
// ```
//
// A host name can be defined by only one VirtualService. A single
// VirtualService can be used to describe traffic properties for multiple
// HTTP and TCP ports.
type VirtualServiceSpec struct {
// REQUIRED. The destination address for traffic captured by this virtual
// service. Could be a DNS name with wildcard prefix or a CIDR
// prefix. Depending on the platform, short-names can also be used
// instead of a FQDN (i.e. has no dots in the name). In such a scenario,
// the FQDN of the host would be derived based on the underlying
// platform.
// REQUIRED. The destination hosts to which traffic is being sent. Could
// be a DNS name with wildcard prefix or an IP address. Depending on the
// platform, short-names can also be used instead of a FQDN (i.e. has no
// dots in the name). In such a scenario, the FQDN of the host would be
// derived based on the underlying platform.
//
// For example on Kubernetes, when hosts contains a short name, Istio will
// interpret the short name based on the namespace of the rule. Thus, when a
// client namespace applies a rule in the "default" namespace containing a name
// "reviews, Istio will setup routes to the "reviews.default.svc.cluster.local"
// service. However, if a different name such as "reviews.sales.svc.cluster.local"
// is used, it would be treated as a FQDN during virtual host matching.
// In Consul, a plain service name would be resolved to the FQDN
// "reviews.service.consul".
// **A host name can be defined by only one VirtualService**. A single
// VirtualService can be used to describe traffic properties for multiple
// HTTP and TCP ports.
//
// Note that the hosts field applies to both HTTP and TCP
// services. Service inside the mesh, i.e., those found in the service
// registry, must always be referred to using their alphanumeric
// names. IP addresses or CIDR prefixes are allowed only for services
// defined via the Gateway.
// *Note for Kubernetes users*: When short names are used (e.g. "reviews"
// instead of "reviews.default.svc.cluster.local"), Istio will interpret
// the short name based on the namespace of the rule, not the service. A
// rule in the "default" namespace containing a host "reviews will be
// interpreted as "reviews.default.svc.cluster.local", irrespective of
// the actual namespace associated with the reviews service. _To avoid
// potential misconfigurations, it is recommended to always use fully
// qualified domain names over short names._
//
// The hosts field applies to both HTTP and TCP services. Service inside
// the mesh, i.e., those found in the service registry, must always be
// referred to using their alphanumeric names. IP addresses are allowed
// only for services defined via the Gateway.
Hosts []string `json:"hosts"`
// The names of gateways and sidecars that should apply these routes. A
// single VirtualService is used for sidecars inside the mesh as well
// as for one or more gateways. The selection condition imposed by this field
// can be overridden using the source field in the match conditions of HTTP/TCP
// routes. The reserved word "mesh" is used to imply all the sidecars in
// the mesh. When this field is omitted, the default gateway ("mesh")
// will be used, which would apply the rule to all sidecars in the
// mesh. If a list of gateway names is provided, the rules will apply
// only to the gateways. To apply the rules to both gateways and sidecars,
// specify "mesh" as one of the gateway names.
// single VirtualService is used for sidecars inside the mesh as well as
// for one or more gateways. The selection condition imposed by this
// field can be overridden using the source field in the match conditions
// of protocol-specific routes. The reserved word `mesh` is used to imply
// all the sidecars in the mesh. When this field is omitted, the default
// gateway (`mesh`) will be used, which would apply the rule to all
// sidecars in the mesh. If a list of gateway names is provided, the
// rules will apply only to the gateways. To apply the rules to both
// gateways and sidecars, specify `mesh` as one of the gateway names.
Gateways []string `json:"gateways,omitempty"`
// An ordered list of route rules for HTTP traffic.
// The first rule matching an incoming request is used.
// An ordered list of route rules for HTTP traffic. HTTP routes will be
// applied to platform service ports named 'http-*'/'http2-*'/'grpc-*', gateway
// ports with protocol HTTP/HTTP2/GRPC/ TLS-terminated-HTTPS and service
// entry ports using HTTP/HTTP2/GRPC protocols. The first rule matching
// an incoming request is used.
Http []HTTPRoute `json:"http,omitempty"`
// An ordered list of route rules for TCP traffic.
// The first rule matching an incoming request is used.
// An ordered list of route rules for opaque TCP traffic. TCP routes will
// be applied to any port that is not a HTTP or TLS port. The first rule
// matching an incoming request is used.
Tcp []TCPRoute `json:"tcp,omitempty"`
}
// Destination indicates the network addressable service to which the
// request/connection will be sent after processing a routing rule. The
// destination.host should unambiguously refer to a service in the service
// registry. Istio's service registry is composed of all the services found
// in the platform's service registry (e.g., Kubernetes services, Consul
// services), as well as services declared through the
// [ServiceEntry](#ServiceEntry) resource.
//
// *Note for Kubernetes users*: When short names are used (e.g. "reviews"
// instead of "reviews.default.svc.cluster.local"), Istio will interpret
// the short name based on the namespace of the rule, not the service. A
// rule in the "default" namespace containing a host "reviews will be
// interpreted as "reviews.default.svc.cluster.local", irrespective of the
// actual namespace associated with the reviews service. _To avoid potential
// misconfigurations, it is recommended to always use fully qualified
// domain names over short names._
//
// The following Kubernetes example routes all traffic by default to pods
// of the reviews service with label "version: v1" (i.e., subset v1), and
// some to subset v2, in a kubernetes environment.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: reviews-route
// namespace: foo
// spec:
// hosts:
// - reviews # interpreted as reviews.foo.svc.cluster.local
// http:
// - match:
// - uri:
// prefix: "/wpcatalog"
// - uri:
// prefix: "/consumercatalog"
// rewrite:
// uri: "/newcatalog"
// route:
// - destination:
// host: reviews # interpreted as reviews.foo.svc.cluster.local
// subset: v2
// - route:
// - destination:
// host: reviews # interpreted as reviews.foo.svc.cluster.local
// subset: v1
// ```
//
// And the associated DestinationRule
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
// name: reviews-destination
// namespace: foo
// spec:
// host: reviews # interpreted as reviews.foo.svc.cluster.local
// subsets:
// - name: v1
// labels:
// version: v1
// - name: v2
// labels:
// version: v2
// ```
//
// The following VirtualService sets a timeout of 5s for all calls to
// productpage.prod.svc.cluster.local service in Kubernetes. Notice that
// there are no subsets defined in this rule. Istio will fetch all
// instances of productpage.prod.svc.cluster.local service from the service
// registry and populate the sidecar's load balancing pool. Also, notice
// that this rule is set in the istio-system namespace but uses the fully
// qualified domain name of the productpage service,
// productpage.prod.svc.cluster.local. Therefore the rule's namespace does
// not have an impact in resolving the name of the productpage service.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: my-productpage-rule
// namespace: istio-system
// spec:
// hosts:
// - productpage.prod.svc.cluster.local # ignores rule namespace
// http:
// - timeout: 5s
// route:
// - destination:
// host: productpage.prod.svc.cluster.local
// ```
//
// To control routing for traffic bound to services outside the mesh, external
// services must first be added to Istio's internal service registry using the
// ServiceEntry resource. VirtualServices can then be defined to control traffic
// bound to these external services. For example, the following rules define a
// Service for wikipedia.org and set a timeout of 5s for http requests.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
// name: external-svc-wikipedia
// spec:
// hosts:
// - wikipedia.org
// location: MESH_EXTERNAL
// ports:
// - number: 80
// name: example-http
// protocol: HTTP
// resolution: DNS
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: my-wiki-rule
// spec:
// hosts:
// - wikipedia.org
// http:
// - timeout: 5s
// route:
// - destination:
// host: wikipedia.org
// ```
type Destination struct {
// REQUIRED. The name of a service from the service registry. Service
// names are looked up from the platform's service registry (e.g.,
// Kubernetes services, Consul services, etc.) and from the hosts
// declared by [ServiceEntry](#ServiceEntry). Traffic forwarded to
// destinations that are not found in either of the two, will be dropped.
//
// *Note for Kubernetes users*: When short names are used (e.g. "reviews"
// instead of "reviews.default.svc.cluster.local"), Istio will interpret
// the short name based on the namespace of the rule, not the service. A
// rule in the "default" namespace containing a host "reviews will be
// interpreted as "reviews.default.svc.cluster.local", irrespective of
// the actual namespace associated with the reviews service. _To avoid
// potential misconfigurations, it is recommended to always use fully
// qualified domain names over short names._
Host string `json:"host"`
// The name of a subset within the service. Applicable only to services
// within the mesh. The subset must be defined in a corresponding
// DestinationRule.
Subset string `json:"subset,omitempty"`
// Specifies the port on the host that is being addressed. If a service
// exposes only a single port it is not required to explicitly select the
// port.
Port PortSelector `json:"port,omitempty"`
}
// Describes match conditions and actions for routing HTTP/1.1, HTTP2, and
// gRPC traffic. See VirtualService for usage examples.
type HTTPRoute struct {
@ -166,15 +308,6 @@ type HTTPRoute struct {
// Redirect primitive. Rewrite will be performed before forwarding.
Rewrite *HTTPRewrite `json:"rewrite,omitempty"`
// Indicates that a HTTP/1.1 client connection to this particular route
// should be allowed (and expected) to upgrade to a WebSocket connection.
// The default is false. Istio's reference sidecar implementation (Envoy)
// expects the first request to this route to contain the WebSocket
// upgrade headers. Otherwise, the request will be rejected. Note that
// Websocket allows secondary protocol negotiation which may then be
// subject to further routing rules based on the protocol selected.
WebsocketUpgrade bool `json:"websocketUpgrade,omitempty"`
// Timeout for HTTP requests.
Timeout string `json:"timeout,omitempty"`
@ -192,6 +325,8 @@ type HTTPRoute struct {
// destination.
Mirror *Destination `json:"mirror,omitempty"`
CorsPolicy *CorsPolicy `json:"CorsPolicy,omitempty"`
// Additional HTTP headers to add before forwarding a request to the
// destination service.
AppendHeaders map[string]string `json:"appendHeaders,omitempty"`
@ -283,6 +418,22 @@ type HTTPMatchRequest struct {
//
// **Note:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.
Headers map[string]v1alpha1.StringMatch `json:"headers,omitempty"`
// Specifies the ports on the host that is being addressed. Many services
// only expose a single port or label ports with the protocols they support,
// in these cases it is not required to explicitly select the port.
Port uint32 `json:"port,omitempty"`
// One or more labels that constrain the applicability of a rule to
// workloads with the given labels. If the VirtualService has a list of
// gateways specified at the top, it should include the reserved gateway
// `mesh` in order for this field to be applicable.
SourceLabels map[string]string `json:"sourceLabels,omitempty"`
// Names of gateways where the rule should be applied to. Gateway names
// at the top of the VirtualService (if any) are overridden. The gateway match is
// independent of sourceLabels.
Gateways []string `json:"gateways,omitempty"`
}
type DestinationWeight struct {
@ -297,137 +448,6 @@ type DestinationWeight struct {
Weight int `json:"weight"`
}
// Destination indicates the network addressable service to which the
// request/connection will be sent after processing a routing rule. The
// destination.name should unambiguously refer to a service in the service
// registry. It can be a short name or a fully qualified domain name from
// the service registry, a resolvable DNS name, an IP address or a service
// name from the service registry and a subset name. The order of inference
// is as follows:
//
// 1. Service registry lookup. The entire name is looked up in the service
// registry. If the lookup succeeds, the search terminates. The requests
// will be routed to any instance of the service in the mesh. When the
// service name consists of a single word, the FQDN will be constructed in
// a platform specific manner. For example, in Kubernetes, the namespace
// associated with the routing rule will be used to identify the service as
// <servicename>.<rulenamespace>. However, if the service name contains
// multiple words separated by a dot (e.g., reviews.prod), the name in its
// entirety would be looked up in the service registry.
//
// 2. Runtime DNS lookup by the proxy. If step 1 fails, and the name is not
// an IP address, it will be considered as a DNS name that is not in the
// service registry (e.g., wikipedia.org). The sidecar/gateway will resolve
// the DNS and load balance requests appropriately. See Envoy's strict_dns
// for details.
//
// The following example routes all traffic by default to pods of the
// reviews service with label "version: v1" (i.e., subset v1), and some
// to subset v2, in a kubernetes environment.
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: reviews-route
// spec:
// hosts:
// - reviews # namespace is same as the client/caller's namespace
// http:
// - match:
// - uri:
// prefix: "/wpcatalog"
// - uri:
// prefix: "/consumercatalog"
// rewrite:
// uri: "/newcatalog"
// route:
// - destination:
// host: reviews
// subset: v2
// - route:
// - destination:
// host: reviews
// subset: v1
//
// And the associated DestinationRule
//
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
// name: reviews-destination
// spec:
// host: reviews
// subsets:
// - name: v1
// labels:
// version: v1
// - name: v2
// labels:
// version: v2
//
// The following VirtualService sets a timeout of 5s for all calls to
// productpage.prod service. Notice that there are no subsets defined in
// this rule. Istio will fetch all instances of productpage.prod service
// from the service registry and populate the sidecar's load balancing
// pool.
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: my-productpage-rule
// spec:
// hosts:
// - productpage.prod # in kubernetes, this applies only to prod namespace
// http:
// - timeout: 5s
// route:
// - destination:
// host: productpage.prod
//
// The following sets a timeout of 5s for all calls to the external
// service wikipedia.org, as there is no internal service of that name.
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: my-wiki-rule
// spec:
// hosts:
// - wikipedia.org
// http:
// - timeout: 5s
// route:
// - destination:
// host: wikipedia.org
//
type Destination struct {
// REQUIRED. The name of a service from the service registry. Service
// names are looked up from the platform's service registry (e.g.,
// Kubernetes services, Consul services, etc.) and from the hosts
// declared by [ServiceEntry](#ServiceEntry). Traffic forwarded to
// destinations that are not found in either of the two, will be dropped.
//
// *Note for Kubernetes users*: When short names are used (e.g. "reviews"
// instead of "reviews.default.svc.cluster.local"), Istio will interpret
// the short name based on the namespace of the rule, not the service. A
// rule in the "default" namespace containing a host "reviews will be
// interpreted as "reviews.default.svc.cluster.local", irrespective of
// the actual namespace associated with the reviews service. _To avoid
// potential misconfigurations, it is recommended to always use fully
// qualified domain names over short names._
Host string `json:"host"`
// The name of a subset within the service. Applicable only to services
// within the mesh. The subset must be defined in a corresponding
// DestinationRule.
Subset string `json:"subset,omitempty"`
// Specifies the port on the host that is being addressed. If a service
// exposes only a single port it is not required to explicitly select the
// port.
Port PortSelector `json:"port,omitempty"`
}
// PortSelector specifies the number of a port to be used for
// matching or selection for final routing.
type PortSelector struct {
@ -578,21 +598,24 @@ type HTTPRewrite struct {
// example, the following rule sets the maximum number of retries to 3 when
// calling ratings:v1 service, with a 2s timeout per retry attempt.
//
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: ratings-route
// spec:
// hosts:
// - ratings
// http:
// - route:
// - destination:
// host: ratings
// subset: v1
// retries:
// attempts: 3
// perTryTimeout: 2s
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
// name: ratings-route
// spec:
// hosts:
// - ratings.prod.svc.cluster.local
// http:
// - route:
// - destination:
// host: ratings.prod.svc.cluster.local
// subset: v1
// retries:
// attempts: 3
// perTryTimeout: 2s
// retryOn: gateway-error,connect-failure,refused-stream
// ```
//
type HTTPRetry struct {
// REQUIRED. Number of retries for a given request. The interval
@ -602,6 +625,13 @@ type HTTPRetry struct {
// Timeout per retry attempt for a given request. format: 1h/1m/1s/1ms. MUST BE >=1ms.
PerTryTimeout string `json:"perTryTimeout"`
// Specifies the conditions under which retry takes place.
// One or more policies can be specified using a , delimited list.
// The supported policies can be found in
// <https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/router_filter#x-envoy-retry-on>
// and <https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/router_filter#x-envoy-retry-grpc-on>
RetryOn string `json:"retryOn"`
}
// Describes the Cross-Origin Resource Sharing (CORS) policy, for a given
@ -766,4 +796,4 @@ type VirtualServiceList struct {
metav1.ListMeta `json:"metadata"`
Items []VirtualService `json:"items"`
}
}

View File

@ -0,0 +1,497 @@
// +build !ignore_autogenerated
/*
Copyright The Flagger 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 v1alpha3
import (
v1alpha1 "github.com/stefanprodan/flagger/pkg/apis/istio/common/v1alpha1"
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 *CorsPolicy) DeepCopyInto(out *CorsPolicy) {
*out = *in
if in.AllowOrigin != nil {
in, out := &in.AllowOrigin, &out.AllowOrigin
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.AllowMethods != nil {
in, out := &in.AllowMethods, &out.AllowMethods
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.AllowHeaders != nil {
in, out := &in.AllowHeaders, &out.AllowHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ExposeHeaders != nil {
in, out := &in.ExposeHeaders, &out.ExposeHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CorsPolicy.
func (in *CorsPolicy) DeepCopy() *CorsPolicy {
if in == nil {
return nil
}
out := new(CorsPolicy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Destination) DeepCopyInto(out *Destination) {
*out = *in
out.Port = in.Port
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Destination.
func (in *Destination) DeepCopy() *Destination {
if in == nil {
return nil
}
out := new(Destination)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DestinationWeight) DeepCopyInto(out *DestinationWeight) {
*out = *in
out.Destination = in.Destination
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationWeight.
func (in *DestinationWeight) DeepCopy() *DestinationWeight {
if in == nil {
return nil
}
out := new(DestinationWeight)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPFaultInjection) DeepCopyInto(out *HTTPFaultInjection) {
*out = *in
if in.Delay != nil {
in, out := &in.Delay, &out.Delay
*out = new(InjectDelay)
**out = **in
}
if in.Abort != nil {
in, out := &in.Abort, &out.Abort
*out = new(InjectAbort)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPFaultInjection.
func (in *HTTPFaultInjection) DeepCopy() *HTTPFaultInjection {
if in == nil {
return nil
}
out := new(HTTPFaultInjection)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPMatchRequest) DeepCopyInto(out *HTTPMatchRequest) {
*out = *in
if in.Uri != nil {
in, out := &in.Uri, &out.Uri
*out = new(v1alpha1.StringMatch)
**out = **in
}
if in.Scheme != nil {
in, out := &in.Scheme, &out.Scheme
*out = new(v1alpha1.StringMatch)
**out = **in
}
if in.Method != nil {
in, out := &in.Method, &out.Method
*out = new(v1alpha1.StringMatch)
**out = **in
}
if in.Authority != nil {
in, out := &in.Authority, &out.Authority
*out = new(v1alpha1.StringMatch)
**out = **in
}
if in.Headers != nil {
in, out := &in.Headers, &out.Headers
*out = make(map[string]v1alpha1.StringMatch, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.SourceLabels != nil {
in, out := &in.SourceLabels, &out.SourceLabels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Gateways != nil {
in, out := &in.Gateways, &out.Gateways
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPMatchRequest.
func (in *HTTPMatchRequest) DeepCopy() *HTTPMatchRequest {
if in == nil {
return nil
}
out := new(HTTPMatchRequest)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPRedirect) DeepCopyInto(out *HTTPRedirect) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRedirect.
func (in *HTTPRedirect) DeepCopy() *HTTPRedirect {
if in == nil {
return nil
}
out := new(HTTPRedirect)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPRetry) DeepCopyInto(out *HTTPRetry) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRetry.
func (in *HTTPRetry) DeepCopy() *HTTPRetry {
if in == nil {
return nil
}
out := new(HTTPRetry)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPRewrite) DeepCopyInto(out *HTTPRewrite) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRewrite.
func (in *HTTPRewrite) DeepCopy() *HTTPRewrite {
if in == nil {
return nil
}
out := new(HTTPRewrite)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
*out = *in
if in.Match != nil {
in, out := &in.Match, &out.Match
*out = make([]HTTPMatchRequest, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Route != nil {
in, out := &in.Route, &out.Route
*out = make([]DestinationWeight, len(*in))
copy(*out, *in)
}
if in.Redirect != nil {
in, out := &in.Redirect, &out.Redirect
*out = new(HTTPRedirect)
**out = **in
}
if in.Rewrite != nil {
in, out := &in.Rewrite, &out.Rewrite
*out = new(HTTPRewrite)
**out = **in
}
if in.Retries != nil {
in, out := &in.Retries, &out.Retries
*out = new(HTTPRetry)
**out = **in
}
if in.Fault != nil {
in, out := &in.Fault, &out.Fault
*out = new(HTTPFaultInjection)
(*in).DeepCopyInto(*out)
}
if in.Mirror != nil {
in, out := &in.Mirror, &out.Mirror
*out = new(Destination)
**out = **in
}
if in.CorsPolicy != nil {
in, out := &in.CorsPolicy, &out.CorsPolicy
*out = new(CorsPolicy)
(*in).DeepCopyInto(*out)
}
if in.AppendHeaders != nil {
in, out := &in.AppendHeaders, &out.AppendHeaders
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.RemoveResponseHeaders != nil {
in, out := &in.RemoveResponseHeaders, &out.RemoveResponseHeaders
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute.
func (in *HTTPRoute) DeepCopy() *HTTPRoute {
if in == nil {
return nil
}
out := new(HTTPRoute)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InjectAbort) DeepCopyInto(out *InjectAbort) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InjectAbort.
func (in *InjectAbort) DeepCopy() *InjectAbort {
if in == nil {
return nil
}
out := new(InjectAbort)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InjectDelay) DeepCopyInto(out *InjectDelay) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InjectDelay.
func (in *InjectDelay) DeepCopy() *InjectDelay {
if in == nil {
return nil
}
out := new(InjectDelay)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *L4MatchAttributes) DeepCopyInto(out *L4MatchAttributes) {
*out = *in
if in.SourceLabel != nil {
in, out := &in.SourceLabel, &out.SourceLabel
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Gateways != nil {
in, out := &in.Gateways, &out.Gateways
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L4MatchAttributes.
func (in *L4MatchAttributes) DeepCopy() *L4MatchAttributes {
if in == nil {
return nil
}
out := new(L4MatchAttributes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PortSelector) DeepCopyInto(out *PortSelector) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortSelector.
func (in *PortSelector) DeepCopy() *PortSelector {
if in == nil {
return nil
}
out := new(PortSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TCPRoute) DeepCopyInto(out *TCPRoute) {
*out = *in
if in.Match != nil {
in, out := &in.Match, &out.Match
*out = make([]L4MatchAttributes, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
out.Route = in.Route
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPRoute.
func (in *TCPRoute) DeepCopy() *TCPRoute {
if in == nil {
return nil
}
out := new(TCPRoute)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VirtualService) DeepCopyInto(out *VirtualService) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualService.
func (in *VirtualService) DeepCopy() *VirtualService {
if in == nil {
return nil
}
out := new(VirtualService)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VirtualService) 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 *VirtualServiceList) DeepCopyInto(out *VirtualServiceList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]VirtualService, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceList.
func (in *VirtualServiceList) DeepCopy() *VirtualServiceList {
if in == nil {
return nil
}
out := new(VirtualServiceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VirtualServiceList) 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 *VirtualServiceSpec) DeepCopyInto(out *VirtualServiceSpec) {
*out = *in
if in.Hosts != nil {
in, out := &in.Hosts, &out.Hosts
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Gateways != nil {
in, out := &in.Gateways, &out.Gateways
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Http != nil {
in, out := &in.Http, &out.Http
*out = make([]HTTPRoute, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Tcp != nil {
in, out := &in.Tcp, &out.Tcp
*out = make([]TCPRoute, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceSpec.
func (in *VirtualServiceSpec) DeepCopy() *VirtualServiceSpec {
if in == nil {
return nil
}
out := new(VirtualServiceSpec)
in.DeepCopyInto(out)
return out
}

View File

@ -20,6 +20,7 @@ package versioned
import (
flaggerv1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha3"
networkingv1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol"
@ -30,13 +31,17 @@ type Interface interface {
FlaggerV1alpha3() flaggerv1alpha3.FlaggerV1alpha3Interface
// Deprecated: please explicitly pick a version if possible.
Flagger() flaggerv1alpha3.FlaggerV1alpha3Interface
NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface
// Deprecated: please explicitly pick a version if possible.
Networking() networkingv1alpha3.NetworkingV1alpha3Interface
}
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
type Clientset struct {
*discovery.DiscoveryClient
flaggerV1alpha3 *flaggerv1alpha3.FlaggerV1alpha3Client
flaggerV1alpha3 *flaggerv1alpha3.FlaggerV1alpha3Client
networkingV1alpha3 *networkingv1alpha3.NetworkingV1alpha3Client
}
// FlaggerV1alpha3 retrieves the FlaggerV1alpha3Client
@ -50,6 +55,17 @@ func (c *Clientset) Flagger() flaggerv1alpha3.FlaggerV1alpha3Interface {
return c.flaggerV1alpha3
}
// NetworkingV1alpha3 retrieves the NetworkingV1alpha3Client
func (c *Clientset) NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface {
return c.networkingV1alpha3
}
// Deprecated: Networking retrieves the default version of NetworkingClient.
// Please explicitly pick a version.
func (c *Clientset) Networking() networkingv1alpha3.NetworkingV1alpha3Interface {
return c.networkingV1alpha3
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
@ -70,6 +86,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.networkingV1alpha3, err = networkingv1alpha3.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
@ -83,6 +103,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.flaggerV1alpha3 = flaggerv1alpha3.NewForConfigOrDie(c)
cs.networkingV1alpha3 = networkingv1alpha3.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs
@ -92,6 +113,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.flaggerV1alpha3 = flaggerv1alpha3.New(c)
cs.networkingV1alpha3 = networkingv1alpha3.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs

View File

@ -22,6 +22,8 @@ import (
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
flaggerv1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha3"
fakeflaggerv1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha3/fake"
networkingv1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
fakenetworkingv1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
@ -80,3 +82,13 @@ func (c *Clientset) FlaggerV1alpha3() flaggerv1alpha3.FlaggerV1alpha3Interface {
func (c *Clientset) Flagger() flaggerv1alpha3.FlaggerV1alpha3Interface {
return &fakeflaggerv1alpha3.FakeFlaggerV1alpha3{Fake: &c.Fake}
}
// NetworkingV1alpha3 retrieves the NetworkingV1alpha3Client
func (c *Clientset) NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface {
return &fakenetworkingv1alpha3.FakeNetworkingV1alpha3{Fake: &c.Fake}
}
// Networking retrieves the NetworkingV1alpha3Client
func (c *Clientset) Networking() networkingv1alpha3.NetworkingV1alpha3Interface {
return &fakenetworkingv1alpha3.FakeNetworkingV1alpha3{Fake: &c.Fake}
}

View File

@ -20,6 +20,7 @@ package fake
import (
flaggerv1alpha3 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
networkingv1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -51,4 +52,5 @@ func init() {
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
flaggerv1alpha3.AddToScheme(scheme)
networkingv1alpha3.AddToScheme(scheme)
}

View File

@ -20,6 +20,7 @@ package scheme
import (
flaggerv1alpha3 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
networkingv1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -51,4 +52,5 @@ func init() {
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
flaggerv1alpha3.AddToScheme(scheme)
networkingv1alpha3.AddToScheme(scheme)
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ limitations under the License.
package fake
import (
v1alpha3 "github.com/knative/pkg/client/clientset/versioned/typed/istio/v1alpha3"
v1alpha3 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
@ -28,14 +28,6 @@ type FakeNetworkingV1alpha3 struct {
*testing.Fake
}
func (c *FakeNetworkingV1alpha3) DestinationRules(namespace string) v1alpha3.DestinationRuleInterface {
return &FakeDestinationRules{c, namespace}
}
func (c *FakeNetworkingV1alpha3) Gateways(namespace string) v1alpha3.GatewayInterface {
return &FakeGateways{c, namespace}
}
func (c *FakeNetworkingV1alpha3) VirtualServices(namespace string) v1alpha3.VirtualServiceInterface {
return &FakeVirtualServices{c, namespace}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ limitations under the License.
package fake
import (
v1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
v1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,6 +16,6 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
package v1alpha3
type PolicyExpansion interface{}
type VirtualServiceExpansion interface{}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -19,16 +19,14 @@ limitations under the License.
package v1alpha3
import (
v1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
"github.com/knative/pkg/client/clientset/versioned/scheme"
v1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
"github.com/stefanprodan/flagger/pkg/client/clientset/versioned/scheme"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
rest "k8s.io/client-go/rest"
)
type NetworkingV1alpha3Interface interface {
RESTClient() rest.Interface
DestinationRulesGetter
GatewaysGetter
VirtualServicesGetter
}
@ -37,14 +35,6 @@ type NetworkingV1alpha3Client struct {
restClient rest.Interface
}
func (c *NetworkingV1alpha3Client) DestinationRules(namespace string) DestinationRuleInterface {
return newDestinationRules(c, namespace)
}
func (c *NetworkingV1alpha3Client) Gateways(namespace string) GatewayInterface {
return newGateways(c, namespace)
}
func (c *NetworkingV1alpha3Client) VirtualServices(namespace string) VirtualServiceInterface {
return newVirtualServices(c, namespace)
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -19,8 +19,8 @@ limitations under the License.
package v1alpha3
import (
v1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
scheme "github.com/knative/pkg/client/clientset/versioned/scheme"
v1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
scheme "github.com/stefanprodan/flagger/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"

View File

@ -26,6 +26,7 @@ import (
versioned "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
flagger "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/flagger"
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
istio "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/istio"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -173,8 +174,13 @@ type SharedInformerFactory interface {
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
Flagger() flagger.Interface
Networking() istio.Interface
}
func (f *sharedInformerFactory) Flagger() flagger.Interface {
return flagger.New(f, f.namespace, f.tweakListOptions)
}
func (f *sharedInformerFactory) Networking() istio.Interface {
return istio.New(f, f.namespace, f.tweakListOptions)
}

View File

@ -22,6 +22,7 @@ import (
"fmt"
v1alpha3 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
istiov1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
@ -56,6 +57,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case v1alpha3.SchemeGroupVersion.WithResource("canaries"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Flagger().V1alpha3().Canaries().Informer()}, nil
// Group=networking.istio.io, Version=v1alpha3
case istiov1alpha3.SchemeGroupVersion.WithResource("virtualservices"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha3().VirtualServices().Informer()}, nil
}
return nil, fmt.Errorf("no informer found for %v", resource)

View File

@ -0,0 +1,46 @@
/*
Copyright The Flagger 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 informer-gen. DO NOT EDIT.
package networking
import (
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha3 "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/istio/v1alpha3"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha3 provides access to shared informers for resources in V1alpha3.
V1alpha3() v1alpha3.Interface
}
type group struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha3 returns a new v1alpha3.Interface.
func (g *group) V1alpha3() v1alpha3.Interface {
return v1alpha3.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@ -0,0 +1,45 @@
/*
Copyright The Flagger 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 informer-gen. DO NOT EDIT.
package v1alpha3
import (
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// VirtualServices returns a VirtualServiceInformer.
VirtualServices() VirtualServiceInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// VirtualServices returns a VirtualServiceInformer.
func (v *version) VirtualServices() VirtualServiceInformer {
return &virtualServiceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@ -0,0 +1,89 @@
/*
Copyright The Flagger 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 informer-gen. DO NOT EDIT.
package v1alpha3
import (
time "time"
istiov1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
versioned "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha3 "github.com/stefanprodan/flagger/pkg/client/listers/istio/v1alpha3"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// VirtualServiceInformer provides access to a shared informer and lister for
// VirtualServices.
type VirtualServiceInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha3.VirtualServiceLister
}
type virtualServiceInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewVirtualServiceInformer constructs a new informer for VirtualService type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewVirtualServiceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredVirtualServiceInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredVirtualServiceInformer constructs a new informer for VirtualService type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredVirtualServiceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.NetworkingV1alpha3().VirtualServices(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.NetworkingV1alpha3().VirtualServices(namespace).Watch(options)
},
},
&istiov1alpha3.VirtualService{},
resyncPeriod,
indexers,
)
}
func (f *virtualServiceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredVirtualServiceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *virtualServiceInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&istiov1alpha3.VirtualService{}, f.defaultInformer)
}
func (f *virtualServiceInformer) Lister() v1alpha3.VirtualServiceLister {
return v1alpha3.NewVirtualServiceLister(f.Informer().GetIndexer())
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Knative Authors
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,12 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha3
type DestinationRuleExpansion interface{}
// VirtualServiceListerExpansion allows custom methods to be added to
// VirtualServiceLister.
type VirtualServiceListerExpansion interface{}
type GatewayExpansion interface{}
type VirtualServiceExpansion interface{}
// VirtualServiceNamespaceListerExpansion allows custom methods to be added to
// VirtualServiceNamespaceLister.
type VirtualServiceNamespaceListerExpansion interface{}

View File

@ -0,0 +1,94 @@
/*
Copyright The Flagger 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 lister-gen. DO NOT EDIT.
package v1alpha3
import (
v1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// VirtualServiceLister helps list VirtualServices.
type VirtualServiceLister interface {
// List lists all VirtualServices in the indexer.
List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error)
// VirtualServices returns an object that can list and get VirtualServices.
VirtualServices(namespace string) VirtualServiceNamespaceLister
VirtualServiceListerExpansion
}
// virtualServiceLister implements the VirtualServiceLister interface.
type virtualServiceLister struct {
indexer cache.Indexer
}
// NewVirtualServiceLister returns a new VirtualServiceLister.
func NewVirtualServiceLister(indexer cache.Indexer) VirtualServiceLister {
return &virtualServiceLister{indexer: indexer}
}
// List lists all VirtualServices in the indexer.
func (s *virtualServiceLister) List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha3.VirtualService))
})
return ret, err
}
// VirtualServices returns an object that can list and get VirtualServices.
func (s *virtualServiceLister) VirtualServices(namespace string) VirtualServiceNamespaceLister {
return virtualServiceNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// VirtualServiceNamespaceLister helps list and get VirtualServices.
type VirtualServiceNamespaceLister interface {
// List lists all VirtualServices in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error)
// Get retrieves the VirtualService from the indexer for a given namespace and name.
Get(name string) (*v1alpha3.VirtualService, error)
VirtualServiceNamespaceListerExpansion
}
// virtualServiceNamespaceLister implements the VirtualServiceNamespaceLister
// interface.
type virtualServiceNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all VirtualServices in the indexer for a given namespace.
func (s virtualServiceNamespaceLister) List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha3.VirtualService))
})
return ret, err
}
// Get retrieves the VirtualService from the indexer for a given namespace and name.
func (s virtualServiceNamespaceLister) Get(name string) (*v1alpha3.VirtualService, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha3.Resource("virtualservice"), name)
}
return obj.(*v1alpha3.VirtualService), nil
}

View File

@ -6,7 +6,6 @@ import (
"time"
"github.com/google/go-cmp/cmp"
istioclientset "github.com/knative/pkg/client/clientset/versioned"
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
flaggerscheme "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/scheme"
@ -31,7 +30,7 @@ const controllerAgentName = "flagger"
// Controller is managing the canary objects and schedules canary deployments
type Controller struct {
kubeClient kubernetes.Interface
istioClient istioclientset.Interface
istioClient clientset.Interface
flaggerClient clientset.Interface
flaggerLister flaggerlisters.CanaryLister
flaggerSynced cache.InformerSynced
@ -49,7 +48,7 @@ type Controller struct {
func NewController(
kubeClient kubernetes.Interface,
istioClient istioclientset.Interface,
istioClient clientset.Interface,
flaggerClient clientset.Interface,
flaggerInformer flaggerinformers.CanaryInformer,
flaggerWindow time.Duration,
@ -71,7 +70,6 @@ func NewController(
deployer := CanaryDeployer{
logger: logger,
kubeClient: kubeClient,
istioClient: istioClient,
flaggerClient: flaggerClient,
configTracker: ConfigTracker{
logger: logger,

View File

@ -1,8 +1,6 @@
package controller
import (
istioclientset "github.com/knative/pkg/client/clientset/versioned"
fakeIstio "github.com/knative/pkg/client/clientset/versioned/fake"
"github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
fakeFlagger "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/fake"
@ -31,7 +29,7 @@ var (
type Mocks struct {
canary *v1alpha3.Canary
kubeClient kubernetes.Interface
istioClient istioclientset.Interface
istioClient clientset.Interface
flaggerClient clientset.Interface
deployer CanaryDeployer
observer CanaryObserver
@ -57,7 +55,6 @@ func SetupMocks() Mocks {
NewTestSecretVol(),
)
istioClient := fakeIstio.NewSimpleClientset()
logger, _ := logging.NewLogger("debug")
// init controller helpers
@ -81,7 +78,7 @@ func SetupMocks() Mocks {
ctrl := &Controller{
kubeClient: kubeClient,
istioClient: istioClient,
istioClient: flaggerClient,
flaggerClient: flaggerClient,
flaggerLister: flaggerInformer.Lister(),
flaggerSynced: flaggerInformer.Informer().HasSynced,
@ -97,7 +94,7 @@ func SetupMocks() Mocks {
ctrl.flaggerSynced = alwaysReady
// init router
rf := router.NewFactory(kubeClient, flaggerClient, logger, istioClient)
rf := router.NewFactory(kubeClient, flaggerClient, logger, flaggerClient)
var meshRouter router.Interface
meshRouter = rf.IstioRouter()
@ -107,7 +104,7 @@ func SetupMocks() Mocks {
deployer: deployer,
logger: logger,
flaggerClient: flaggerClient,
istioClient: istioClient,
istioClient: flaggerClient,
kubeClient: kubeClient,
ctrl: ctrl,
router: meshRouter,

View File

@ -10,7 +10,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
istioclientset "github.com/knative/pkg/client/clientset/versioned"
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
"go.uber.org/zap"
@ -27,7 +26,6 @@ import (
// CanaryDeployer is managing the operations for Kubernetes deployment kind
type CanaryDeployer struct {
kubeClient kubernetes.Interface
istioClient istioclientset.Interface
flaggerClient clientset.Interface
logger *zap.SugaredLogger
configTracker ConfigTracker

View File

@ -1,7 +1,6 @@
package router
import (
istioclientset "github.com/knative/pkg/client/clientset/versioned"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
"go.uber.org/zap"
"k8s.io/client-go/kubernetes"
@ -9,7 +8,7 @@ import (
type Factory struct {
kubeClient kubernetes.Interface
istioClient istioclientset.Interface
istioClient clientset.Interface
flaggerClient clientset.Interface
logger *zap.SugaredLogger
}
@ -17,7 +16,7 @@ type Factory struct {
func NewFactory(kubeClient kubernetes.Interface,
flaggerClient clientset.Interface,
logger *zap.SugaredLogger,
istioClient istioclientset.Interface) *Factory {
istioClient clientset.Interface) *Factory {
return &Factory{
istioClient: istioClient,
kubeClient: kubeClient,

View File

@ -4,9 +4,8 @@ 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"
istiov1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
"go.uber.org/zap"
"k8s.io/apimachinery/pkg/api/errors"
@ -19,7 +18,7 @@ import (
// IstioRouter is managing Istio virtual services
type IstioRouter struct {
kubeClient kubernetes.Interface
istioClient istioclientset.Interface
istioClient clientset.Interface
flaggerClient clientset.Interface
logger *zap.SugaredLogger
}

View File

@ -2,7 +2,7 @@ package router
import (
"fmt"
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
istiov1alpha3 "github.com/stefanprodan/flagger/pkg/apis/istio/v1alpha3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"testing"
)

View File

@ -1,8 +1,6 @@
package router
import (
istioclientset "github.com/knative/pkg/client/clientset/versioned"
fakeIstio "github.com/knative/pkg/client/clientset/versioned/fake"
"github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha3"
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
fakeFlagger "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/fake"
@ -19,7 +17,7 @@ import (
type fakeClients struct {
canary *v1alpha3.Canary
kubeClient kubernetes.Interface
istioClient istioclientset.Interface
istioClient clientset.Interface
flaggerClient clientset.Interface
logger *zap.SugaredLogger
}
@ -32,7 +30,7 @@ func setupfakeClients() fakeClients {
newMockDeployment(),
)
istioClient := fakeIstio.NewSimpleClientset()
istioClient := fakeFlagger.NewSimpleClientset()
logger, _ := logging.NewLogger("debug")
return fakeClients{

View File

@ -1,12 +1,9 @@
/*
Copyright 2018 The Knative Authors
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

View File

@ -1,14 +1,11 @@
// +build !windows
/*
Copyright 2018 The Knative Authors
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

View File

@ -1,12 +1,9 @@
/*
Copyright 2018 The Knative Authors
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.