Merge pull request #440 from weaveworks/smi-v1alpha2-client

SMI TrafficSplit v1alpha2 client
This commit is contained in:
Stefan Prodan
2020-02-14 11:20:03 +02:00
committed by GitHub
31 changed files with 1388 additions and 94 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ chmod +x ${CODEGEN_PKG}/generate-groups.sh
${CODEGEN_PKG}/generate-groups.sh all \
github.com/weaveworks/flagger/pkg/client github.com/weaveworks/flagger/pkg/apis \
"flagger:v1beta1 appmesh:v1beta1 istio:v1alpha3 smi:v1alpha1 gloo:v1 projectcontour:v1" \
"flagger:v1beta1 appmesh:v1beta1 istio:v1alpha3 smi:v1alpha1 smi:v1alpha2 gloo:v1 projectcontour:v1" \
--output-base "${TEMP_DIR}" \
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
+4
View File
@@ -0,0 +1,4 @@
// +k8s:deepcopy-gen=package
// +groupName=split.smi-spec.io
package v1alpha2
+48
View File
@@ -0,0 +1,48 @@
package v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
ts "github.com/weaveworks/flagger/pkg/apis/smi"
)
// SchemeGroupVersion is the identifier for the API which includes
// the name of the group and the version of the API
var SchemeGroupVersion = schema.GroupVersion{
Group: ts.GroupName,
Version: "v1alpha2",
}
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// SchemeBuilder collects functions that add things to a scheme. It's to allow
// code to compile without explicitly referencing generated types. You should
// declare one in each package that will have generated deep copy or conversion
// functions.
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme applies all the stored functions to the scheme. A non-nil error
// indicates that one function failed and the attempt was abandoned.
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&TrafficSplit{},
&TrafficSplitList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
+55
View File
@@ -0,0 +1,55 @@
package v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:noStatus
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// TrafficSplit allows users to incrementally direct percentages of traffic
// between various services. It will be used by clients such as ingress
// controllers or service mesh sidecars to split the outgoing traffic to
// different destinations.
type TrafficSplit struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the desired behavior of the traffic split.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
Spec TrafficSplitSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Most recently observed status of the pod.
// This data may not be up to date.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
//Status Status `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// TrafficSplitSpec is the specification for a TrafficSplit
type TrafficSplitSpec struct {
Service string `json:"service,omitempty"`
Backends []TrafficSplitBackend `json:"backends,omitempty"`
}
// TrafficSplitBackend defines a backend
type TrafficSplitBackend struct {
Service string `json:"service,omitempty"`
Weight int `json:"weight,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TrafficSplitList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []TrafficSplit `json:"items"`
}
@@ -0,0 +1,122 @@
// +build !ignore_autogenerated
/*
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha2
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TrafficSplit) DeepCopyInto(out *TrafficSplit) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficSplit.
func (in *TrafficSplit) DeepCopy() *TrafficSplit {
if in == nil {
return nil
}
out := new(TrafficSplit)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TrafficSplit) 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 *TrafficSplitBackend) DeepCopyInto(out *TrafficSplitBackend) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficSplitBackend.
func (in *TrafficSplitBackend) DeepCopy() *TrafficSplitBackend {
if in == nil {
return nil
}
out := new(TrafficSplitBackend)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TrafficSplitList) DeepCopyInto(out *TrafficSplitList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]TrafficSplit, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficSplitList.
func (in *TrafficSplitList) DeepCopy() *TrafficSplitList {
if in == nil {
return nil
}
out := new(TrafficSplitList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TrafficSplitList) 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 *TrafficSplitSpec) DeepCopyInto(out *TrafficSplitSpec) {
*out = *in
if in.Backends != nil {
in, out := &in.Backends, &out.Backends
*out = make([]TrafficSplitBackend, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficSplitSpec.
func (in *TrafficSplitSpec) DeepCopy() *TrafficSplitSpec {
if in == nil {
return nil
}
out := new(TrafficSplitSpec)
in.DeepCopyInto(out)
return out
}
@@ -27,6 +27,7 @@ import (
networkingv1alpha3 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
projectcontourv1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/projectcontour/v1"
splitv1alpha1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha1"
splitv1alpha2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha2"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol"
@@ -40,6 +41,7 @@ type Interface interface {
NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface
ProjectcontourV1() projectcontourv1.ProjectcontourV1Interface
SplitV1alpha1() splitv1alpha1.SplitV1alpha1Interface
SplitV1alpha2() splitv1alpha2.SplitV1alpha2Interface
}
// Clientset contains the clients for groups. Each group has exactly one
@@ -52,6 +54,7 @@ type Clientset struct {
networkingV1alpha3 *networkingv1alpha3.NetworkingV1alpha3Client
projectcontourV1 *projectcontourv1.ProjectcontourV1Client
splitV1alpha1 *splitv1alpha1.SplitV1alpha1Client
splitV1alpha2 *splitv1alpha2.SplitV1alpha2Client
}
// AppmeshV1beta1 retrieves the AppmeshV1beta1Client
@@ -84,6 +87,11 @@ func (c *Clientset) SplitV1alpha1() splitv1alpha1.SplitV1alpha1Interface {
return c.splitV1alpha1
}
// SplitV1alpha2 retrieves the SplitV1alpha2Client
func (c *Clientset) SplitV1alpha2() splitv1alpha2.SplitV1alpha2Interface {
return c.splitV1alpha2
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
@@ -129,6 +137,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.splitV1alpha2, err = splitv1alpha2.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
@@ -147,6 +159,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
cs.networkingV1alpha3 = networkingv1alpha3.NewForConfigOrDie(c)
cs.projectcontourV1 = projectcontourv1.NewForConfigOrDie(c)
cs.splitV1alpha1 = splitv1alpha1.NewForConfigOrDie(c)
cs.splitV1alpha2 = splitv1alpha2.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs
@@ -161,6 +174,7 @@ func New(c rest.Interface) *Clientset {
cs.networkingV1alpha3 = networkingv1alpha3.New(c)
cs.projectcontourV1 = projectcontourv1.New(c)
cs.splitV1alpha1 = splitv1alpha1.New(c)
cs.splitV1alpha2 = splitv1alpha2.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs
@@ -32,6 +32,8 @@ import (
fakeprojectcontourv1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/projectcontour/v1/fake"
splitv1alpha1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha1"
fakesplitv1alpha1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha1/fake"
splitv1alpha2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha2"
fakesplitv1alpha2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha2/fake"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
@@ -115,3 +117,8 @@ func (c *Clientset) ProjectcontourV1() projectcontourv1.ProjectcontourV1Interfac
func (c *Clientset) SplitV1alpha1() splitv1alpha1.SplitV1alpha1Interface {
return &fakesplitv1alpha1.FakeSplitV1alpha1{Fake: &c.Fake}
}
// SplitV1alpha2 retrieves the SplitV1alpha2Client
func (c *Clientset) SplitV1alpha2() splitv1alpha2.SplitV1alpha2Interface {
return &fakesplitv1alpha2.FakeSplitV1alpha2{Fake: &c.Fake}
}
@@ -25,6 +25,7 @@ import (
networkingv1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
projectcontourv1 "github.com/weaveworks/flagger/pkg/apis/projectcontour/v1"
splitv1alpha1 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha1"
splitv1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -42,6 +43,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
networkingv1alpha3.AddToScheme,
projectcontourv1.AddToScheme,
splitv1alpha1.AddToScheme,
splitv1alpha2.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
@@ -25,6 +25,7 @@ import (
networkingv1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
projectcontourv1 "github.com/weaveworks/flagger/pkg/apis/projectcontour/v1"
splitv1alpha1 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha1"
splitv1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -42,6 +43,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
networkingv1alpha3.AddToScheme,
projectcontourv1.AddToScheme,
splitv1alpha1.AddToScheme,
splitv1alpha2.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
@@ -0,0 +1,20 @@
/*
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.
// This package has the automatically generated typed clients.
package v1alpha2
@@ -0,0 +1,20 @@
/*
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 has the automatically generated clients.
package fake
@@ -0,0 +1,40 @@
/*
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 (
v1alpha2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/smi/v1alpha2"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeSplitV1alpha2 struct {
*testing.Fake
}
func (c *FakeSplitV1alpha2) TrafficSplits(namespace string) v1alpha2.TrafficSplitInterface {
return &FakeTrafficSplits{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeSplitV1alpha2) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}
@@ -0,0 +1,128 @@
/*
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 (
v1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
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"
)
// FakeTrafficSplits implements TrafficSplitInterface
type FakeTrafficSplits struct {
Fake *FakeSplitV1alpha2
ns string
}
var trafficsplitsResource = schema.GroupVersionResource{Group: "split.smi-spec.io", Version: "v1alpha2", Resource: "trafficsplits"}
var trafficsplitsKind = schema.GroupVersionKind{Group: "split.smi-spec.io", Version: "v1alpha2", Kind: "TrafficSplit"}
// Get takes name of the trafficSplit, and returns the corresponding trafficSplit object, and an error if there is any.
func (c *FakeTrafficSplits) Get(name string, options v1.GetOptions) (result *v1alpha2.TrafficSplit, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(trafficsplitsResource, c.ns, name), &v1alpha2.TrafficSplit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.TrafficSplit), err
}
// List takes label and field selectors, and returns the list of TrafficSplits that match those selectors.
func (c *FakeTrafficSplits) List(opts v1.ListOptions) (result *v1alpha2.TrafficSplitList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(trafficsplitsResource, trafficsplitsKind, c.ns, opts), &v1alpha2.TrafficSplitList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha2.TrafficSplitList{ListMeta: obj.(*v1alpha2.TrafficSplitList).ListMeta}
for _, item := range obj.(*v1alpha2.TrafficSplitList).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 trafficSplits.
func (c *FakeTrafficSplits) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(trafficsplitsResource, c.ns, opts))
}
// Create takes the representation of a trafficSplit and creates it. Returns the server's representation of the trafficSplit, and an error, if there is any.
func (c *FakeTrafficSplits) Create(trafficSplit *v1alpha2.TrafficSplit) (result *v1alpha2.TrafficSplit, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(trafficsplitsResource, c.ns, trafficSplit), &v1alpha2.TrafficSplit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.TrafficSplit), err
}
// Update takes the representation of a trafficSplit and updates it. Returns the server's representation of the trafficSplit, and an error, if there is any.
func (c *FakeTrafficSplits) Update(trafficSplit *v1alpha2.TrafficSplit) (result *v1alpha2.TrafficSplit, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(trafficsplitsResource, c.ns, trafficSplit), &v1alpha2.TrafficSplit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.TrafficSplit), err
}
// Delete takes name of the trafficSplit and deletes it. Returns an error if one occurs.
func (c *FakeTrafficSplits) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(trafficsplitsResource, c.ns, name), &v1alpha2.TrafficSplit{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeTrafficSplits) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(trafficsplitsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha2.TrafficSplitList{})
return err
}
// Patch applies the patch and returns the patched trafficSplit.
func (c *FakeTrafficSplits) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.TrafficSplit, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(trafficsplitsResource, c.ns, name, pt, data, subresources...), &v1alpha2.TrafficSplit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.TrafficSplit), err
}
@@ -0,0 +1,21 @@
/*
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 v1alpha2
type TrafficSplitExpansion interface{}
@@ -0,0 +1,89 @@
/*
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha2
import (
v1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
"github.com/weaveworks/flagger/pkg/client/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type SplitV1alpha2Interface interface {
RESTClient() rest.Interface
TrafficSplitsGetter
}
// SplitV1alpha2Client is used to interact with features provided by the split.smi-spec.io group.
type SplitV1alpha2Client struct {
restClient rest.Interface
}
func (c *SplitV1alpha2Client) TrafficSplits(namespace string) TrafficSplitInterface {
return newTrafficSplits(c, namespace)
}
// NewForConfig creates a new SplitV1alpha2Client for the given config.
func NewForConfig(c *rest.Config) (*SplitV1alpha2Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &SplitV1alpha2Client{client}, nil
}
// NewForConfigOrDie creates a new SplitV1alpha2Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *SplitV1alpha2Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new SplitV1alpha2Client for the given RESTClient.
func New(c rest.Interface) *SplitV1alpha2Client {
return &SplitV1alpha2Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1alpha2.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *SplitV1alpha2Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}
@@ -0,0 +1,174 @@
/*
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 v1alpha2
import (
"time"
v1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
scheme "github.com/weaveworks/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"
)
// TrafficSplitsGetter has a method to return a TrafficSplitInterface.
// A group's client should implement this interface.
type TrafficSplitsGetter interface {
TrafficSplits(namespace string) TrafficSplitInterface
}
// TrafficSplitInterface has methods to work with TrafficSplit resources.
type TrafficSplitInterface interface {
Create(*v1alpha2.TrafficSplit) (*v1alpha2.TrafficSplit, error)
Update(*v1alpha2.TrafficSplit) (*v1alpha2.TrafficSplit, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha2.TrafficSplit, error)
List(opts v1.ListOptions) (*v1alpha2.TrafficSplitList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.TrafficSplit, err error)
TrafficSplitExpansion
}
// trafficSplits implements TrafficSplitInterface
type trafficSplits struct {
client rest.Interface
ns string
}
// newTrafficSplits returns a TrafficSplits
func newTrafficSplits(c *SplitV1alpha2Client, namespace string) *trafficSplits {
return &trafficSplits{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the trafficSplit, and returns the corresponding trafficSplit object, and an error if there is any.
func (c *trafficSplits) Get(name string, options v1.GetOptions) (result *v1alpha2.TrafficSplit, err error) {
result = &v1alpha2.TrafficSplit{}
err = c.client.Get().
Namespace(c.ns).
Resource("trafficsplits").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of TrafficSplits that match those selectors.
func (c *trafficSplits) List(opts v1.ListOptions) (result *v1alpha2.TrafficSplitList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha2.TrafficSplitList{}
err = c.client.Get().
Namespace(c.ns).
Resource("trafficsplits").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested trafficSplits.
func (c *trafficSplits) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("trafficsplits").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a trafficSplit and creates it. Returns the server's representation of the trafficSplit, and an error, if there is any.
func (c *trafficSplits) Create(trafficSplit *v1alpha2.TrafficSplit) (result *v1alpha2.TrafficSplit, err error) {
result = &v1alpha2.TrafficSplit{}
err = c.client.Post().
Namespace(c.ns).
Resource("trafficsplits").
Body(trafficSplit).
Do().
Into(result)
return
}
// Update takes the representation of a trafficSplit and updates it. Returns the server's representation of the trafficSplit, and an error, if there is any.
func (c *trafficSplits) Update(trafficSplit *v1alpha2.TrafficSplit) (result *v1alpha2.TrafficSplit, err error) {
result = &v1alpha2.TrafficSplit{}
err = c.client.Put().
Namespace(c.ns).
Resource("trafficsplits").
Name(trafficSplit.Name).
Body(trafficSplit).
Do().
Into(result)
return
}
// Delete takes name of the trafficSplit and deletes it. Returns an error if one occurs.
func (c *trafficSplits) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("trafficsplits").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *trafficSplits) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("trafficsplits").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched trafficSplit.
func (c *trafficSplits) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.TrafficSplit, err error) {
result = &v1alpha2.TrafficSplit{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("trafficsplits").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
@@ -27,6 +27,7 @@ import (
v1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
projectcontourv1 "github.com/weaveworks/flagger/pkg/apis/projectcontour/v1"
v1alpha1 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha1"
v1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
@@ -91,6 +92,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case v1alpha1.SchemeGroupVersion.WithResource("trafficsplits"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Split().V1alpha1().TrafficSplits().Informer()}, nil
// Group=split.smi-spec.io, Version=v1alpha2
case v1alpha2.SchemeGroupVersion.WithResource("trafficsplits"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Split().V1alpha2().TrafficSplits().Informer()}, nil
}
return nil, fmt.Errorf("no informer found for %v", resource)
@@ -21,12 +21,15 @@ package smi
import (
internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha1 "github.com/weaveworks/flagger/pkg/client/informers/externalversions/smi/v1alpha1"
v1alpha2 "github.com/weaveworks/flagger/pkg/client/informers/externalversions/smi/v1alpha2"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha1 provides access to shared informers for resources in V1alpha1.
V1alpha1() v1alpha1.Interface
// V1alpha2 provides access to shared informers for resources in V1alpha2.
V1alpha2() v1alpha2.Interface
}
type group struct {
@@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
func (g *group) V1alpha1() v1alpha1.Interface {
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1alpha2 returns a new v1alpha2.Interface.
func (g *group) V1alpha2() v1alpha2.Interface {
return v1alpha2.New(g.factory, g.namespace, g.tweakListOptions)
}
@@ -0,0 +1,45 @@
/*
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha2
import (
internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// TrafficSplits returns a TrafficSplitInformer.
TrafficSplits() TrafficSplitInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// TrafficSplits returns a TrafficSplitInformer.
func (v *version) TrafficSplits() TrafficSplitInformer {
return &trafficSplitInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
@@ -0,0 +1,89 @@
/*
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha2
import (
time "time"
smiv1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
versioned "github.com/weaveworks/flagger/pkg/client/clientset/versioned"
internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha2 "github.com/weaveworks/flagger/pkg/client/listers/smi/v1alpha2"
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"
)
// TrafficSplitInformer provides access to a shared informer and lister for
// TrafficSplits.
type TrafficSplitInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha2.TrafficSplitLister
}
type trafficSplitInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewTrafficSplitInformer constructs a new informer for TrafficSplit 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 NewTrafficSplitInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredTrafficSplitInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredTrafficSplitInformer constructs a new informer for TrafficSplit 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 NewFilteredTrafficSplitInformer(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.SplitV1alpha2().TrafficSplits(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.SplitV1alpha2().TrafficSplits(namespace).Watch(options)
},
},
&smiv1alpha2.TrafficSplit{},
resyncPeriod,
indexers,
)
}
func (f *trafficSplitInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredTrafficSplitInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *trafficSplitInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&smiv1alpha2.TrafficSplit{}, f.defaultInformer)
}
func (f *trafficSplitInformer) Lister() v1alpha2.TrafficSplitLister {
return v1alpha2.NewTrafficSplitLister(f.Informer().GetIndexer())
}
@@ -0,0 +1,27 @@
/*
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 v1alpha2
// TrafficSplitListerExpansion allows custom methods to be added to
// TrafficSplitLister.
type TrafficSplitListerExpansion interface{}
// TrafficSplitNamespaceListerExpansion allows custom methods to be added to
// TrafficSplitNamespaceLister.
type TrafficSplitNamespaceListerExpansion interface{}
@@ -0,0 +1,94 @@
/*
Copyright The Flagger Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha2
import (
v1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// TrafficSplitLister helps list TrafficSplits.
type TrafficSplitLister interface {
// List lists all TrafficSplits in the indexer.
List(selector labels.Selector) (ret []*v1alpha2.TrafficSplit, err error)
// TrafficSplits returns an object that can list and get TrafficSplits.
TrafficSplits(namespace string) TrafficSplitNamespaceLister
TrafficSplitListerExpansion
}
// trafficSplitLister implements the TrafficSplitLister interface.
type trafficSplitLister struct {
indexer cache.Indexer
}
// NewTrafficSplitLister returns a new TrafficSplitLister.
func NewTrafficSplitLister(indexer cache.Indexer) TrafficSplitLister {
return &trafficSplitLister{indexer: indexer}
}
// List lists all TrafficSplits in the indexer.
func (s *trafficSplitLister) List(selector labels.Selector) (ret []*v1alpha2.TrafficSplit, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.TrafficSplit))
})
return ret, err
}
// TrafficSplits returns an object that can list and get TrafficSplits.
func (s *trafficSplitLister) TrafficSplits(namespace string) TrafficSplitNamespaceLister {
return trafficSplitNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// TrafficSplitNamespaceLister helps list and get TrafficSplits.
type TrafficSplitNamespaceLister interface {
// List lists all TrafficSplits in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1alpha2.TrafficSplit, err error)
// Get retrieves the TrafficSplit from the indexer for a given namespace and name.
Get(name string) (*v1alpha2.TrafficSplit, error)
TrafficSplitNamespaceListerExpansion
}
// trafficSplitNamespaceLister implements the TrafficSplitNamespaceLister
// interface.
type trafficSplitNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all TrafficSplits in the indexer for a given namespace.
func (s trafficSplitNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.TrafficSplit, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.TrafficSplit))
})
return ret, err
}
// Get retrieves the TrafficSplit from the indexer for a given namespace and name.
func (s trafficSplitNamespaceLister) Get(name string) (*v1alpha2.TrafficSplit, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha2.Resource("trafficsplit"), name)
}
return obj.(*v1alpha2.TrafficSplit), nil
}
+4 -4
View File
@@ -10,7 +10,7 @@ import (
)
func TestAppmeshRouter_Reconcile(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &AppMeshRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -151,7 +151,7 @@ func TestAppmeshRouter_Reconcile(t *testing.T) {
}
func TestAppmeshRouter_GetSetRoutes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &AppMeshRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -188,7 +188,7 @@ func TestAppmeshRouter_GetSetRoutes(t *testing.T) {
}
func TestAppmeshRouter_ABTest(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &AppMeshRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -230,7 +230,7 @@ func TestAppmeshRouter_ABTest(t *testing.T) {
}
func TestAppmeshRouter_Gateway(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &AppMeshRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
+4 -4
View File
@@ -7,7 +7,7 @@ import (
)
func TestContourRouter_Reconcile(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &ContourRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -92,7 +92,7 @@ func TestContourRouter_Reconcile(t *testing.T) {
cdClone = cd.DeepCopy()
cdClone.Spec.CanaryAnalysis.Iterations = 5
cdClone.Spec.CanaryAnalysis.Match = newMockABTest().Spec.CanaryAnalysis.Match
cdClone.Spec.CanaryAnalysis.Match = newTestABTest().Spec.CanaryAnalysis.Match
canary, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cdClone)
if err != nil {
t.Fatal(err.Error())
@@ -116,7 +116,7 @@ func TestContourRouter_Reconcile(t *testing.T) {
}
func TestContourRouter_Routes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &ContourRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -164,7 +164,7 @@ func TestContourRouter_Routes(t *testing.T) {
// test update to A/B
cdClone := cd.DeepCopy()
cdClone.Spec.CanaryAnalysis.Iterations = 5
cdClone.Spec.CanaryAnalysis.Match = newMockABTest().Spec.CanaryAnalysis.Match
cdClone.Spec.CanaryAnalysis.Match = newTestABTest().Spec.CanaryAnalysis.Match
canary, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cdClone)
if err != nil {
t.Fatal(err.Error())
+3 -3
View File
@@ -10,7 +10,7 @@ import (
)
func TestGlooRouter_Sync(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &GlooRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -43,7 +43,7 @@ func TestGlooRouter_Sync(t *testing.T) {
}
func TestGlooRouter_SetRoutes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &GlooRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -100,7 +100,7 @@ func TestGlooRouter_SetRoutes(t *testing.T) {
}
func TestGlooRouter_GetRoutes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &GlooRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
+2 -2
View File
@@ -8,7 +8,7 @@ import (
)
func TestIngressRouter_Reconcile(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IngressRouter{
logger: mocks.logger,
kubeClient: mocks.kubeClient,
@@ -44,7 +44,7 @@ func TestIngressRouter_Reconcile(t *testing.T) {
}
func TestIngressRouter_GetSetRoutes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IngressRouter{
logger: mocks.logger,
kubeClient: mocks.kubeClient,
+8 -8
View File
@@ -10,7 +10,7 @@ import (
)
func TestIstioRouter_Sync(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -112,7 +112,7 @@ func TestIstioRouter_Sync(t *testing.T) {
}
func TestIstioRouter_SetRoutes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -217,7 +217,7 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
}
func TestIstioRouter_GetRoutes(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -247,7 +247,7 @@ func TestIstioRouter_GetRoutes(t *testing.T) {
t.Errorf("Got mirror %v wanted %v", m, false)
}
mocks.canary = newMockMirror()
mocks.canary = newTestMirror()
err = router.Reconcile(mocks.canary)
if err != nil {
@@ -313,7 +313,7 @@ func TestIstioRouter_GetRoutes(t *testing.T) {
}
func TestIstioRouter_HTTPRequestHeaders(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -342,7 +342,7 @@ func TestIstioRouter_HTTPRequestHeaders(t *testing.T) {
}
func TestIstioRouter_CORS(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -375,7 +375,7 @@ func TestIstioRouter_CORS(t *testing.T) {
}
func TestIstioRouter_ABTest(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
@@ -444,7 +444,7 @@ func TestIstioRouter_ABTest(t *testing.T) {
}
func TestIstioRouter_GatewayPort(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &IstioRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
+3 -3
View File
@@ -7,7 +7,7 @@ import (
)
func TestServiceRouter_Create(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &KubernetesDeploymentRouter{
kubeClient: mocks.kubeClient,
flaggerClient: mocks.flaggerClient,
@@ -52,7 +52,7 @@ func TestServiceRouter_Create(t *testing.T) {
}
func TestServiceRouter_Update(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &KubernetesDeploymentRouter{
kubeClient: mocks.kubeClient,
flaggerClient: mocks.flaggerClient,
@@ -103,7 +103,7 @@ func TestServiceRouter_Update(t *testing.T) {
}
func TestServiceRouter_Undo(t *testing.T) {
mocks := newFixture()
mocks := newFixture(nil)
router := &KubernetesDeploymentRouter{
kubeClient: mocks.kubeClient,
flaggerClient: mocks.flaggerClient,
+132 -64
View File
@@ -29,18 +29,31 @@ type fixture struct {
logger *zap.SugaredLogger
}
func newFixture() fixture {
canary := newMockCanary()
abtest := newMockABTest()
appmeshCanary := newMockCanaryAppMesh()
ingressCanary := newMockCanaryIngress()
flaggerClient := fakeFlagger.NewSimpleClientset(canary, abtest, appmeshCanary, ingressCanary)
func newFixture(c *flaggerv1.Canary) fixture {
canary := newTestCanary()
if c != nil {
canary = c
}
abtest := newTestABTest()
appmeshCanary := newTestCanaryAppMesh()
ingressCanary := newTestCanaryIngress()
kubeClient := fake.NewSimpleClientset(newMockDeployment(), newMockABTestDeployment(), newMockIngress())
flaggerClient := fakeFlagger.NewSimpleClientset(
canary,
abtest,
appmeshCanary,
ingressCanary,
)
kubeClient := fake.NewSimpleClientset(
newTestDeployment(),
newTestABTestDeployment(),
newTestIngress(),
)
meshClient := fakeFlagger.NewSimpleClientset()
logger, _ := logger.NewLogger("debug")
logger, _ := logger.NewLogger("debug")
return fixture{
canary: canary,
abtest: abtest,
@@ -53,53 +66,7 @@ func newFixture() fixture {
}
}
func newMockCanaryAppMesh() *flaggerv1.Canary {
cd := &flaggerv1.Canary{
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "appmesh",
},
Spec: flaggerv1.CanarySpec{
TargetRef: flaggerv1.CrossNamespaceObjectReference{
Name: "podinfo",
APIVersion: "apps/v1",
Kind: "Deployment",
},
Service: flaggerv1.CanaryService{
Port: 9898,
MeshName: "global",
Hosts: []string{"*"},
Backends: []string{"backend.default"},
Timeout: "25",
Retries: &istiov1alpha3.HTTPRetry{
Attempts: 5,
PerTryTimeout: "gateway-error",
RetryOn: "5s",
},
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
Threshold: 10,
StepWeight: 10,
MaxWeight: 50,
Metrics: []flaggerv1.CanaryMetric{
{
Name: "request-success-rate",
Threshold: 99,
Interval: "1m",
},
{
Name: "request-duration",
Threshold: 500,
Interval: "1m",
},
},
},
},
}
return cd
}
func newMockCanary() *flaggerv1.Canary {
func newTestCanary() *flaggerv1.Canary {
cd := &flaggerv1.Canary{
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
@@ -163,13 +130,104 @@ func newMockCanary() *flaggerv1.Canary {
return cd
}
func newMockMirror() *flaggerv1.Canary {
cd := newMockCanary()
func newTestCanaryAppMesh() *flaggerv1.Canary {
cd := &flaggerv1.Canary{
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "appmesh",
},
Spec: flaggerv1.CanarySpec{
TargetRef: flaggerv1.CrossNamespaceObjectReference{
Name: "podinfo",
APIVersion: "apps/v1",
Kind: "Deployment",
},
Service: flaggerv1.CanaryService{
Port: 9898,
MeshName: "global",
Hosts: []string{"*"},
Backends: []string{"backend.default"},
Timeout: "25",
Retries: &istiov1alpha3.HTTPRetry{
Attempts: 5,
PerTryTimeout: "gateway-error",
RetryOn: "5s",
},
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
Threshold: 10,
StepWeight: 10,
MaxWeight: 50,
Metrics: []flaggerv1.CanaryMetric{
{
Name: "request-success-rate",
Threshold: 99,
Interval: "1m",
},
{
Name: "request-duration",
Threshold: 500,
Interval: "1m",
},
},
},
},
}
return cd
}
func newTestSMICanary() *flaggerv1.Canary {
cd := &flaggerv1.Canary{
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "podinfo",
},
Spec: flaggerv1.CanarySpec{
TargetRef: flaggerv1.CrossNamespaceObjectReference{
Name: "podinfo",
APIVersion: "apps/v1",
Kind: "Deployment",
},
Service: flaggerv1.CanaryService{
Name: "podinfo",
Port: 80,
PortName: "http",
TargetPort: intstr.IntOrString{
Type: 0,
IntVal: 9898,
},
PortDiscovery: true,
},
CanaryAnalysis: flaggerv1.CanaryAnalysis{
Threshold: 10,
StepWeight: 10,
MaxWeight: 50,
Metrics: []flaggerv1.CanaryMetric{
{
Name: "request-success-rate",
Threshold: 99,
Interval: "1m",
},
{
Name: "request-duration",
Threshold: 500,
Interval: "1m",
},
},
},
},
}
return cd
}
func newTestMirror() *flaggerv1.Canary {
cd := newTestCanary()
cd.Spec.CanaryAnalysis.Mirror = true
return cd
}
func newMockABTest() *flaggerv1.Canary {
func newTestABTest() *flaggerv1.Canary {
cd := &flaggerv1.Canary{
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
@@ -215,7 +273,7 @@ func newMockABTest() *flaggerv1.Canary {
return cd
}
func newMockDeployment() *appsv1.Deployment {
func newTestDeployment() *appsv1.Deployment {
d := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
@@ -233,15 +291,20 @@ func newMockDeployment() *appsv1.Deployment {
Labels: map[string]string{
"app": "podinfo",
},
Annotations: map[string]string{
"prometheus.io/scrape": "true",
"prometheus.io/port": "9797",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "podinfo",
Image: "quay.io/stefanprodan/podinfo:1.4.0",
Image: "stefanprodan/podinfo:test",
Command: []string{
"./podinfo",
"--port=9898",
"--port-metrics=9797",
},
Ports: []corev1.ContainerPort{
{
@@ -249,6 +312,11 @@ func newMockDeployment() *appsv1.Deployment {
ContainerPort: 9898,
Protocol: corev1.ProtocolTCP,
},
{
Name: "http-prom",
ContainerPort: 9797,
Protocol: corev1.ProtocolTCP,
},
},
},
},
@@ -260,7 +328,7 @@ func newMockDeployment() *appsv1.Deployment {
return d
}
func newMockABTestDeployment() *appsv1.Deployment {
func newTestABTestDeployment() *appsv1.Deployment {
d := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
@@ -283,7 +351,7 @@ func newMockABTestDeployment() *appsv1.Deployment {
Containers: []corev1.Container{
{
Name: "podinfo",
Image: "quay.io/stefanprodan/podinfo:1.4.0",
Image: "quay.io/stefanprodan/podinfo:test",
Command: []string{
"./podinfo",
"--port=9898",
@@ -305,7 +373,7 @@ func newMockABTestDeployment() *appsv1.Deployment {
return d
}
func newMockCanaryIngress() *flaggerv1.Canary {
func newTestCanaryIngress() *flaggerv1.Canary {
cd := &flaggerv1.Canary{
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
@@ -342,7 +410,7 @@ func newMockCanaryIngress() *flaggerv1.Canary {
return cd
}
func newMockIngress() *v1beta1.Ingress {
func newTestIngress() *v1beta1.Ingress {
return &v1beta1.Ingress{
TypeMeta: metav1.TypeMeta{APIVersion: v1beta1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
+50 -5
View File
@@ -14,7 +14,8 @@ import (
"k8s.io/client-go/kubernetes"
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
smiv1 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha1"
smiv1alpha1 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha1"
smiv1alpha2 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha2"
clientset "github.com/weaveworks/flagger/pkg/client/clientset/versioned"
)
@@ -37,9 +38,9 @@ func (sr *SmiRouter) Reconcile(canary *flaggerv1.Canary) error {
host = apexName
}
tsSpec := smiv1.TrafficSplitSpec{
tsSpec := smiv1alpha1.TrafficSplitSpec{
Service: host,
Backends: []smiv1.TrafficSplitBackend{
Backends: []smiv1alpha1.TrafficSplitBackend{
{
Service: canaryName,
Weight: resource.NewQuantity(0, resource.DecimalExponent),
@@ -54,7 +55,7 @@ func (sr *SmiRouter) Reconcile(canary *flaggerv1.Canary) error {
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(apexName, metav1.GetOptions{})
// create traffic split
if errors.IsNotFound(err) {
t := &smiv1.TrafficSplit{
t := &smiv1alpha1.TrafficSplit{
ObjectMeta: metav1.ObjectMeta{
Name: apexName,
Namespace: canary.Namespace,
@@ -157,7 +158,7 @@ func (sr *SmiRouter) SetRoutes(
return fmt.Errorf("TrafficSplit %s.%s query error %v", apexName, canary.Namespace, err)
}
backends := []smiv1.TrafficSplitBackend{
backends := []smiv1alpha1.TrafficSplitBackend{
{
Service: canaryName,
Weight: resource.NewQuantity(int64(canaryWeight), resource.DecimalExponent),
@@ -187,3 +188,47 @@ func (sr *SmiRouter) makeAnnotations(gateways []string) map[string]string {
}
return res
}
// getWithConvert overrides invalid traffic split and sets weight based on the canary status
func (sr *SmiRouter) getWithConvert(canary *flaggerv1.Canary, host string) (*smiv1alpha2.TrafficSplit, error) {
apexName, primaryName, canaryName := canary.GetServiceNames()
ts, err := sr.smiClient.SplitV1alpha2().TrafficSplits(canary.Namespace).Get(apexName, metav1.GetOptions{})
if errors.IsInvalid(err) {
t := &smiv1alpha2.TrafficSplit{
ObjectMeta: metav1.ObjectMeta{
Name: apexName,
Namespace: canary.Namespace,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(canary, schema.GroupVersionKind{
Group: flaggerv1.SchemeGroupVersion.Group,
Version: flaggerv1.SchemeGroupVersion.Version,
Kind: flaggerv1.CanaryKind,
}),
},
Annotations: sr.makeAnnotations(canary.Spec.Service.Gateways),
},
Spec: smiv1alpha2.TrafficSplitSpec{
Service: host,
Backends: []smiv1alpha2.TrafficSplitBackend{
{
Service: canaryName,
Weight: canary.Status.CanaryWeight,
},
{
Service: primaryName,
Weight: 100 - canary.Status.CanaryWeight,
},
},
},
}
_, err := sr.smiClient.SplitV1alpha2().TrafficSplits(canary.Namespace).Update(t)
if err != nil {
return nil, err
}
sr.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("TrafficSplit %s.%s converted", t.GetName(), canary.Namespace)
}
return ts, err
}
+167
View File
@@ -0,0 +1,167 @@
package router
import (
"strconv"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
smiv1 "github.com/weaveworks/flagger/pkg/apis/smi/v1alpha1"
)
func TestSmiRouter_Sync(t *testing.T) {
canary := newTestSMICanary()
mocks := newFixture(canary)
router := &SmiRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
smiClient: mocks.meshClient,
kubeClient: mocks.kubeClient,
}
err := router.Reconcile(canary)
if err != nil {
t.Fatal(err.Error())
}
// test insert
ts, err := router.smiClient.SplitV1alpha1().TrafficSplits("default").Get("podinfo", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
dests := ts.Spec.Backends
if len(dests) != 2 {
t.Errorf("Got backends %v wanted %v", len(dests), 2)
}
apexName, primaryName, canaryName := canary.GetServiceNames()
if ts.Spec.Service != apexName {
t.Errorf("Got service %v wanted %v", ts.Spec.Service, apexName)
}
var pRoute smiv1.TrafficSplitBackend
var cRoute smiv1.TrafficSplitBackend
for _, dest := range ts.Spec.Backends {
if dest.Service == primaryName {
pRoute = dest
}
if dest.Service == canaryName {
cRoute = dest
}
}
if pRoute.Weight.String() != strconv.Itoa(100) {
t.Errorf("%s weight is %v wanted 100", pRoute.Service, pRoute.Weight)
}
if cRoute.Weight.String() != strconv.Itoa(0) {
t.Errorf("%s weight is %v wanted 0", cRoute.Service, cRoute.Weight)
}
// test update
host := "test"
canary.Spec.Service.Name = host
err = router.Reconcile(canary)
if err != nil {
t.Fatal(err.Error())
}
ts, err = router.smiClient.SplitV1alpha1().TrafficSplits("default").Get("test", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
if ts.Spec.Service != host {
t.Errorf("Got service %v wanted %v", ts.Spec.Service, host)
}
}
func TestSmiRouter_SetRoutes(t *testing.T) {
canary := newTestSMICanary()
mocks := newFixture(canary)
router := &SmiRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
smiClient: mocks.meshClient,
kubeClient: mocks.kubeClient,
}
err := router.Reconcile(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
p, c, m, err := router.GetRoutes(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
p = 50
c = 50
m = false
err = router.SetRoutes(mocks.canary, p, c, m)
if err != nil {
t.Fatal(err.Error())
}
ts, err := router.smiClient.SplitV1alpha1().TrafficSplits("default").Get("podinfo", metav1.GetOptions{})
if err != nil {
t.Fatal(err.Error())
}
var pRoute smiv1.TrafficSplitBackend
var cRoute smiv1.TrafficSplitBackend
_, primaryName, canaryName := canary.GetServiceNames()
for _, dest := range ts.Spec.Backends {
if dest.Service == primaryName {
pRoute = dest
}
if dest.Service == canaryName {
cRoute = dest
}
}
if pRoute.Weight.String() != strconv.Itoa(p) {
t.Errorf("Got primary weight %v wanted %v", pRoute.Weight, p)
}
if cRoute.Weight.String() != strconv.Itoa(c) {
t.Errorf("Got canary weight %v wanted %v", cRoute.Weight, c)
}
}
func TestSmiRouter_GetRoutes(t *testing.T) {
mocks := newFixture(nil)
router := &SmiRouter{
logger: mocks.logger,
flaggerClient: mocks.flaggerClient,
smiClient: mocks.meshClient,
kubeClient: mocks.kubeClient,
}
err := router.Reconcile(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
p, c, m, err := router.GetRoutes(mocks.canary)
if err != nil {
t.Fatal(err.Error())
}
if p != 100 {
t.Errorf("Got primary weight %v wanted %v", p, 100)
}
if c != 0 {
t.Errorf("Got canary weight %v wanted %v", c, 0)
}
if m != false {
t.Errorf("Got mirror %v wanted %v", m, false)
}
}