mirror of
https://github.com/fluxcd/flagger.git
synced 2026-02-14 18:10:00 +00:00
Canary CRD refactoring
- set canaries.flagger.app version to v1alpha1 - replace old Canary spec with CanaryDeployment
This commit is contained in:
1
Gopkg.lock
generated
1
Gopkg.lock
generated
@@ -665,6 +665,7 @@
|
||||
"k8s.io/api/autoscaling/v1",
|
||||
"k8s.io/api/core/v1",
|
||||
"k8s.io/apimachinery/pkg/api/errors",
|
||||
"k8s.io/apimachinery/pkg/api/resource",
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"k8s.io/apimachinery/pkg/labels",
|
||||
"k8s.io/apimachinery/pkg/runtime",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: CanaryDeployment
|
||||
apiVersion: flagger.app/v1alpha1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
|
||||
@@ -4,9 +4,9 @@ metadata:
|
||||
name: canaries.flagger.app
|
||||
spec:
|
||||
group: flagger.app
|
||||
version: v1beta1
|
||||
version: v1alpha1
|
||||
versions:
|
||||
- name: v1beta1
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
names:
|
||||
@@ -19,75 +19,22 @@ spec:
|
||||
properties:
|
||||
spec:
|
||||
required:
|
||||
- targetKind
|
||||
- virtualService
|
||||
- primary
|
||||
- canary
|
||||
- canaryAnalysis
|
||||
properties:
|
||||
targetKind:
|
||||
type: string
|
||||
virtualService:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
primary:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
canary:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
canaryAnalysis:
|
||||
properties:
|
||||
threshold:
|
||||
type: number
|
||||
maxWeight:
|
||||
type: number
|
||||
stepWeight:
|
||||
type: number
|
||||
metrics:
|
||||
type: array
|
||||
properties:
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
interval:
|
||||
type: string
|
||||
pattern: "^[0-9]+(m)"
|
||||
threshold:
|
||||
type: number
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: canarydeployments.flagger.app
|
||||
spec:
|
||||
group: flagger.app
|
||||
version: v1beta1
|
||||
versions:
|
||||
- name: v1beta1
|
||||
served: true
|
||||
storage: true
|
||||
names:
|
||||
plural: canarydeployments
|
||||
singular: canarydeployment
|
||||
kind: CanaryDeployment
|
||||
scope: Namespaced
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
spec:
|
||||
required:
|
||||
- targetRef
|
||||
- service
|
||||
- canaryAnalysis
|
||||
properties:
|
||||
targetRef:
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
service:
|
||||
properties:
|
||||
port:
|
||||
type: number
|
||||
canaryAnalysis:
|
||||
properties:
|
||||
threshold:
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# monitor events: watch "kubectl -n test describe rollout/podinfo | sed -n 35,1000p"
|
||||
# run tester: kubectl run -n test tester --image=quay.io/stefanprodan/podinfo:1.2.1 -- ./podinfo --port=9898
|
||||
# generate latency: watch curl http://podinfo-canary:9898/delay/1
|
||||
# generate errors: watch curl http://podinfo-canary:9898/status/500
|
||||
# run load test: kubectl run -n test -it --rm --restart=Never hey --image=stefanprodan/loadtest -- sh
|
||||
# generate load: hey -z 2m -h2 -m POST -d '{test: 1}' -c 10 -q 5 http://podinfo:9898/api/echo
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
targetKind: Deployment
|
||||
virtualService:
|
||||
name: podinfo
|
||||
primary:
|
||||
name: podinfo
|
||||
host: podinfo
|
||||
canary:
|
||||
name: podinfo-canary
|
||||
host: podinfo-canary
|
||||
canaryAnalysis:
|
||||
# max number of failed metric checks
|
||||
# before rolling back the canary
|
||||
threshold: 5
|
||||
# max traffic percentage routed to canary
|
||||
# percentage (0-100)
|
||||
maxWeight: 50
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 10
|
||||
metrics:
|
||||
- name: istio_requests_total
|
||||
# minimum req success rate (non 5xx responses)
|
||||
# percentage (0-100)
|
||||
threshold: 99
|
||||
interval: 1m
|
||||
- name: istio_request_duration_seconds_bucket
|
||||
# maximum req duration P99
|
||||
# milliseconds
|
||||
threshold: 500
|
||||
interval: 30s
|
||||
@@ -1,36 +0,0 @@
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfoc
|
||||
namespace: test
|
||||
spec:
|
||||
targetKind: Deployment
|
||||
virtualService:
|
||||
name: podinfoc
|
||||
primary:
|
||||
name: podinfoc-primary
|
||||
host: podinfoc-primary
|
||||
canary:
|
||||
name: podinfoc-canary
|
||||
host: podinfoc-canary
|
||||
canaryAnalysis:
|
||||
# max number of failed metric checks
|
||||
# before rolling back the canary
|
||||
threshold: 10
|
||||
# max traffic percentage routed to canary
|
||||
# percentage (0-100)
|
||||
maxWeight: 50
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 10
|
||||
metrics:
|
||||
- name: istio_requests_total
|
||||
# minimum req success rate (non 5xx responses)
|
||||
# percentage (0-100)
|
||||
threshold: 99
|
||||
interval: 1m
|
||||
- name: istio_request_duration_seconds_bucket
|
||||
# maximum req duration P99
|
||||
# milliseconds
|
||||
threshold: 500
|
||||
interval: 30s
|
||||
@@ -5,9 +5,9 @@ metadata:
|
||||
name: canaries.flagger.app
|
||||
spec:
|
||||
group: flagger.app
|
||||
version: v1beta1
|
||||
version: v1alpha1
|
||||
versions:
|
||||
- name: v1beta1
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
names:
|
||||
@@ -20,30 +20,22 @@ spec:
|
||||
properties:
|
||||
spec:
|
||||
required:
|
||||
- targetKind
|
||||
- virtualService
|
||||
- primary
|
||||
- canary
|
||||
- canaryAnalysis
|
||||
- targetRef
|
||||
- service
|
||||
- canaryAnalysis
|
||||
properties:
|
||||
targetKind:
|
||||
type: string
|
||||
virtualService:
|
||||
targetRef:
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
primary:
|
||||
service:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
canary:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
port:
|
||||
type: number
|
||||
canaryAnalysis:
|
||||
properties:
|
||||
threshold:
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/stefanprodan/flagger/pkg/operator"
|
||||
|
||||
_ "github.com/istio/glog"
|
||||
sharedclientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
"github.com/knative/pkg/signals"
|
||||
@@ -71,9 +69,8 @@ func main() {
|
||||
logger.Fatalf("Error building example clientset: %s", err.Error())
|
||||
}
|
||||
|
||||
rolloutInformerFactory := informers.NewSharedInformerFactory(rolloutClient, time.Second*30)
|
||||
rolloutInformer := rolloutInformerFactory.Flagger().V1beta1().Canaries()
|
||||
canaryDeploymentInformer := rolloutInformerFactory.Flagger().V1beta1().CanaryDeployments()
|
||||
canaryInformerFactory := informers.NewSharedInformerFactory(rolloutClient, time.Second*30)
|
||||
canaryInformer := canaryInformerFactory.Flagger().V1alpha1().Canaries()
|
||||
|
||||
logger.Infof("Starting flagger version %s revision %s", version.VERSION, version.REVISION)
|
||||
|
||||
@@ -98,28 +95,17 @@ func main() {
|
||||
kubeClient,
|
||||
sharedClient,
|
||||
rolloutClient,
|
||||
rolloutInformer,
|
||||
canaryInformer,
|
||||
controlLoopInterval,
|
||||
metricsServer,
|
||||
logger,
|
||||
)
|
||||
|
||||
cd := operator.NewController(
|
||||
kubeClient,
|
||||
sharedClient,
|
||||
rolloutClient,
|
||||
canaryDeploymentInformer,
|
||||
controlLoopInterval,
|
||||
metricsServer,
|
||||
logger,
|
||||
)
|
||||
|
||||
rolloutInformerFactory.Start(stopCh)
|
||||
canaryInformerFactory.Start(stopCh)
|
||||
|
||||
logger.Info("Waiting for informer caches to sync")
|
||||
for _, synced := range []cache.InformerSynced{
|
||||
rolloutInformer.Informer().HasSynced,
|
||||
canaryDeploymentInformer.Informer().HasSynced,
|
||||
canaryInformer.Informer().HasSynced,
|
||||
} {
|
||||
if ok := cache.WaitForCacheSync(stopCh, synced); !ok {
|
||||
logger.Fatalf("Failed to wait for cache sync")
|
||||
@@ -133,12 +119,5 @@ func main() {
|
||||
}
|
||||
}(c)
|
||||
|
||||
// start controller
|
||||
go func(ctrl *operator.Controller) {
|
||||
if err := ctrl.Run(2, stopCh); err != nil {
|
||||
logger.Fatalf("Error running controller: %v", err)
|
||||
}
|
||||
}(cd)
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
@@ -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:v1beta1 \
|
||||
flagger:v1alpha1 \
|
||||
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ limitations under the License.
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
// Package v1beta1 is the v1beta1 version of the API.
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
// +groupName=flagger.app
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: rollout.GroupName, Version: "v1beta1"}
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: rollout.GroupName, Version: "v1alpha1"}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
@@ -47,8 +47,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Canary{},
|
||||
&CanaryList{},
|
||||
&CanaryDeployment{},
|
||||
&CanaryDeploymentList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
hpav1 "k8s.io/api/autoscaling/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const CanaryDeploymentKind = "CanaryDeployment"
|
||||
const CanaryKind = "Canary"
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
@@ -37,11 +37,14 @@ type Canary struct {
|
||||
|
||||
// CanarySpec is the spec for a Canary resource
|
||||
type CanarySpec struct {
|
||||
TargetKind string `json:"targetKind"`
|
||||
Primary Target `json:"primary"`
|
||||
Canary Target `json:"canary"`
|
||||
// reference to target resource
|
||||
TargetRef hpav1.CrossVersionObjectReference `json:"targetRef"`
|
||||
|
||||
// virtual service spec
|
||||
Service CanaryService `json:"service"`
|
||||
|
||||
// metrics and thresholds
|
||||
CanaryAnalysis CanaryAnalysis `json:"canaryAnalysis"`
|
||||
VirtualService VirtualService `json:"virtualService"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
@@ -61,71 +64,21 @@ type CanaryStatus struct {
|
||||
FailedChecks int `json:"failedChecks"`
|
||||
}
|
||||
|
||||
type Target struct {
|
||||
Name string `json:"name"`
|
||||
Host string `json:"host"`
|
||||
}
|
||||
|
||||
type VirtualService struct {
|
||||
Name string `json:"name"`
|
||||
type CanaryService struct {
|
||||
Port int32 `json:"port"`
|
||||
Gateways []string `json:"gateways"`
|
||||
Hosts []string `json:"hosts"`
|
||||
}
|
||||
|
||||
type CanaryAnalysis struct {
|
||||
Threshold int `json:"threshold"`
|
||||
MaxWeight int `json:"maxWeight"`
|
||||
StepWeight int `json:"stepWeight"`
|
||||
Metrics []Metric `json:"metrics"`
|
||||
Threshold int `json:"threshold"`
|
||||
MaxWeight int `json:"maxWeight"`
|
||||
StepWeight int `json:"stepWeight"`
|
||||
Metrics []CanaryMetric `json:"metrics"`
|
||||
}
|
||||
|
||||
type Metric struct {
|
||||
type CanaryMetric struct {
|
||||
Name string `json:"name"`
|
||||
Interval string `json:"interval"`
|
||||
Threshold int `json:"threshold"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// Canary is a specification for a Canary resource
|
||||
type CanaryDeployment struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec CanaryDeploymentSpec `json:"spec"`
|
||||
Status CanaryDeploymentStatus `json:"status"`
|
||||
}
|
||||
|
||||
// CanarySpec is the spec for a Canary resource
|
||||
type CanaryDeploymentSpec struct {
|
||||
// reference to target resource
|
||||
TargetRef hpav1.CrossVersionObjectReference `json:"targetRef"`
|
||||
|
||||
// virtual service spec
|
||||
Service CanaryDeploymentService `json:"service"`
|
||||
|
||||
// metrics and thresholds
|
||||
CanaryAnalysis CanaryAnalysis `json:"canaryAnalysis"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CanaryList is a list of Canary resources
|
||||
type CanaryDeploymentList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []CanaryDeployment `json:"items"`
|
||||
}
|
||||
|
||||
// CanaryStatus is used for state persistence (read-only)
|
||||
type CanaryDeploymentStatus struct {
|
||||
State string `json:"state"`
|
||||
CanaryRevision string `json:"canaryRevision"`
|
||||
FailedChecks int `json:"failedChecks"`
|
||||
}
|
||||
|
||||
type CanaryDeploymentService struct {
|
||||
Port int32 `json:"port"`
|
||||
Gateways []string `json:"gateways"`
|
||||
Hosts []string `json:"hosts"`
|
||||
}
|
||||
@@ -18,7 +18,7 @@ limitations under the License.
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -57,7 +57,7 @@ func (in *CanaryAnalysis) DeepCopyInto(out *CanaryAnalysis) {
|
||||
*out = *in
|
||||
if in.Metrics != nil {
|
||||
in, out := &in.Metrics, &out.Metrics
|
||||
*out = make([]Metric, len(*in))
|
||||
*out = make([]CanaryMetric, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
@@ -73,128 +73,6 @@ func (in *CanaryAnalysis) DeepCopy() *CanaryAnalysis {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryDeployment) DeepCopyInto(out *CanaryDeployment) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryDeployment.
|
||||
func (in *CanaryDeployment) DeepCopy() *CanaryDeployment {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryDeployment)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CanaryDeployment) 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 *CanaryDeploymentList) DeepCopyInto(out *CanaryDeploymentList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CanaryDeployment, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryDeploymentList.
|
||||
func (in *CanaryDeploymentList) DeepCopy() *CanaryDeploymentList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryDeploymentList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CanaryDeploymentList) 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 *CanaryDeploymentService) DeepCopyInto(out *CanaryDeploymentService) {
|
||||
*out = *in
|
||||
if in.Gateways != nil {
|
||||
in, out := &in.Gateways, &out.Gateways
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Hosts != nil {
|
||||
in, out := &in.Hosts, &out.Hosts
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryDeploymentService.
|
||||
func (in *CanaryDeploymentService) DeepCopy() *CanaryDeploymentService {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryDeploymentService)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryDeploymentSpec) DeepCopyInto(out *CanaryDeploymentSpec) {
|
||||
*out = *in
|
||||
out.TargetRef = in.TargetRef
|
||||
in.Service.DeepCopyInto(&out.Service)
|
||||
in.CanaryAnalysis.DeepCopyInto(&out.CanaryAnalysis)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryDeploymentSpec.
|
||||
func (in *CanaryDeploymentSpec) DeepCopy() *CanaryDeploymentSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryDeploymentSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryDeploymentStatus) DeepCopyInto(out *CanaryDeploymentStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryDeploymentStatus.
|
||||
func (in *CanaryDeploymentStatus) DeepCopy() *CanaryDeploymentStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryDeploymentStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryList) DeepCopyInto(out *CanaryList) {
|
||||
*out = *in
|
||||
@@ -228,13 +106,54 @@ func (in *CanaryList) DeepCopyObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryMetric) DeepCopyInto(out *CanaryMetric) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryMetric.
|
||||
func (in *CanaryMetric) DeepCopy() *CanaryMetric {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryMetric)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryService) DeepCopyInto(out *CanaryService) {
|
||||
*out = *in
|
||||
if in.Gateways != nil {
|
||||
in, out := &in.Gateways, &out.Gateways
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Hosts != nil {
|
||||
in, out := &in.Hosts, &out.Hosts
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryService.
|
||||
func (in *CanaryService) DeepCopy() *CanaryService {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryService)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanarySpec) DeepCopyInto(out *CanarySpec) {
|
||||
*out = *in
|
||||
out.Primary = in.Primary
|
||||
out.Canary = in.Canary
|
||||
out.TargetRef = in.TargetRef
|
||||
in.Service.DeepCopyInto(&out.Service)
|
||||
in.CanaryAnalysis.DeepCopyInto(&out.CanaryAnalysis)
|
||||
out.VirtualService = in.VirtualService
|
||||
return
|
||||
}
|
||||
|
||||
@@ -263,51 +182,3 @@ func (in *CanaryStatus) DeepCopy() *CanaryStatus {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Metric) DeepCopyInto(out *Metric) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Metric.
|
||||
func (in *Metric) DeepCopy() *Metric {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Metric)
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
}
|
||||
@@ -19,7 +19,7 @@ limitations under the License.
|
||||
package versioned
|
||||
|
||||
import (
|
||||
flaggerv1beta1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1"
|
||||
flaggerv1alpha1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha1"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
@@ -27,27 +27,27 @@ import (
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
FlaggerV1beta1() flaggerv1beta1.FlaggerV1beta1Interface
|
||||
FlaggerV1alpha1() flaggerv1alpha1.FlaggerV1alpha1Interface
|
||||
// Deprecated: please explicitly pick a version if possible.
|
||||
Flagger() flaggerv1beta1.FlaggerV1beta1Interface
|
||||
Flagger() flaggerv1alpha1.FlaggerV1alpha1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
flaggerV1beta1 *flaggerv1beta1.FlaggerV1beta1Client
|
||||
flaggerV1alpha1 *flaggerv1alpha1.FlaggerV1alpha1Client
|
||||
}
|
||||
|
||||
// FlaggerV1beta1 retrieves the FlaggerV1beta1Client
|
||||
func (c *Clientset) FlaggerV1beta1() flaggerv1beta1.FlaggerV1beta1Interface {
|
||||
return c.flaggerV1beta1
|
||||
// FlaggerV1alpha1 retrieves the FlaggerV1alpha1Client
|
||||
func (c *Clientset) FlaggerV1alpha1() flaggerv1alpha1.FlaggerV1alpha1Interface {
|
||||
return c.flaggerV1alpha1
|
||||
}
|
||||
|
||||
// Deprecated: Flagger retrieves the default version of FlaggerClient.
|
||||
// Please explicitly pick a version.
|
||||
func (c *Clientset) Flagger() flaggerv1beta1.FlaggerV1beta1Interface {
|
||||
return c.flaggerV1beta1
|
||||
func (c *Clientset) Flagger() flaggerv1alpha1.FlaggerV1alpha1Interface {
|
||||
return c.flaggerV1alpha1
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
@@ -66,7 +66,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.flaggerV1beta1, err = flaggerv1beta1.NewForConfig(&configShallowCopy)
|
||||
cs.flaggerV1alpha1, err = flaggerv1alpha1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.flaggerV1beta1 = flaggerv1beta1.NewForConfigOrDie(c)
|
||||
cs.flaggerV1alpha1 = flaggerv1alpha1.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
@@ -91,7 +91,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.flaggerV1beta1 = flaggerv1beta1.New(c)
|
||||
cs.flaggerV1alpha1 = flaggerv1alpha1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
|
||||
@@ -20,8 +20,8 @@ package fake
|
||||
|
||||
import (
|
||||
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
flaggerv1beta1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1"
|
||||
fakeflaggerv1beta1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1/fake"
|
||||
flaggerv1alpha1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha1"
|
||||
fakeflaggerv1alpha1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha1/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
@@ -71,12 +71,12 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// FlaggerV1beta1 retrieves the FlaggerV1beta1Client
|
||||
func (c *Clientset) FlaggerV1beta1() flaggerv1beta1.FlaggerV1beta1Interface {
|
||||
return &fakeflaggerv1beta1.FakeFlaggerV1beta1{Fake: &c.Fake}
|
||||
// FlaggerV1alpha1 retrieves the FlaggerV1alpha1Client
|
||||
func (c *Clientset) FlaggerV1alpha1() flaggerv1alpha1.FlaggerV1alpha1Interface {
|
||||
return &fakeflaggerv1alpha1.FakeFlaggerV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Flagger retrieves the FlaggerV1beta1Client
|
||||
func (c *Clientset) Flagger() flaggerv1beta1.FlaggerV1beta1Interface {
|
||||
return &fakeflaggerv1beta1.FakeFlaggerV1beta1{Fake: &c.Fake}
|
||||
// Flagger retrieves the FlaggerV1alpha1Client
|
||||
func (c *Clientset) Flagger() flaggerv1alpha1.FlaggerV1alpha1Interface {
|
||||
return &fakeflaggerv1alpha1.FakeFlaggerV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ limitations under the License.
|
||||
package fake
|
||||
|
||||
import (
|
||||
flaggerv1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@@ -50,5 +50,5 @@ func init() {
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
flaggerv1beta1.AddToScheme(scheme)
|
||||
flaggerv1alpha1.AddToScheme(scheme)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ limitations under the License.
|
||||
package scheme
|
||||
|
||||
import (
|
||||
flaggerv1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@@ -50,5 +50,5 @@ func init() {
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
flaggerv1beta1.AddToScheme(scheme)
|
||||
flaggerv1alpha1.AddToScheme(scheme)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ limitations under the License.
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
scheme "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
@@ -35,15 +35,15 @@ type CanariesGetter interface {
|
||||
|
||||
// CanaryInterface has methods to work with Canary resources.
|
||||
type CanaryInterface interface {
|
||||
Create(*v1beta1.Canary) (*v1beta1.Canary, error)
|
||||
Update(*v1beta1.Canary) (*v1beta1.Canary, error)
|
||||
UpdateStatus(*v1beta1.Canary) (*v1beta1.Canary, error)
|
||||
Create(*v1alpha1.Canary) (*v1alpha1.Canary, error)
|
||||
Update(*v1alpha1.Canary) (*v1alpha1.Canary, error)
|
||||
UpdateStatus(*v1alpha1.Canary) (*v1alpha1.Canary, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta1.Canary, error)
|
||||
List(opts v1.ListOptions) (*v1beta1.CanaryList, error)
|
||||
Get(name string, options v1.GetOptions) (*v1alpha1.Canary, error)
|
||||
List(opts v1.ListOptions) (*v1alpha1.CanaryList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Canary, err error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Canary, err error)
|
||||
CanaryExpansion
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ type canaries struct {
|
||||
}
|
||||
|
||||
// newCanaries returns a Canaries
|
||||
func newCanaries(c *FlaggerV1beta1Client, namespace string) *canaries {
|
||||
func newCanaries(c *FlaggerV1alpha1Client, namespace string) *canaries {
|
||||
return &canaries{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
@@ -62,8 +62,8 @@ func newCanaries(c *FlaggerV1beta1Client, namespace string) *canaries {
|
||||
}
|
||||
|
||||
// Get takes name of the canary, and returns the corresponding canary object, and an error if there is any.
|
||||
func (c *canaries) Get(name string, options v1.GetOptions) (result *v1beta1.Canary, err error) {
|
||||
result = &v1beta1.Canary{}
|
||||
func (c *canaries) Get(name string, options v1.GetOptions) (result *v1alpha1.Canary, err error) {
|
||||
result = &v1alpha1.Canary{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("canaries").
|
||||
@@ -75,8 +75,8 @@ func (c *canaries) Get(name string, options v1.GetOptions) (result *v1beta1.Cana
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Canaries that match those selectors.
|
||||
func (c *canaries) List(opts v1.ListOptions) (result *v1beta1.CanaryList, err error) {
|
||||
result = &v1beta1.CanaryList{}
|
||||
func (c *canaries) List(opts v1.ListOptions) (result *v1alpha1.CanaryList, err error) {
|
||||
result = &v1alpha1.CanaryList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("canaries").
|
||||
@@ -97,8 +97,8 @@ func (c *canaries) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
}
|
||||
|
||||
// Create takes the representation of a canary and creates it. Returns the server's representation of the canary, and an error, if there is any.
|
||||
func (c *canaries) Create(canary *v1beta1.Canary) (result *v1beta1.Canary, err error) {
|
||||
result = &v1beta1.Canary{}
|
||||
func (c *canaries) Create(canary *v1alpha1.Canary) (result *v1alpha1.Canary, err error) {
|
||||
result = &v1alpha1.Canary{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("canaries").
|
||||
@@ -109,8 +109,8 @@ func (c *canaries) Create(canary *v1beta1.Canary) (result *v1beta1.Canary, err e
|
||||
}
|
||||
|
||||
// Update takes the representation of a canary and updates it. Returns the server's representation of the canary, and an error, if there is any.
|
||||
func (c *canaries) Update(canary *v1beta1.Canary) (result *v1beta1.Canary, err error) {
|
||||
result = &v1beta1.Canary{}
|
||||
func (c *canaries) Update(canary *v1alpha1.Canary) (result *v1alpha1.Canary, err error) {
|
||||
result = &v1alpha1.Canary{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("canaries").
|
||||
@@ -124,8 +124,8 @@ func (c *canaries) Update(canary *v1beta1.Canary) (result *v1beta1.Canary, err e
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *canaries) UpdateStatus(canary *v1beta1.Canary) (result *v1beta1.Canary, err error) {
|
||||
result = &v1beta1.Canary{}
|
||||
func (c *canaries) UpdateStatus(canary *v1alpha1.Canary) (result *v1alpha1.Canary, err error) {
|
||||
result = &v1alpha1.Canary{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("canaries").
|
||||
@@ -160,8 +160,8 @@ func (c *canaries) DeleteCollection(options *v1.DeleteOptions, listOptions v1.Li
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched canary.
|
||||
func (c *canaries) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Canary, err error) {
|
||||
result = &v1beta1.Canary{}
|
||||
func (c *canaries) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Canary, err error) {
|
||||
result = &v1alpha1.Canary{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("canaries").
|
||||
@@ -17,4 +17,4 @@ limitations under the License.
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
@@ -19,7 +19,7 @@ limitations under the License.
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@@ -30,29 +30,29 @@ import (
|
||||
|
||||
// FakeCanaries implements CanaryInterface
|
||||
type FakeCanaries struct {
|
||||
Fake *FakeFlaggerV1beta1
|
||||
Fake *FakeFlaggerV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var canariesResource = schema.GroupVersionResource{Group: "flagger.app", Version: "v1beta1", Resource: "canaries"}
|
||||
var canariesResource = schema.GroupVersionResource{Group: "flagger.app", Version: "v1alpha1", Resource: "canaries"}
|
||||
|
||||
var canariesKind = schema.GroupVersionKind{Group: "flagger.app", Version: "v1beta1", Kind: "Canary"}
|
||||
var canariesKind = schema.GroupVersionKind{Group: "flagger.app", Version: "v1alpha1", Kind: "Canary"}
|
||||
|
||||
// Get takes name of the canary, and returns the corresponding canary object, and an error if there is any.
|
||||
func (c *FakeCanaries) Get(name string, options v1.GetOptions) (result *v1beta1.Canary, err error) {
|
||||
func (c *FakeCanaries) Get(name string, options v1.GetOptions) (result *v1alpha1.Canary, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(canariesResource, c.ns, name), &v1beta1.Canary{})
|
||||
Invokes(testing.NewGetAction(canariesResource, c.ns, name), &v1alpha1.Canary{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Canary), err
|
||||
return obj.(*v1alpha1.Canary), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Canaries that match those selectors.
|
||||
func (c *FakeCanaries) List(opts v1.ListOptions) (result *v1beta1.CanaryList, err error) {
|
||||
func (c *FakeCanaries) List(opts v1.ListOptions) (result *v1alpha1.CanaryList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(canariesResource, canariesKind, c.ns, opts), &v1beta1.CanaryList{})
|
||||
Invokes(testing.NewListAction(canariesResource, canariesKind, c.ns, opts), &v1alpha1.CanaryList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
@@ -62,8 +62,8 @@ func (c *FakeCanaries) List(opts v1.ListOptions) (result *v1beta1.CanaryList, er
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.CanaryList{ListMeta: obj.(*v1beta1.CanaryList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.CanaryList).Items {
|
||||
list := &v1alpha1.CanaryList{ListMeta: obj.(*v1alpha1.CanaryList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.CanaryList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
@@ -79,43 +79,43 @@ func (c *FakeCanaries) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
}
|
||||
|
||||
// Create takes the representation of a canary and creates it. Returns the server's representation of the canary, and an error, if there is any.
|
||||
func (c *FakeCanaries) Create(canary *v1beta1.Canary) (result *v1beta1.Canary, err error) {
|
||||
func (c *FakeCanaries) Create(canary *v1alpha1.Canary) (result *v1alpha1.Canary, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(canariesResource, c.ns, canary), &v1beta1.Canary{})
|
||||
Invokes(testing.NewCreateAction(canariesResource, c.ns, canary), &v1alpha1.Canary{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Canary), err
|
||||
return obj.(*v1alpha1.Canary), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a canary and updates it. Returns the server's representation of the canary, and an error, if there is any.
|
||||
func (c *FakeCanaries) Update(canary *v1beta1.Canary) (result *v1beta1.Canary, err error) {
|
||||
func (c *FakeCanaries) Update(canary *v1alpha1.Canary) (result *v1alpha1.Canary, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(canariesResource, c.ns, canary), &v1beta1.Canary{})
|
||||
Invokes(testing.NewUpdateAction(canariesResource, c.ns, canary), &v1alpha1.Canary{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Canary), err
|
||||
return obj.(*v1alpha1.Canary), 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 *FakeCanaries) UpdateStatus(canary *v1beta1.Canary) (*v1beta1.Canary, error) {
|
||||
func (c *FakeCanaries) UpdateStatus(canary *v1alpha1.Canary) (*v1alpha1.Canary, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(canariesResource, "status", c.ns, canary), &v1beta1.Canary{})
|
||||
Invokes(testing.NewUpdateSubresourceAction(canariesResource, "status", c.ns, canary), &v1alpha1.Canary{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Canary), err
|
||||
return obj.(*v1alpha1.Canary), err
|
||||
}
|
||||
|
||||
// Delete takes name of the canary and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeCanaries) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(canariesResource, c.ns, name), &v1beta1.Canary{})
|
||||
Invokes(testing.NewDeleteAction(canariesResource, c.ns, name), &v1alpha1.Canary{})
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -124,17 +124,17 @@ func (c *FakeCanaries) Delete(name string, options *v1.DeleteOptions) error {
|
||||
func (c *FakeCanaries) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(canariesResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.CanaryList{})
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.CanaryList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched canary.
|
||||
func (c *FakeCanaries) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Canary, err error) {
|
||||
func (c *FakeCanaries) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Canary, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(canariesResource, c.ns, name, data, subresources...), &v1beta1.Canary{})
|
||||
Invokes(testing.NewPatchSubresourceAction(canariesResource, c.ns, name, data, subresources...), &v1alpha1.Canary{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Canary), err
|
||||
return obj.(*v1alpha1.Canary), err
|
||||
}
|
||||
@@ -19,26 +19,22 @@ limitations under the License.
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/typed/flagger/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeFlaggerV1beta1 struct {
|
||||
type FakeFlaggerV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeFlaggerV1beta1) Canaries(namespace string) v1beta1.CanaryInterface {
|
||||
func (c *FakeFlaggerV1alpha1) Canaries(namespace string) v1alpha1.CanaryInterface {
|
||||
return &FakeCanaries{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeFlaggerV1beta1) CanaryDeployments(namespace string) v1beta1.CanaryDeploymentInterface {
|
||||
return &FakeCanaryDeployments{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeFlaggerV1beta1) RESTClient() rest.Interface {
|
||||
func (c *FakeFlaggerV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
@@ -16,36 +16,31 @@ limitations under the License.
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
"github.com/stefanprodan/flagger/pkg/client/clientset/versioned/scheme"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type FlaggerV1beta1Interface interface {
|
||||
type FlaggerV1alpha1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
CanariesGetter
|
||||
CanaryDeploymentsGetter
|
||||
}
|
||||
|
||||
// FlaggerV1beta1Client is used to interact with features provided by the flagger.app group.
|
||||
type FlaggerV1beta1Client struct {
|
||||
// FlaggerV1alpha1Client is used to interact with features provided by the flagger.app group.
|
||||
type FlaggerV1alpha1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *FlaggerV1beta1Client) Canaries(namespace string) CanaryInterface {
|
||||
func (c *FlaggerV1alpha1Client) Canaries(namespace string) CanaryInterface {
|
||||
return newCanaries(c, namespace)
|
||||
}
|
||||
|
||||
func (c *FlaggerV1beta1Client) CanaryDeployments(namespace string) CanaryDeploymentInterface {
|
||||
return newCanaryDeployments(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new FlaggerV1beta1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*FlaggerV1beta1Client, error) {
|
||||
// NewForConfig creates a new FlaggerV1alpha1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*FlaggerV1alpha1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
@@ -54,12 +49,12 @@ func NewForConfig(c *rest.Config) (*FlaggerV1beta1Client, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FlaggerV1beta1Client{client}, nil
|
||||
return &FlaggerV1alpha1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new FlaggerV1beta1Client for the given config and
|
||||
// NewForConfigOrDie creates a new FlaggerV1alpha1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *FlaggerV1beta1Client {
|
||||
func NewForConfigOrDie(c *rest.Config) *FlaggerV1alpha1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -67,13 +62,13 @@ func NewForConfigOrDie(c *rest.Config) *FlaggerV1beta1Client {
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new FlaggerV1beta1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *FlaggerV1beta1Client {
|
||||
return &FlaggerV1beta1Client{c}
|
||||
// New creates a new FlaggerV1alpha1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *FlaggerV1alpha1Client {
|
||||
return &FlaggerV1alpha1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
gv := v1alpha1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
@@ -87,7 +82,7 @@ func setConfigDefaults(config *rest.Config) error {
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FlaggerV1beta1Client) RESTClient() rest.Interface {
|
||||
func (c *FlaggerV1alpha1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -16,8 +16,6 @@ limitations under the License.
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
type CanaryExpansion interface{}
|
||||
|
||||
type CanaryDeploymentExpansion interface{}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
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 client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
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"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// CanaryDeploymentsGetter has a method to return a CanaryDeploymentInterface.
|
||||
// A group's client should implement this interface.
|
||||
type CanaryDeploymentsGetter interface {
|
||||
CanaryDeployments(namespace string) CanaryDeploymentInterface
|
||||
}
|
||||
|
||||
// CanaryDeploymentInterface has methods to work with CanaryDeployment resources.
|
||||
type CanaryDeploymentInterface interface {
|
||||
Create(*v1beta1.CanaryDeployment) (*v1beta1.CanaryDeployment, error)
|
||||
Update(*v1beta1.CanaryDeployment) (*v1beta1.CanaryDeployment, error)
|
||||
UpdateStatus(*v1beta1.CanaryDeployment) (*v1beta1.CanaryDeployment, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta1.CanaryDeployment, error)
|
||||
List(opts v1.ListOptions) (*v1beta1.CanaryDeploymentList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CanaryDeployment, err error)
|
||||
CanaryDeploymentExpansion
|
||||
}
|
||||
|
||||
// canaryDeployments implements CanaryDeploymentInterface
|
||||
type canaryDeployments struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newCanaryDeployments returns a CanaryDeployments
|
||||
func newCanaryDeployments(c *FlaggerV1beta1Client, namespace string) *canaryDeployments {
|
||||
return &canaryDeployments{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the canaryDeployment, and returns the corresponding canaryDeployment object, and an error if there is any.
|
||||
func (c *canaryDeployments) Get(name string, options v1.GetOptions) (result *v1beta1.CanaryDeployment, err error) {
|
||||
result = &v1beta1.CanaryDeployment{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of CanaryDeployments that match those selectors.
|
||||
func (c *canaryDeployments) List(opts v1.ListOptions) (result *v1beta1.CanaryDeploymentList, err error) {
|
||||
result = &v1beta1.CanaryDeploymentList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested canaryDeployments.
|
||||
func (c *canaryDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a canaryDeployment and creates it. Returns the server's representation of the canaryDeployment, and an error, if there is any.
|
||||
func (c *canaryDeployments) Create(canaryDeployment *v1beta1.CanaryDeployment) (result *v1beta1.CanaryDeployment, err error) {
|
||||
result = &v1beta1.CanaryDeployment{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
Body(canaryDeployment).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a canaryDeployment and updates it. Returns the server's representation of the canaryDeployment, and an error, if there is any.
|
||||
func (c *canaryDeployments) Update(canaryDeployment *v1beta1.CanaryDeployment) (result *v1beta1.CanaryDeployment, err error) {
|
||||
result = &v1beta1.CanaryDeployment{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
Name(canaryDeployment.Name).
|
||||
Body(canaryDeployment).
|
||||
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 *canaryDeployments) UpdateStatus(canaryDeployment *v1beta1.CanaryDeployment) (result *v1beta1.CanaryDeployment, err error) {
|
||||
result = &v1beta1.CanaryDeployment{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
Name(canaryDeployment.Name).
|
||||
SubResource("status").
|
||||
Body(canaryDeployment).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the canaryDeployment and deletes it. Returns an error if one occurs.
|
||||
func (c *canaryDeployments) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *canaryDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched canaryDeployment.
|
||||
func (c *canaryDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CanaryDeployment, err error) {
|
||||
result = &v1beta1.CanaryDeployment{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("canarydeployments").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
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 client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeCanaryDeployments implements CanaryDeploymentInterface
|
||||
type FakeCanaryDeployments struct {
|
||||
Fake *FakeFlaggerV1beta1
|
||||
ns string
|
||||
}
|
||||
|
||||
var canarydeploymentsResource = schema.GroupVersionResource{Group: "flagger.app", Version: "v1beta1", Resource: "canarydeployments"}
|
||||
|
||||
var canarydeploymentsKind = schema.GroupVersionKind{Group: "flagger.app", Version: "v1beta1", Kind: "CanaryDeployment"}
|
||||
|
||||
// Get takes name of the canaryDeployment, and returns the corresponding canaryDeployment object, and an error if there is any.
|
||||
func (c *FakeCanaryDeployments) Get(name string, options v1.GetOptions) (result *v1beta1.CanaryDeployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(canarydeploymentsResource, c.ns, name), &v1beta1.CanaryDeployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CanaryDeployment), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of CanaryDeployments that match those selectors.
|
||||
func (c *FakeCanaryDeployments) List(opts v1.ListOptions) (result *v1beta1.CanaryDeploymentList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(canarydeploymentsResource, canarydeploymentsKind, c.ns, opts), &v1beta1.CanaryDeploymentList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.CanaryDeploymentList{ListMeta: obj.(*v1beta1.CanaryDeploymentList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.CanaryDeploymentList).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 canaryDeployments.
|
||||
func (c *FakeCanaryDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(canarydeploymentsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a canaryDeployment and creates it. Returns the server's representation of the canaryDeployment, and an error, if there is any.
|
||||
func (c *FakeCanaryDeployments) Create(canaryDeployment *v1beta1.CanaryDeployment) (result *v1beta1.CanaryDeployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(canarydeploymentsResource, c.ns, canaryDeployment), &v1beta1.CanaryDeployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CanaryDeployment), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a canaryDeployment and updates it. Returns the server's representation of the canaryDeployment, and an error, if there is any.
|
||||
func (c *FakeCanaryDeployments) Update(canaryDeployment *v1beta1.CanaryDeployment) (result *v1beta1.CanaryDeployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(canarydeploymentsResource, c.ns, canaryDeployment), &v1beta1.CanaryDeployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CanaryDeployment), 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 *FakeCanaryDeployments) UpdateStatus(canaryDeployment *v1beta1.CanaryDeployment) (*v1beta1.CanaryDeployment, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(canarydeploymentsResource, "status", c.ns, canaryDeployment), &v1beta1.CanaryDeployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CanaryDeployment), err
|
||||
}
|
||||
|
||||
// Delete takes name of the canaryDeployment and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeCanaryDeployments) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(canarydeploymentsResource, c.ns, name), &v1beta1.CanaryDeployment{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeCanaryDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(canarydeploymentsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.CanaryDeploymentList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched canaryDeployment.
|
||||
func (c *FakeCanaryDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CanaryDeployment, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(canarydeploymentsResource, c.ns, name, data, subresources...), &v1beta1.CanaryDeployment{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CanaryDeployment), err
|
||||
}
|
||||
@@ -19,14 +19,14 @@ limitations under the License.
|
||||
package flagger
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/flagger/v1alpha1"
|
||||
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1beta1 provides access to shared informers for resources in V1beta1.
|
||||
V1beta1() v1beta1.Interface
|
||||
// V1alpha1 provides access to shared informers for resources in V1alpha1.
|
||||
V1alpha1() v1alpha1.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
@@ -40,7 +40,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1beta1 returns a new v1beta1.Interface.
|
||||
func (g *group) V1beta1() v1beta1.Interface {
|
||||
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
// V1alpha1 returns a new v1alpha1.Interface.
|
||||
func (g *group) V1alpha1() v1alpha1.Interface {
|
||||
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ limitations under the License.
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
flaggerv1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
versioned "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/client/listers/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/client/listers/flagger/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
@@ -35,7 +35,7 @@ import (
|
||||
// Canaries.
|
||||
type CanaryInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1beta1.CanaryLister
|
||||
Lister() v1alpha1.CanaryLister
|
||||
}
|
||||
|
||||
type canaryInformer struct {
|
||||
@@ -61,16 +61,16 @@ func NewFilteredCanaryInformer(client versioned.Interface, namespace string, res
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.FlaggerV1beta1().Canaries(namespace).List(options)
|
||||
return client.FlaggerV1alpha1().Canaries(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.FlaggerV1beta1().Canaries(namespace).Watch(options)
|
||||
return client.FlaggerV1alpha1().Canaries(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&flaggerv1beta1.Canary{},
|
||||
&flaggerv1alpha1.Canary{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
@@ -81,9 +81,9 @@ func (f *canaryInformer) defaultInformer(client versioned.Interface, resyncPerio
|
||||
}
|
||||
|
||||
func (f *canaryInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&flaggerv1beta1.Canary{}, f.defaultInformer)
|
||||
return f.factory.InformerFor(&flaggerv1alpha1.Canary{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *canaryInformer) Lister() v1beta1.CanaryLister {
|
||||
return v1beta1.NewCanaryLister(f.Informer().GetIndexer())
|
||||
func (f *canaryInformer) Lister() v1alpha1.CanaryLister {
|
||||
return v1alpha1.NewCanaryLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
|
||||
@@ -26,8 +26,6 @@ import (
|
||||
type Interface interface {
|
||||
// Canaries returns a CanaryInformer.
|
||||
Canaries() CanaryInformer
|
||||
// CanaryDeployments returns a CanaryDeploymentInformer.
|
||||
CanaryDeployments() CanaryDeploymentInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
@@ -45,8 +43,3 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
|
||||
func (v *version) Canaries() CanaryInformer {
|
||||
return &canaryInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// CanaryDeployments returns a CanaryDeploymentInformer.
|
||||
func (v *version) CanaryDeployments() CanaryDeploymentInformer {
|
||||
return &canaryDeploymentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
flaggerv1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
versioned "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/client/listers/flagger/v1beta1"
|
||||
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"
|
||||
)
|
||||
|
||||
// CanaryDeploymentInformer provides access to a shared informer and lister for
|
||||
// CanaryDeployments.
|
||||
type CanaryDeploymentInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1beta1.CanaryDeploymentLister
|
||||
}
|
||||
|
||||
type canaryDeploymentInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewCanaryDeploymentInformer constructs a new informer for CanaryDeployment 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 NewCanaryDeploymentInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredCanaryDeploymentInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredCanaryDeploymentInformer constructs a new informer for CanaryDeployment 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 NewFilteredCanaryDeploymentInformer(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.FlaggerV1beta1().CanaryDeployments(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.FlaggerV1beta1().CanaryDeployments(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&flaggerv1beta1.CanaryDeployment{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *canaryDeploymentInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredCanaryDeploymentInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *canaryDeploymentInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&flaggerv1beta1.CanaryDeployment{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *canaryDeploymentInformer) Lister() v1beta1.CanaryDeploymentLister {
|
||||
return v1beta1.NewCanaryDeploymentLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -21,7 +21,7 @@ package externalversions
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
@@ -52,11 +52,9 @@ func (f *genericInformer) Lister() cache.GenericLister {
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=flagger.app, Version=v1beta1
|
||||
case v1beta1.SchemeGroupVersion.WithResource("canaries"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Flagger().V1beta1().Canaries().Informer()}, nil
|
||||
case v1beta1.SchemeGroupVersion.WithResource("canarydeployments"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Flagger().V1beta1().CanaryDeployments().Informer()}, nil
|
||||
// Group=flagger.app, Version=v1alpha1
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("canaries"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Flagger().V1alpha1().Canaries().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ limitations under the License.
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
v1alpha1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
// CanaryLister helps list Canaries.
|
||||
type CanaryLister interface {
|
||||
// List lists all Canaries in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1beta1.Canary, err error)
|
||||
List(selector labels.Selector) (ret []*v1alpha1.Canary, err error)
|
||||
// Canaries returns an object that can list and get Canaries.
|
||||
Canaries(namespace string) CanaryNamespaceLister
|
||||
CanaryListerExpansion
|
||||
@@ -45,9 +45,9 @@ func NewCanaryLister(indexer cache.Indexer) CanaryLister {
|
||||
}
|
||||
|
||||
// List lists all Canaries in the indexer.
|
||||
func (s *canaryLister) List(selector labels.Selector) (ret []*v1beta1.Canary, err error) {
|
||||
func (s *canaryLister) List(selector labels.Selector) (ret []*v1alpha1.Canary, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.Canary))
|
||||
ret = append(ret, m.(*v1alpha1.Canary))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@@ -60,9 +60,9 @@ func (s *canaryLister) Canaries(namespace string) CanaryNamespaceLister {
|
||||
// CanaryNamespaceLister helps list and get Canaries.
|
||||
type CanaryNamespaceLister interface {
|
||||
// List lists all Canaries in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*v1beta1.Canary, err error)
|
||||
List(selector labels.Selector) (ret []*v1alpha1.Canary, err error)
|
||||
// Get retrieves the Canary from the indexer for a given namespace and name.
|
||||
Get(name string) (*v1beta1.Canary, error)
|
||||
Get(name string) (*v1alpha1.Canary, error)
|
||||
CanaryNamespaceListerExpansion
|
||||
}
|
||||
|
||||
@@ -74,21 +74,21 @@ type canaryNamespaceLister struct {
|
||||
}
|
||||
|
||||
// List lists all Canaries in the indexer for a given namespace.
|
||||
func (s canaryNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.Canary, err error) {
|
||||
func (s canaryNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Canary, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.Canary))
|
||||
ret = append(ret, m.(*v1alpha1.Canary))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the Canary from the indexer for a given namespace and name.
|
||||
func (s canaryNamespaceLister) Get(name string) (*v1beta1.Canary, error) {
|
||||
func (s canaryNamespaceLister) Get(name string) (*v1alpha1.Canary, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1beta1.Resource("canary"), name)
|
||||
return nil, errors.NewNotFound(v1alpha1.Resource("canary"), name)
|
||||
}
|
||||
return obj.(*v1beta1.Canary), nil
|
||||
return obj.(*v1alpha1.Canary), nil
|
||||
}
|
||||
@@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
package v1alpha1
|
||||
|
||||
// CanaryListerExpansion allows custom methods to be added to
|
||||
// CanaryLister.
|
||||
@@ -25,11 +25,3 @@ type CanaryListerExpansion interface{}
|
||||
// CanaryNamespaceListerExpansion allows custom methods to be added to
|
||||
// CanaryNamespaceLister.
|
||||
type CanaryNamespaceListerExpansion interface{}
|
||||
|
||||
// CanaryDeploymentListerExpansion allows custom methods to be added to
|
||||
// CanaryDeploymentLister.
|
||||
type CanaryDeploymentListerExpansion interface{}
|
||||
|
||||
// CanaryDeploymentNamespaceListerExpansion allows custom methods to be added to
|
||||
// CanaryDeploymentNamespaceLister.
|
||||
type CanaryDeploymentNamespaceListerExpansion interface{}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// CanaryDeploymentLister helps list CanaryDeployments.
|
||||
type CanaryDeploymentLister interface {
|
||||
// List lists all CanaryDeployments in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1beta1.CanaryDeployment, err error)
|
||||
// CanaryDeployments returns an object that can list and get CanaryDeployments.
|
||||
CanaryDeployments(namespace string) CanaryDeploymentNamespaceLister
|
||||
CanaryDeploymentListerExpansion
|
||||
}
|
||||
|
||||
// canaryDeploymentLister implements the CanaryDeploymentLister interface.
|
||||
type canaryDeploymentLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewCanaryDeploymentLister returns a new CanaryDeploymentLister.
|
||||
func NewCanaryDeploymentLister(indexer cache.Indexer) CanaryDeploymentLister {
|
||||
return &canaryDeploymentLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all CanaryDeployments in the indexer.
|
||||
func (s *canaryDeploymentLister) List(selector labels.Selector) (ret []*v1beta1.CanaryDeployment, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.CanaryDeployment))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// CanaryDeployments returns an object that can list and get CanaryDeployments.
|
||||
func (s *canaryDeploymentLister) CanaryDeployments(namespace string) CanaryDeploymentNamespaceLister {
|
||||
return canaryDeploymentNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// CanaryDeploymentNamespaceLister helps list and get CanaryDeployments.
|
||||
type CanaryDeploymentNamespaceLister interface {
|
||||
// List lists all CanaryDeployments in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*v1beta1.CanaryDeployment, err error)
|
||||
// Get retrieves the CanaryDeployment from the indexer for a given namespace and name.
|
||||
Get(name string) (*v1beta1.CanaryDeployment, error)
|
||||
CanaryDeploymentNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// canaryDeploymentNamespaceLister implements the CanaryDeploymentNamespaceLister
|
||||
// interface.
|
||||
type canaryDeploymentNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all CanaryDeployments in the indexer for a given namespace.
|
||||
func (s canaryDeploymentNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.CanaryDeployment, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.CanaryDeployment))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the CanaryDeployment from the indexer for a given namespace and name.
|
||||
func (s canaryDeploymentNamespaceLister) Get(name string) (*v1beta1.CanaryDeployment, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1beta1.Resource("canarydeployment"), name)
|
||||
}
|
||||
return obj.(*v1beta1.CanaryDeployment), nil
|
||||
}
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
istioclientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
flaggerscheme "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/scheme"
|
||||
flaggerinformers "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/flagger/v1beta1"
|
||||
flaggerlisters "github.com/stefanprodan/flagger/pkg/client/listers/flagger/v1beta1"
|
||||
flaggerinformers "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/flagger/v1alpha1"
|
||||
flaggerlisters "github.com/stefanprodan/flagger/pkg/client/listers/flagger/v1alpha1"
|
||||
"go.uber.org/zap"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -76,7 +76,7 @@ func NewController(
|
||||
}
|
||||
|
||||
rolloutInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: ctrl.enqueueRollout,
|
||||
AddFunc: ctrl.enqueue,
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
oldRoll, ok := checkCustomResourceType(old, logger)
|
||||
if !ok {
|
||||
@@ -89,7 +89,7 @@ func NewController(
|
||||
|
||||
if diff := cmp.Diff(newRoll.Spec, oldRoll.Spec); diff != "" {
|
||||
ctrl.logger.Debugf("Diff detected %s.%s %s", oldRoll.Name, oldRoll.Namespace, diff)
|
||||
ctrl.enqueueRollout(new)
|
||||
ctrl.enqueue(new)
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(old interface{}) {
|
||||
@@ -108,7 +108,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
|
||||
c.logger.Info("Starting controller")
|
||||
c.logger.Info("Starting operator")
|
||||
|
||||
for i := 0; i < threadiness; i++ {
|
||||
go wait.Until(func() {
|
||||
@@ -117,7 +117,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
||||
}, time.Second, stopCh)
|
||||
}
|
||||
|
||||
c.logger.Info("Started workers")
|
||||
c.logger.Info("Started operator workers")
|
||||
|
||||
tickChan := time.NewTicker(c.rolloutWindow).C
|
||||
for {
|
||||
@@ -125,7 +125,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
||||
case <-tickChan:
|
||||
c.doRollouts()
|
||||
case <-stopCh:
|
||||
c.logger.Info("Shutting down workers")
|
||||
c.logger.Info("Shutting down operator workers")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -174,19 +174,26 @@ func (c *Controller) syncHandler(key string) error {
|
||||
utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
|
||||
return nil
|
||||
}
|
||||
rollout, err := c.rolloutLister.Canaries(namespace).Get(name)
|
||||
cd, err := c.rolloutLister.Canaries(namespace).Get(name)
|
||||
if errors.IsNotFound(err) {
|
||||
utilruntime.HandleError(fmt.Errorf("rollout '%s' in work queue no longer exists", key))
|
||||
utilruntime.HandleError(fmt.Errorf("'%s' in work queue no longer exists", key))
|
||||
return nil
|
||||
}
|
||||
|
||||
c.rollouts.Store(fmt.Sprintf("%s.%s", rollout.Name, rollout.Namespace), rollout)
|
||||
c.rollouts.Store(fmt.Sprintf("%s.%s", cd.Name, cd.Namespace), cd)
|
||||
|
||||
err = c.bootstrapDeployment(cd)
|
||||
if err != nil {
|
||||
c.logger.Warnf("%s.%s bootstrap error %v", cd.Name, cd.Namespace, err)
|
||||
return err
|
||||
}
|
||||
|
||||
c.logger.Infof("Synced %s", key)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) enqueueRollout(obj interface{}) {
|
||||
func (c *Controller) enqueue(obj interface{}) {
|
||||
var key string
|
||||
var err error
|
||||
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
||||
@@ -196,6 +203,16 @@ func (c *Controller) enqueueRollout(obj interface{}) {
|
||||
c.workqueue.AddRateLimited(key)
|
||||
}
|
||||
|
||||
func checkCustomResourceType(obj interface{}, logger *zap.SugaredLogger) (flaggerv1.Canary, bool) {
|
||||
var roll *flaggerv1.Canary
|
||||
var ok bool
|
||||
if roll, ok = obj.(*flaggerv1.Canary); !ok {
|
||||
logger.Errorf("Event Watch received an invalid object: %#v", obj)
|
||||
return flaggerv1.Canary{}, false
|
||||
}
|
||||
return *roll, true
|
||||
}
|
||||
|
||||
func (c *Controller) recordEventInfof(r *flaggerv1.Canary, template string, args ...interface{}) {
|
||||
c.logger.Infof(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeNormal, "Synced", fmt.Sprintf(template, args...))
|
||||
@@ -210,13 +227,3 @@ func (c *Controller) recordEventWarningf(r *flaggerv1.Canary, template string, a
|
||||
c.logger.Infof(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func checkCustomResourceType(obj interface{}, logger *zap.SugaredLogger) (flaggerv1.Canary, bool) {
|
||||
var roll *flaggerv1.Canary
|
||||
var ok bool
|
||||
if roll, ok = obj.(*flaggerv1.Canary); !ok {
|
||||
logger.Errorf("Event Watch received an invalid object: %#v", obj)
|
||||
return flaggerv1.Canary{}, false
|
||||
}
|
||||
return *roll, true
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package operator
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func (c *Controller) bootstrapDeployment(cd *flaggerv1.CanaryDeployment) error {
|
||||
func (c *Controller) bootstrapDeployment(cd *flaggerv1.Canary) error {
|
||||
|
||||
canaryName := cd.Spec.TargetRef.Name
|
||||
primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name)
|
||||
@@ -39,7 +39,7 @@ func (c *Controller) bootstrapDeployment(cd *flaggerv1.CanaryDeployment) error {
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryDeploymentKind,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -83,7 +83,7 @@ func (c *Controller) bootstrapDeployment(cd *flaggerv1.CanaryDeployment) error {
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryDeploymentKind,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -122,7 +122,7 @@ func (c *Controller) bootstrapDeployment(cd *flaggerv1.CanaryDeployment) error {
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryDeploymentKind,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -160,7 +160,7 @@ func (c *Controller) bootstrapDeployment(cd *flaggerv1.CanaryDeployment) error {
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryDeploymentKind,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -201,7 +201,7 @@ func (c *Controller) bootstrapDeployment(cd *flaggerv1.CanaryDeployment) error {
|
||||
*metav1.NewControllerRef(cd, schema.GroupVersionKind{
|
||||
Group: flaggerv1.SchemeGroupVersion.Group,
|
||||
Version: flaggerv1.SchemeGroupVersion.Version,
|
||||
Kind: flaggerv1.CanaryDeploymentKind,
|
||||
Kind: flaggerv1.CanaryKind,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
func (c *Controller) doRollouts() {
|
||||
c.rollouts.Range(func(key interface{}, value interface{}) bool {
|
||||
r := value.(*flaggerv1.Canary)
|
||||
if r.Spec.TargetKind == "Deployment" {
|
||||
if r.Spec.TargetRef.Kind == "Deployment" {
|
||||
go c.advanceDeploymentRollout(r.Name, r.Namespace)
|
||||
}
|
||||
return true
|
||||
@@ -27,6 +27,12 @@ func (c *Controller) advanceDeploymentRollout(name string, namespace string) {
|
||||
return
|
||||
}
|
||||
|
||||
err := c.bootstrapDeployment(r)
|
||||
if err != nil {
|
||||
c.recordEventWarningf(r, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// set max weight default value to 100%
|
||||
maxWeight := 100
|
||||
if r.Spec.CanaryAnalysis.MaxWeight > 0 {
|
||||
@@ -34,13 +40,13 @@ func (c *Controller) advanceDeploymentRollout(name string, namespace string) {
|
||||
}
|
||||
|
||||
// gate stage: check if canary deployment exists and is healthy
|
||||
canary, ok := c.getCanaryDeployment(r, r.Spec.Canary.Name, r.Namespace)
|
||||
canary, ok := c.getCanaryDeployment(r, r.Spec.TargetRef.Name, r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if primary deployment exists and is healthy
|
||||
primary, ok := c.getDeployment(r, r.Spec.Primary.Name, r.Namespace)
|
||||
primary, ok := c.getDeployment(r, fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name), r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -60,7 +66,7 @@ func (c *Controller) advanceDeploymentRollout(name string, namespace string) {
|
||||
// gate stage: check if the number of failed checks reached the threshold
|
||||
if r.Status.State == "running" && r.Status.FailedChecks >= r.Spec.CanaryAnalysis.Threshold {
|
||||
c.recordEventWarningf(r, "Rolling back %s.%s failed checks threshold reached %v",
|
||||
r.Spec.Canary.Name, r.Namespace, r.Status.FailedChecks)
|
||||
r.Name, r.Namespace, r.Status.FailedChecks)
|
||||
|
||||
// route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
@@ -136,7 +142,7 @@ func (c *Controller) advanceDeploymentRollout(name string, namespace string) {
|
||||
}
|
||||
|
||||
func (c *Controller) getRollout(name string, namespace string) (*flaggerv1.Canary, bool) {
|
||||
r, err := c.rolloutClient.FlaggerV1beta1().Canaries(namespace).Get(name, v1.GetOptions{})
|
||||
r, err := c.rolloutClient.FlaggerV1alpha1().Canaries(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
@@ -146,19 +152,26 @@ func (c *Controller) getRollout(name string, namespace string) (*flaggerv1.Canar
|
||||
}
|
||||
|
||||
func (c *Controller) checkRolloutStatus(r *flaggerv1.Canary, canary *appsv1.Deployment) bool {
|
||||
var err error
|
||||
canaryRevision, err := c.getDeploymentSpecEnc(canary)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s not found: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "" {
|
||||
r.Status = flaggerv1.CanaryStatus{
|
||||
State: "running",
|
||||
CanaryRevision: canary.ResourceVersion,
|
||||
State: "initialized",
|
||||
CanaryRevision: canaryRevision,
|
||||
FailedChecks: 0,
|
||||
}
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().Canaries(r.Namespace).Update(r)
|
||||
r, err = c.rolloutClient.FlaggerV1alpha1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
c.recordEventInfof(r, "Initialization done! %s.%s", canary.GetName(), canary.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "running" {
|
||||
@@ -166,38 +179,31 @@ func (c *Controller) checkRolloutStatus(r *flaggerv1.Canary, canary *appsv1.Depl
|
||||
}
|
||||
|
||||
if r.Status.State == "promotion-finished" {
|
||||
c.setCanaryRevision(r, "finished")
|
||||
c.logger.Infof("Promotion completed! %s.%s revision %s", r.Spec.Canary.Name, r.Namespace,
|
||||
c.getDeploymentRevision(r.Spec.Canary.Name, r.Namespace))
|
||||
c.setCanaryRevision(r, canary, "finished")
|
||||
c.logger.Infof("Promotion completed! %s.%s", r.Name, r.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "promotion-failed" {
|
||||
c.setCanaryRevision(r, "failed")
|
||||
c.logger.Infof("Promotion failed! %s.%s revision %s", r.Spec.Canary.Name, r.Namespace,
|
||||
c.getDeploymentRevision(r.Spec.Canary.Name, r.Namespace))
|
||||
c.setCanaryRevision(r, canary, "failed")
|
||||
c.logger.Infof("Promotion failed! %s.%s", r.Name, r.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.CanaryRevision != canary.ResourceVersion {
|
||||
c.recordEventInfof(r, "New revision detected %s.%s old %s new %s",
|
||||
canary.GetName(), canary.Namespace, r.Status.CanaryRevision, canary.ResourceVersion)
|
||||
if diff, err := c.diffDeploymentSpec(r, canary); diff {
|
||||
c.recordEventInfof(r, "New revision detected %s.%s",
|
||||
canary.GetName(), canary.Namespace)
|
||||
canary.Spec.Replicas = int32p(1)
|
||||
canary, err = c.kubeClient.AppsV1().Deployments(canary.Namespace).Update(canary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Scaling up %s.%s failed: %v", canary.GetName(), canary.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
r.Status = flaggerv1.CanaryStatus{
|
||||
State: "running",
|
||||
CanaryRevision: canary.ResourceVersion,
|
||||
FailedChecks: 0,
|
||||
}
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
FailedChecks: 0,
|
||||
}
|
||||
c.setCanaryRevision(r, canary, "running")
|
||||
c.recordEventInfof(r, "Scaling up %s.%s", canary.GetName(), canary.Namespace)
|
||||
|
||||
return false
|
||||
@@ -209,7 +215,7 @@ func (c *Controller) checkRolloutStatus(r *flaggerv1.Canary, canary *appsv1.Depl
|
||||
func (c *Controller) updateRolloutStatus(r *flaggerv1.Canary, status string) bool {
|
||||
var err error
|
||||
r.Status.State = status
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().Canaries(r.Namespace).Update(r)
|
||||
r, err = c.rolloutClient.FlaggerV1alpha1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
@@ -220,7 +226,7 @@ func (c *Controller) updateRolloutStatus(r *flaggerv1.Canary, status string) boo
|
||||
func (c *Controller) updateRolloutFailedChecks(r *flaggerv1.Canary, val int) bool {
|
||||
var err error
|
||||
r.Status.FailedChecks = val
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().Canaries(r.Namespace).Update(r)
|
||||
r, err = c.rolloutClient.FlaggerV1alpha1().Canaries(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
@@ -262,20 +268,10 @@ func (c *Controller) getCanaryDeployment(r *flaggerv1.Canary, name string, names
|
||||
return dep, true
|
||||
}
|
||||
|
||||
func (c *Controller) getDeploymentRevision(name string, namespace string) string {
|
||||
dep, err := c.kubeClient.AppsV1().Deployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.logger.Errorf("Deployment %s.%s not found", name, namespace)
|
||||
return ""
|
||||
}
|
||||
|
||||
return dep.ResourceVersion
|
||||
}
|
||||
|
||||
func (c *Controller) checkDeploymentMetrics(r *flaggerv1.Canary) bool {
|
||||
for _, metric := range r.Spec.CanaryAnalysis.Metrics {
|
||||
if metric.Name == "istio_requests_total" {
|
||||
val, err := c.getDeploymentCounter(r.Spec.Canary.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
val, err := c.getDeploymentCounter(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.metricsServer, err)
|
||||
return false
|
||||
@@ -288,7 +284,7 @@ func (c *Controller) checkDeploymentMetrics(r *flaggerv1.Canary) bool {
|
||||
}
|
||||
|
||||
if metric.Name == "istio_request_duration_seconds_bucket" {
|
||||
val, err := c.GetDeploymentHistogram(r.Spec.Canary.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
val, err := c.GetDeploymentHistogram(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.metricsServer, err)
|
||||
return false
|
||||
@@ -306,9 +302,9 @@ func (c *Controller) checkDeploymentMetrics(r *flaggerv1.Canary) bool {
|
||||
}
|
||||
|
||||
func (c *Controller) scaleToZeroCanary(r *flaggerv1.Canary) {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(r.Namespace).Get(r.Spec.Canary.Name, v1.GetOptions{})
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(r.Namespace).Get(r.Spec.TargetRef.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", r.Spec.Canary.Name, r.Namespace)
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", r.Spec.TargetRef.Name, r.Namespace)
|
||||
return
|
||||
}
|
||||
//HPA https://github.com/kubernetes/kubernetes/pull/29212
|
||||
@@ -320,22 +316,15 @@ func (c *Controller) scaleToZeroCanary(r *flaggerv1.Canary) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) setCanaryRevision(r *flaggerv1.Canary, status string) {
|
||||
canaryRevision := c.getDeploymentRevision(r.Spec.Canary.Name, r.Namespace)
|
||||
r, ok := c.getRollout(r.Name, r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
func (c *Controller) setCanaryRevision(r *flaggerv1.Canary, canary *appsv1.Deployment, status string) {
|
||||
r.Status = flaggerv1.CanaryStatus{
|
||||
State: status,
|
||||
CanaryRevision: canaryRevision,
|
||||
FailedChecks: r.Status.FailedChecks,
|
||||
State: status,
|
||||
FailedChecks: r.Status.FailedChecks,
|
||||
}
|
||||
r, err := c.rolloutClient.FlaggerV1beta1().Canaries(r.Namespace).Update(r)
|
||||
err := c.saveDeploymentSpec(r, canary)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
}
|
||||
//c.logger.Infof("Canary %s.%s status %+v", r.Spec.Canary.Name, r.Namespace, r.Status)
|
||||
}
|
||||
|
||||
func (c *Controller) getVirtualService(r *flaggerv1.Canary) (
|
||||
@@ -345,18 +334,18 @@ func (c *Controller) getVirtualService(r *flaggerv1.Canary) (
|
||||
ok bool,
|
||||
) {
|
||||
var err error
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Get(r.Spec.VirtualService.Name, v1.GetOptions{})
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Get(r.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s not found", r.Spec.VirtualService.Name, r.Namespace)
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s not found", r.Name, r.Namespace)
|
||||
return
|
||||
}
|
||||
|
||||
for _, http := range vs.Spec.Http {
|
||||
for _, route := range http.Route {
|
||||
if route.Destination.Host == r.Spec.Primary.Host {
|
||||
if route.Destination.Host == fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name) {
|
||||
primary = route
|
||||
}
|
||||
if route.Destination.Host == r.Spec.Canary.Host {
|
||||
if route.Destination.Host == r.Spec.TargetRef.Name {
|
||||
canary = route
|
||||
}
|
||||
}
|
||||
@@ -364,7 +353,7 @@ func (c *Controller) getVirtualService(r *flaggerv1.Canary) (
|
||||
|
||||
if primary.Weight == 0 && canary.Weight == 0 {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s does not contain routes for %s and %s",
|
||||
r.Spec.VirtualService.Name, r.Namespace, r.Spec.Primary.Host, r.Spec.Canary.Host)
|
||||
r.Name, r.Namespace, fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name), r.Spec.TargetRef.Name)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -387,7 +376,7 @@ func (c *Controller) updateVirtualServiceRoutes(
|
||||
var err error
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Update(vs)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s update failed: %v", r.Spec.VirtualService.Name, r.Namespace, err)
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package operator
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (c *Controller) saveDeploymentSpec(cd *flaggerv1.CanaryDeployment, dep *appsv1.Deployment) error {
|
||||
func (c *Controller) saveDeploymentSpec(cd *flaggerv1.Canary, dep *appsv1.Deployment) error {
|
||||
specJson, err := json.Marshal(dep.Spec.Template.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -22,14 +22,14 @@ func (c *Controller) saveDeploymentSpec(cd *flaggerv1.CanaryDeployment, dep *app
|
||||
|
||||
specEnc := base64.StdEncoding.EncodeToString(specJson)
|
||||
cd.Status.CanaryRevision = specEnc
|
||||
cd, err = c.rolloutClient.FlaggerV1beta1().CanaryDeployments(cd.Namespace).Update(cd)
|
||||
cd, err = c.rolloutClient.FlaggerV1alpha1().Canaries(cd.Namespace).Update(cd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) diffDeploymentSpec(cd *flaggerv1.CanaryDeployment, dep *appsv1.Deployment) (bool, error) {
|
||||
func (c *Controller) diffDeploymentSpec(cd *flaggerv1.Canary, dep *appsv1.Deployment) (bool, error) {
|
||||
if cd.Status.CanaryRevision == "" {
|
||||
return true, nil
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
istiov1alpha3 "github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (c *Controller) doRollouts() {
|
||||
c.rollouts.Range(func(key interface{}, value interface{}) bool {
|
||||
r := value.(*flaggerv1.CanaryDeployment)
|
||||
if r.Spec.TargetRef.Kind == "Deployment" {
|
||||
go c.advanceDeploymentRollout(r.Name, r.Namespace)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Controller) advanceDeploymentRollout(name string, namespace string) {
|
||||
// gate stage: check if the rollout exists
|
||||
r, ok := c.getRollout(name, namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := c.bootstrapDeployment(r)
|
||||
if err != nil {
|
||||
c.recordEventWarningf(r, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// set max weight default value to 100%
|
||||
maxWeight := 100
|
||||
if r.Spec.CanaryAnalysis.MaxWeight > 0 {
|
||||
maxWeight = r.Spec.CanaryAnalysis.MaxWeight
|
||||
}
|
||||
|
||||
// gate stage: check if canary deployment exists and is healthy
|
||||
canary, ok := c.getCanaryDeployment(r, r.Spec.TargetRef.Name, r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if primary deployment exists and is healthy
|
||||
primary, ok := c.getDeployment(r, fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name), r.Namespace)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if virtual service exists
|
||||
// and if it contains weighted destination routes to the primary and canary services
|
||||
vs, primaryRoute, canaryRoute, ok := c.getVirtualService(r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if rollout should start (canary revision has changes) or continue
|
||||
if ok := c.checkRolloutStatus(r, canary); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if the number of failed checks reached the threshold
|
||||
if r.Status.State == "running" && r.Status.FailedChecks >= r.Spec.CanaryAnalysis.Threshold {
|
||||
c.recordEventWarningf(r, "Rolling back %s.%s failed checks threshold reached %v",
|
||||
r.Name, r.Namespace, r.Status.FailedChecks)
|
||||
|
||||
// route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
canaryRoute.Weight = 0
|
||||
if ok := c.updateVirtualServiceRoutes(r, vs, primaryRoute, canaryRoute); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.recordEventWarningf(r, "Canary failed! Scaling down %s.%s",
|
||||
canary.GetName(), canary.Namespace)
|
||||
|
||||
// shutdown canary
|
||||
c.scaleToZeroCanary(r)
|
||||
|
||||
// mark rollout as failed
|
||||
c.updateRolloutStatus(r, "promotion-failed")
|
||||
return
|
||||
}
|
||||
|
||||
// gate stage: check if the canary success rate is above the threshold
|
||||
// skip check if no traffic is routed to canary
|
||||
if canaryRoute.Weight == 0 {
|
||||
c.recordEventInfof(r, "Starting canary deployment for %s.%s", r.Name, r.Namespace)
|
||||
} else {
|
||||
if ok := c.checkDeploymentMetrics(r); !ok {
|
||||
c.updateRolloutFailedChecks(r, r.Status.FailedChecks+1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// routing stage: increase canary traffic percentage
|
||||
if canaryRoute.Weight < maxWeight {
|
||||
primaryRoute.Weight -= r.Spec.CanaryAnalysis.StepWeight
|
||||
if primaryRoute.Weight < 0 {
|
||||
primaryRoute.Weight = 0
|
||||
}
|
||||
canaryRoute.Weight += r.Spec.CanaryAnalysis.StepWeight
|
||||
if primaryRoute.Weight > 100 {
|
||||
primaryRoute.Weight = 100
|
||||
}
|
||||
|
||||
if ok := c.updateVirtualServiceRoutes(r, vs, primaryRoute, canaryRoute); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.recordEventInfof(r, "Advance %s.%s canary weight %v", r.Name, r.Namespace, canaryRoute.Weight)
|
||||
|
||||
// promotion stage: override primary.template.spec with the canary spec
|
||||
if canaryRoute.Weight == maxWeight {
|
||||
c.recordEventInfof(r, "Copying %s.%s template spec to %s.%s",
|
||||
canary.GetName(), canary.Namespace, primary.GetName(), primary.Namespace)
|
||||
|
||||
primary.Spec.Template.Spec = canary.Spec.Template.Spec
|
||||
_, err := c.kubeClient.AppsV1().Deployments(primary.Namespace).Update(primary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Updating template spec %s.%s failed: %v", primary.GetName(), primary.Namespace, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// final stage: route all traffic back to primary
|
||||
primaryRoute.Weight = 100
|
||||
canaryRoute.Weight = 0
|
||||
if ok := c.updateVirtualServiceRoutes(r, vs, primaryRoute, canaryRoute); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// final stage: mark rollout as finished and scale canary to zero replicas
|
||||
c.recordEventInfof(r, "Scaling down %s.%s", canary.GetName(), canary.Namespace)
|
||||
c.scaleToZeroCanary(r)
|
||||
c.updateRolloutStatus(r, "promotion-finished")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getRollout(name string, namespace string) (*flaggerv1.CanaryDeployment, bool) {
|
||||
r, err := c.rolloutClient.FlaggerV1beta1().CanaryDeployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.logger.Errorf("CanaryDeployment %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return r, true
|
||||
}
|
||||
|
||||
func (c *Controller) checkRolloutStatus(r *flaggerv1.CanaryDeployment, canary *appsv1.Deployment) bool {
|
||||
canaryRevision, err := c.getDeploymentSpecEnc(canary)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s not found: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "" {
|
||||
r.Status = flaggerv1.CanaryDeploymentStatus{
|
||||
State: "initialized",
|
||||
CanaryRevision: canaryRevision,
|
||||
FailedChecks: 0,
|
||||
}
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().CanaryDeployments(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
c.recordEventInfof(r, "Initialization done! %s.%ss", canary.GetName(), canary.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "running" {
|
||||
return true
|
||||
}
|
||||
|
||||
if r.Status.State == "promotion-finished" {
|
||||
c.setCanaryRevision(r, canary, "finished")
|
||||
c.logger.Infof("Promotion completed! %s.%s", r.Name, r.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if r.Status.State == "promotion-failed" {
|
||||
c.setCanaryRevision(r, canary, "failed")
|
||||
c.logger.Infof("Promotion failed! %s.%s", r.Name, r.Namespace)
|
||||
return false
|
||||
}
|
||||
|
||||
if diff, err := c.diffDeploymentSpec(r, canary); diff {
|
||||
c.recordEventInfof(r, "New revision detected %s.%s",
|
||||
canary.GetName(), canary.Namespace)
|
||||
canary.Spec.Replicas = int32p(1)
|
||||
canary, err = c.kubeClient.AppsV1().Deployments(canary.Namespace).Update(canary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Scaling up %s.%s failed: %v", canary.GetName(), canary.Namespace, err)
|
||||
return false
|
||||
}
|
||||
|
||||
r.Status = flaggerv1.CanaryDeploymentStatus{
|
||||
FailedChecks: 0,
|
||||
}
|
||||
c.setCanaryRevision(r, canary, "running")
|
||||
c.recordEventInfof(r, "Scaling up %s.%s", canary.GetName(), canary.Namespace)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Controller) updateRolloutStatus(r *flaggerv1.CanaryDeployment, status string) bool {
|
||||
var err error
|
||||
r.Status.State = status
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().CanaryDeployments(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) updateRolloutFailedChecks(r *flaggerv1.CanaryDeployment, val int) bool {
|
||||
var err error
|
||||
r.Status.FailedChecks = val
|
||||
r, err = c.rolloutClient.FlaggerV1beta1().CanaryDeployments(r.Namespace).Update(r)
|
||||
if err != nil {
|
||||
c.logger.Errorf("Canary %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) getDeployment(r *flaggerv1.CanaryDeployment, name string, namespace string) (*appsv1.Deployment, bool) {
|
||||
dep, err := c.kubeClient.AppsV1().Deployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if msg, healthy := getDeploymentStatus(dep); !healthy {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement %s", dep.GetName(), dep.Namespace, msg)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if dep.Spec.Replicas == nil || *dep.Spec.Replicas == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return dep, true
|
||||
}
|
||||
|
||||
func (c *Controller) getCanaryDeployment(r *flaggerv1.CanaryDeployment, name string, namespace string) (*appsv1.Deployment, bool) {
|
||||
dep, err := c.kubeClient.AppsV1().Deployments(namespace).Get(name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", name, namespace)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if msg, healthy := getDeploymentStatus(dep); !healthy {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement %s", dep.GetName(), dep.Namespace, msg)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return dep, true
|
||||
}
|
||||
|
||||
func (c *Controller) checkDeploymentMetrics(r *flaggerv1.CanaryDeployment) bool {
|
||||
for _, metric := range r.Spec.CanaryAnalysis.Metrics {
|
||||
if metric.Name == "istio_requests_total" {
|
||||
val, err := c.getDeploymentCounter(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.metricsServer, err)
|
||||
return false
|
||||
}
|
||||
if float64(metric.Threshold) > val {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement success rate %.2f%% < %v%%",
|
||||
r.Name, r.Namespace, val, metric.Threshold)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if metric.Name == "istio_request_duration_seconds_bucket" {
|
||||
val, err := c.GetDeploymentHistogram(r.Spec.TargetRef.Name, r.Namespace, metric.Name, metric.Interval)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Metrics server %s query failed: %v", c.metricsServer, err)
|
||||
return false
|
||||
}
|
||||
t := time.Duration(metric.Threshold) * time.Millisecond
|
||||
if val > t {
|
||||
c.recordEventWarningf(r, "Halt %s.%s advancement request duration %v > %v",
|
||||
r.Name, r.Namespace, val, t)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) scaleToZeroCanary(r *flaggerv1.CanaryDeployment) {
|
||||
canary, err := c.kubeClient.AppsV1().Deployments(r.Namespace).Get(r.Spec.TargetRef.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Deployment %s.%s not found", r.Spec.TargetRef.Name, r.Namespace)
|
||||
return
|
||||
}
|
||||
//HPA https://github.com/kubernetes/kubernetes/pull/29212
|
||||
canary.Spec.Replicas = int32p(0)
|
||||
canary, err = c.kubeClient.AppsV1().Deployments(canary.Namespace).Update(canary)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "Scaling down %s.%s failed: %v", canary.GetName(), canary.Namespace, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) setCanaryRevision(r *flaggerv1.CanaryDeployment, canary *appsv1.Deployment, status string) {
|
||||
r.Status = flaggerv1.CanaryDeploymentStatus{
|
||||
State: status,
|
||||
FailedChecks: r.Status.FailedChecks,
|
||||
}
|
||||
err := c.saveDeploymentSpec(r, canary)
|
||||
if err != nil {
|
||||
c.logger.Errorf("CanaryDeployment %s.%s status update failed: %v", r.Name, r.Namespace, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getVirtualService(r *flaggerv1.CanaryDeployment) (
|
||||
vs *istiov1alpha3.VirtualService,
|
||||
primary istiov1alpha3.DestinationWeight,
|
||||
canary istiov1alpha3.DestinationWeight,
|
||||
ok bool,
|
||||
) {
|
||||
var err error
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Get(r.Name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s not found", r.Name, r.Namespace)
|
||||
return
|
||||
}
|
||||
|
||||
for _, http := range vs.Spec.Http {
|
||||
for _, route := range http.Route {
|
||||
if route.Destination.Host == fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name) {
|
||||
primary = route
|
||||
}
|
||||
if route.Destination.Host == r.Spec.TargetRef.Name {
|
||||
canary = route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if primary.Weight == 0 && canary.Weight == 0 {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s does not contain routes for %s and %s",
|
||||
r.Name, r.Namespace, fmt.Sprintf("%s-primary", r.Spec.TargetRef.Name), r.Spec.TargetRef.Name)
|
||||
return
|
||||
}
|
||||
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Controller) updateVirtualServiceRoutes(
|
||||
r *flaggerv1.CanaryDeployment,
|
||||
vs *istiov1alpha3.VirtualService,
|
||||
primary istiov1alpha3.DestinationWeight,
|
||||
canary istiov1alpha3.DestinationWeight,
|
||||
) bool {
|
||||
vs.Spec.Http = []istiov1alpha3.HTTPRoute{
|
||||
{
|
||||
Route: []istiov1alpha3.DestinationWeight{primary, canary},
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
vs, err = c.istioClient.NetworkingV1alpha3().VirtualServices(r.Namespace).Update(vs)
|
||||
if err != nil {
|
||||
c.recordEventErrorf(r, "VirtualService %s.%s update failed: %v", r.Name, r.Namespace, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getDeploymentStatus(deployment *appsv1.Deployment) (string, bool) {
|
||||
if deployment.Generation <= deployment.Status.ObservedGeneration {
|
||||
cond := getDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)
|
||||
if cond != nil && cond.Reason == "ProgressDeadlineExceeded" {
|
||||
return fmt.Sprintf("deployment %q exceeded its progress deadline", deployment.GetName()), false
|
||||
} else if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d out of %d new replicas have been updated",
|
||||
deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false
|
||||
} else if deployment.Status.Replicas > deployment.Status.UpdatedReplicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d old replicas are pending termination",
|
||||
deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false
|
||||
} else if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas {
|
||||
return fmt.Sprintf("waiting for rollout to finish: %d of %d updated replicas are available",
|
||||
deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false
|
||||
}
|
||||
} else {
|
||||
return "waiting for rollout to finish: observed deployment generation less then desired generation", false
|
||||
}
|
||||
|
||||
return "ready", true
|
||||
}
|
||||
|
||||
func getDeploymentCondition(
|
||||
status appsv1.DeploymentStatus,
|
||||
conditionType appsv1.DeploymentConditionType,
|
||||
) *appsv1.DeploymentCondition {
|
||||
for i := range status.Conditions {
|
||||
c := status.Conditions[i]
|
||||
if c.Type == conditionType {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func int32p(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type VectorQueryResponse struct {
|
||||
Data struct {
|
||||
Result []struct {
|
||||
Metric struct {
|
||||
Code string `json:"response_code"`
|
||||
Name string `json:"destination_workload"`
|
||||
}
|
||||
Value []interface{} `json:"value"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) queryMetric(query string) (*VectorQueryResponse, error) {
|
||||
promURL, err := url.Parse(c.metricsServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, err := url.Parse(fmt.Sprintf("./api/v1/query?query=%s", query))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u = promURL.ResolveReference(u)
|
||||
|
||||
req, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
r, err := http.DefaultClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading body: %s", err.Error())
|
||||
}
|
||||
|
||||
if 400 <= r.StatusCode {
|
||||
return nil, fmt.Errorf("error response: %s", string(b))
|
||||
}
|
||||
|
||||
var values VectorQueryResponse
|
||||
err = json.Unmarshal(b, &values)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling result: %s, '%s'", err.Error(), string(b))
|
||||
}
|
||||
|
||||
return &values, nil
|
||||
}
|
||||
|
||||
// istio_requests_total
|
||||
func (c *Controller) getDeploymentCounter(name string, namespace string, metric string, interval string) (float64, error) {
|
||||
var rate *float64
|
||||
querySt := url.QueryEscape(`sum(rate(` +
|
||||
metric + `{reporter="destination",destination_workload_namespace=~"` +
|
||||
namespace + `",destination_workload=~"` +
|
||||
name + `",response_code!~"5.*"}[1m])) / sum(rate(` +
|
||||
metric + `{reporter="destination",destination_workload_namespace=~"` +
|
||||
namespace + `",destination_workload=~"` +
|
||||
name + `"}[` +
|
||||
interval + `])) * 100 `)
|
||||
result, err := c.queryMetric(querySt)
|
||||
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
|
||||
}
|
||||
rate = &f
|
||||
}
|
||||
}
|
||||
if rate == nil {
|
||||
return 0, fmt.Errorf("no values found for metric %s", metric)
|
||||
}
|
||||
return *rate, nil
|
||||
}
|
||||
|
||||
// istio_request_duration_seconds_bucket
|
||||
func (c *Controller) GetDeploymentHistogram(name string, namespace string, metric string, interval string) (time.Duration, error) {
|
||||
var rate *float64
|
||||
querySt := url.QueryEscape(`histogram_quantile(0.99, sum(rate(` +
|
||||
metric + `{reporter="destination",destination_workload=~"` +
|
||||
name + `", destination_workload_namespace=~"` +
|
||||
namespace + `"}[` +
|
||||
interval + `])) by (le))`)
|
||||
result, err := c.queryMetric(querySt)
|
||||
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
|
||||
}
|
||||
rate = &f
|
||||
}
|
||||
}
|
||||
if rate == nil {
|
||||
return 0, fmt.Errorf("no values found for metric %s", metric)
|
||||
}
|
||||
ms := time.Duration(int64(*rate*1000)) * time.Millisecond
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func CheckMetricsServer(address string) (bool, error) {
|
||||
promURL, err := url.Parse(address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
u, err := url.Parse("./api/v1/status/flags")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
u = promURL.ResolveReference(u)
|
||||
|
||||
req, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
r, err := http.DefaultClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error reading body: %s", err.Error())
|
||||
}
|
||||
|
||||
if 400 <= r.StatusCode {
|
||||
return false, fmt.Errorf("error response: %s", string(b))
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
istioclientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
flaggerv1 "github.com/stefanprodan/flagger/pkg/apis/flagger/v1beta1"
|
||||
clientset "github.com/stefanprodan/flagger/pkg/client/clientset/versioned"
|
||||
flaggerscheme "github.com/stefanprodan/flagger/pkg/client/clientset/versioned/scheme"
|
||||
flaggerinformers "github.com/stefanprodan/flagger/pkg/client/informers/externalversions/flagger/v1beta1"
|
||||
flaggerlisters "github.com/stefanprodan/flagger/pkg/client/listers/flagger/v1beta1"
|
||||
"go.uber.org/zap"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
|
||||
const controllerAgentName = "flagger"
|
||||
|
||||
type Controller struct {
|
||||
kubeClient kubernetes.Interface
|
||||
istioClient istioclientset.Interface
|
||||
rolloutClient clientset.Interface
|
||||
rolloutLister flaggerlisters.CanaryDeploymentLister
|
||||
rolloutSynced cache.InformerSynced
|
||||
rolloutWindow time.Duration
|
||||
workqueue workqueue.RateLimitingInterface
|
||||
recorder record.EventRecorder
|
||||
logger *zap.SugaredLogger
|
||||
metricsServer string
|
||||
rollouts *sync.Map
|
||||
}
|
||||
|
||||
func NewController(
|
||||
kubeClient kubernetes.Interface,
|
||||
istioClient istioclientset.Interface,
|
||||
rolloutClient clientset.Interface,
|
||||
rolloutInformer flaggerinformers.CanaryDeploymentInformer,
|
||||
rolloutWindow time.Duration,
|
||||
metricServer string,
|
||||
logger *zap.SugaredLogger,
|
||||
|
||||
) *Controller {
|
||||
logger.Debug("Creating event broadcaster")
|
||||
flaggerscheme.AddToScheme(scheme.Scheme)
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Debugf)
|
||||
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{
|
||||
Interface: kubeClient.CoreV1().Events(""),
|
||||
})
|
||||
recorder := eventBroadcaster.NewRecorder(
|
||||
scheme.Scheme, corev1.EventSource{Component: controllerAgentName})
|
||||
|
||||
ctrl := &Controller{
|
||||
kubeClient: kubeClient,
|
||||
istioClient: istioClient,
|
||||
rolloutClient: rolloutClient,
|
||||
rolloutLister: rolloutInformer.Lister(),
|
||||
rolloutSynced: rolloutInformer.Informer().HasSynced,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), controllerAgentName),
|
||||
recorder: recorder,
|
||||
logger: logger,
|
||||
rollouts: new(sync.Map),
|
||||
metricsServer: metricServer,
|
||||
rolloutWindow: rolloutWindow,
|
||||
}
|
||||
|
||||
rolloutInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: ctrl.enqueue,
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
oldRoll, ok := checkCustomResourceType(old, logger)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
newRoll, ok := checkCustomResourceType(new, logger)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(newRoll.Spec, oldRoll.Spec); diff != "" {
|
||||
ctrl.logger.Debugf("Diff detected %s.%s %s", oldRoll.Name, oldRoll.Namespace, diff)
|
||||
ctrl.enqueue(new)
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(old interface{}) {
|
||||
r, ok := checkCustomResourceType(old, logger)
|
||||
if ok {
|
||||
ctrl.logger.Infof("Deleting %s.%s from cache", r.Name, r.Namespace)
|
||||
ctrl.rollouts.Delete(fmt.Sprintf("%s.%s", r.Name, r.Namespace))
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
return ctrl
|
||||
}
|
||||
|
||||
func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
|
||||
c.logger.Info("Starting operator")
|
||||
|
||||
for i := 0; i < threadiness; i++ {
|
||||
go wait.Until(func() {
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
}, time.Second, stopCh)
|
||||
}
|
||||
|
||||
c.logger.Info("Started operator workers")
|
||||
|
||||
tickChan := time.NewTicker(c.rolloutWindow).C
|
||||
for {
|
||||
select {
|
||||
case <-tickChan:
|
||||
c.doRollouts()
|
||||
case <-stopCh:
|
||||
c.logger.Info("Shutting down operator workers")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) processNextWorkItem() bool {
|
||||
obj, shutdown := c.workqueue.Get()
|
||||
|
||||
if shutdown {
|
||||
return false
|
||||
}
|
||||
|
||||
err := func(obj interface{}) error {
|
||||
defer c.workqueue.Done(obj)
|
||||
var key string
|
||||
var ok bool
|
||||
if key, ok = obj.(string); !ok {
|
||||
c.workqueue.Forget(obj)
|
||||
utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj))
|
||||
return nil
|
||||
}
|
||||
// Run the syncHandler, passing it the namespace/name string of the
|
||||
// Foo resource to be synced.
|
||||
if err := c.syncHandler(key); err != nil {
|
||||
return fmt.Errorf("error syncing '%s': %s", key, err.Error())
|
||||
}
|
||||
// Finally, if no error occurs we Forget this item so it does not
|
||||
// get queued again until another change happens.
|
||||
c.workqueue.Forget(obj)
|
||||
return nil
|
||||
}(obj)
|
||||
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Controller) syncHandler(key string) error {
|
||||
namespace, name, err := cache.SplitMetaNamespaceKey(key)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
|
||||
return nil
|
||||
}
|
||||
cd, err := c.rolloutLister.CanaryDeployments(namespace).Get(name)
|
||||
if errors.IsNotFound(err) {
|
||||
utilruntime.HandleError(fmt.Errorf("'%s' in work queue no longer exists", key))
|
||||
return nil
|
||||
}
|
||||
|
||||
c.rollouts.Store(fmt.Sprintf("%s.%s", cd.Name, cd.Namespace), cd)
|
||||
|
||||
err = c.bootstrapDeployment(cd)
|
||||
if err != nil {
|
||||
c.logger.Warnf("%s.%s bootstrap error %v", cd.Name, cd.Namespace, err)
|
||||
return err
|
||||
}
|
||||
|
||||
c.logger.Infof("Synced %s", key)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) enqueue(obj interface{}) {
|
||||
var key string
|
||||
var err error
|
||||
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
return
|
||||
}
|
||||
c.workqueue.AddRateLimited(key)
|
||||
}
|
||||
|
||||
func checkCustomResourceType(obj interface{}, logger *zap.SugaredLogger) (flaggerv1.CanaryDeployment, bool) {
|
||||
var roll *flaggerv1.CanaryDeployment
|
||||
var ok bool
|
||||
if roll, ok = obj.(*flaggerv1.CanaryDeployment); !ok {
|
||||
logger.Errorf("Event Watch received an invalid object: %#v", obj)
|
||||
return flaggerv1.CanaryDeployment{}, false
|
||||
}
|
||||
return *roll, true
|
||||
}
|
||||
|
||||
func (c *Controller) recordEventInfof(r *flaggerv1.CanaryDeployment, template string, args ...interface{}) {
|
||||
c.logger.Infof(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeNormal, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func (c *Controller) recordEventErrorf(r *flaggerv1.CanaryDeployment, template string, args ...interface{}) {
|
||||
c.logger.Errorf(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
|
||||
func (c *Controller) recordEventWarningf(r *flaggerv1.CanaryDeployment, template string, args ...interface{}) {
|
||||
c.logger.Infof(template, args...)
|
||||
c.recorder.Event(r, corev1.EventTypeWarning, "Synced", fmt.Sprintf(template, args...))
|
||||
}
|
||||
Reference in New Issue
Block a user