diff --git a/pkg/apis/appmesh/v1beta1/types.go b/pkg/apis/appmesh/v1beta1/types.go index 86189e4d6..65468a1ac 100644 --- a/pkg/apis/appmesh/v1beta1/types.go +++ b/pkg/apis/appmesh/v1beta1/types.go @@ -102,13 +102,18 @@ type VirtualServiceSpec struct { Routes []Route `json:"routes,omitempty"` } +// VirtualRouter is the spec for a VirtualRouter resource type VirtualRouter struct { - Name string `json:"name"` + Name string `json:"name"` + Listeners []Listener `json:"listeners,omitempty"` } type Route struct { - Name string `json:"name"` - Http HttpRoute `json:"http"` + Name string `json:"name"` + // +optional + Http *HttpRoute `json:"http,omitempty"` + // +optional + Tcp *TcpRoute `json:"tcp,omitempty"` } type HttpRoute struct { @@ -124,6 +129,14 @@ type HttpRouteAction struct { WeightedTargets []WeightedTarget `json:"weightedTargets"` } +type TcpRoute struct { + Action TcpRouteAction `json:"action"` +} + +type TcpRouteAction struct { + WeightedTargets []WeightedTarget `json:"weightedTargets"` +} + type WeightedTarget struct { VirtualNodeName string `json:"virtualNodeName"` Weight int64 `json:"weight"` @@ -203,6 +216,8 @@ type VirtualNodeSpec struct { ServiceDiscovery *ServiceDiscovery `json:"serviceDiscovery,omitempty"` // +optional Backends []Backend `json:"backends,omitempty"` + // +optional + Logging *Logging `json:"logging,omitempty"` } type Listener struct { @@ -237,6 +252,21 @@ type VirtualServiceBackend struct { VirtualServiceName string `json:"virtualServiceName"` } +// Logging refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_Logging.html +type Logging struct { + AccessLog *AccessLog `json:"accessLog"` +} + +// AccessLog refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_AccessLog.html +type AccessLog struct { + File *FileAccessLog `json:"file"` +} + +// FileAccessLog refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_FileAccessLog.html +type FileAccessLog struct { + Path string `json:"path"` +} + // VirtualNodeStatus is the status for a VirtualNode resource type VirtualNodeStatus struct { MeshArn *string `json:"meshArn,omitempty"` diff --git a/pkg/apis/appmesh/v1beta1/zz_generated.deepcopy.go b/pkg/apis/appmesh/v1beta1/zz_generated.deepcopy.go index 40d4b3944..012d891cf 100644 --- a/pkg/apis/appmesh/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/appmesh/v1beta1/zz_generated.deepcopy.go @@ -24,6 +24,27 @@ 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 *AccessLog) DeepCopyInto(out *AccessLog) { + *out = *in + if in.File != nil { + in, out := &in.File, &out.File + *out = new(FileAccessLog) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessLog. +func (in *AccessLog) DeepCopy() *AccessLog { + if in == nil { + return nil + } + out := new(AccessLog) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Backend) DeepCopyInto(out *Backend) { *out = *in @@ -73,6 +94,22 @@ func (in *DnsServiceDiscovery) DeepCopy() *DnsServiceDiscovery { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FileAccessLog) DeepCopyInto(out *FileAccessLog) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileAccessLog. +func (in *FileAccessLog) DeepCopy() *FileAccessLog { + if in == nil { + return nil + } + out := new(FileAccessLog) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HttpRoute) DeepCopyInto(out *HttpRoute) { *out = *in @@ -145,6 +182,27 @@ func (in *Listener) DeepCopy() *Listener { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Logging) DeepCopyInto(out *Logging) { + *out = *in + if in.AccessLog != nil { + in, out := &in.AccessLog, &out.AccessLog + *out = new(AccessLog) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Logging. +func (in *Logging) DeepCopy() *Logging { + if in == nil { + return nil + } + out := new(Logging) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Mesh) DeepCopyInto(out *Mesh) { *out = *in @@ -304,7 +362,16 @@ func (in *PortMapping) DeepCopy() *PortMapping { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Route) DeepCopyInto(out *Route) { *out = *in - in.Http.DeepCopyInto(&out.Http) + if in.Http != nil { + in, out := &in.Http, &out.Http + *out = new(HttpRoute) + (*in).DeepCopyInto(*out) + } + if in.Tcp != nil { + in, out := &in.Tcp, &out.Tcp + *out = new(TcpRoute) + (*in).DeepCopyInto(*out) + } return } @@ -344,6 +411,44 @@ func (in *ServiceDiscovery) DeepCopy() *ServiceDiscovery { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TcpRoute) DeepCopyInto(out *TcpRoute) { + *out = *in + in.Action.DeepCopyInto(&out.Action) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TcpRoute. +func (in *TcpRoute) DeepCopy() *TcpRoute { + if in == nil { + return nil + } + out := new(TcpRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TcpRouteAction) DeepCopyInto(out *TcpRouteAction) { + *out = *in + if in.WeightedTargets != nil { + in, out := &in.WeightedTargets, &out.WeightedTargets + *out = make([]WeightedTarget, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TcpRouteAction. +func (in *TcpRouteAction) DeepCopy() *TcpRouteAction { + if in == nil { + return nil + } + out := new(TcpRouteAction) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNode) DeepCopyInto(out *VirtualNode) { *out = *in @@ -453,6 +558,11 @@ func (in *VirtualNodeSpec) DeepCopyInto(out *VirtualNodeSpec) { *out = make([]Backend, len(*in)) copy(*out, *in) } + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(Logging) + (*in).DeepCopyInto(*out) + } return } @@ -514,6 +624,11 @@ func (in *VirtualNodeStatus) DeepCopy() *VirtualNodeStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualRouter) DeepCopyInto(out *VirtualRouter) { *out = *in + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]Listener, len(*in)) + copy(*out, *in) + } return } @@ -640,7 +755,7 @@ func (in *VirtualServiceSpec) DeepCopyInto(out *VirtualServiceSpec) { if in.VirtualRouter != nil { in, out := &in.VirtualRouter, &out.VirtualRouter *out = new(VirtualRouter) - **out = **in + (*in).DeepCopyInto(*out) } if in.Routes != nil { in, out := &in.Routes, &out.Routes diff --git a/pkg/notifier/client_test.go b/pkg/notifier/client_test.go new file mode 100644 index 000000000..3695f0877 --- /dev/null +++ b/pkg/notifier/client_test.go @@ -0,0 +1,30 @@ +package notifier + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" +) + +func Test_postMessage(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + var payload = make(map[string]string) + err = json.Unmarshal(b, &payload) + + if payload["status"] != "success" { + t.Fatal("wrong payload") + } + })) + defer ts.Close() + + err := postMessage(ts.URL, map[string]string{"status": "success"}) + if err != nil { + t.Fatal(err) + } +} diff --git a/pkg/notifier/slack_test.go b/pkg/notifier/slack_test.go new file mode 100644 index 000000000..e0bb976a6 --- /dev/null +++ b/pkg/notifier/slack_test.go @@ -0,0 +1,35 @@ +package notifier + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" +) + +func TestSlack_Post(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + var payload = SlackPayload{} + err = json.Unmarshal(b, &payload) + + if payload.Attachments[0].AuthorName != "podinfo.test" { + t.Fatal("wrong author name") + } + })) + defer ts.Close() + + slack, err := NewSlack(ts.URL, "test", "test") + if err != nil { + t.Fatal(err) + } + + err = slack.Post("podinfo", "test", "test", nil, true) + if err != nil { + t.Fatal(err) + } +} diff --git a/pkg/notifier/teams_test.go b/pkg/notifier/teams_test.go new file mode 100644 index 000000000..70799b12f --- /dev/null +++ b/pkg/notifier/teams_test.go @@ -0,0 +1,35 @@ +package notifier + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" +) + +func TestTeams_Post(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + var payload = MSTeamsPayload{} + err = json.Unmarshal(b, &payload) + + if payload.Sections[0].ActivitySubtitle != "podinfo.test" { + t.Fatal("wrong activity subtitle") + } + })) + defer ts.Close() + + teams, err := NewMSTeams(ts.URL) + if err != nil { + t.Fatal(err) + } + + err = teams.Post("podinfo", "test", "test", nil, true) + if err != nil { + t.Fatal(err) + } +} diff --git a/pkg/router/appmesh.go b/pkg/router/appmesh.go index 6b516b19d..c8b36ae0a 100644 --- a/pkg/router/appmesh.go +++ b/pkg/router/appmesh.go @@ -165,11 +165,19 @@ func (ar *AppMeshRouter) reconcileVirtualService(canary *flaggerv1.Canary, name MeshName: canary.Spec.Service.MeshName, VirtualRouter: &AppmeshV1beta1.VirtualRouter{ Name: fmt.Sprintf("%s-router", targetName), + Listeners: []AppmeshV1beta1.Listener{ + { + PortMapping: AppmeshV1beta1.PortMapping{ + Port: int64(canary.Spec.Service.Port), + Protocol: "http", + }, + }, + }, }, Routes: []AppmeshV1beta1.Route{ { Name: fmt.Sprintf("%s-route", targetName), - Http: AppmeshV1beta1.HttpRoute{ + Http: &AppmeshV1beta1.HttpRoute{ Match: AppmeshV1beta1.HttpRouteMatch{ Prefix: routePrefix, },