From c5b25a19c88f3c0a87b5eed9e258bd52993e8b47 Mon Sep 17 00:00:00 2001 From: Utkarsh Srivastava Date: Wed, 16 Jun 2021 13:53:58 +0530 Subject: [PATCH 1/5] add envoyfilter schema and oam definitions Signed-off-by: Utkarsh Srivastava --- .../envoyfilter.meshery.layer5.io.schema.json | 277 ++++++++++++++++++ .../oam/workloads/envoyfilter_definition.json | 12 + 2 files changed, 289 insertions(+) create mode 100644 templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json create mode 100644 templates/oam/workloads/envoyfilter_definition.json diff --git a/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json b/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json new file mode 100644 index 000000000..1d0ea50e3 --- /dev/null +++ b/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json @@ -0,0 +1,277 @@ +{ + "description": "Customizing Envoy configuration generated by Istio. See more details at: https://istio.io/docs/reference/config/networking/envoy-filter.html", + "properties": { + "configPatches": { + "description": "One or more patches with match conditions.", + "items": { + "properties": { + "applyTo": { + "enum": [ + "INVALID", + "LISTENER", + "FILTER_CHAIN", + "NETWORK_FILTER", + "HTTP_FILTER", + "ROUTE_CONFIGURATION", + "VIRTUAL_HOST", + "HTTP_ROUTE", + "CLUSTER", + "EXTENSION_CONFIG" + ], + "type": "string" + }, + "match": { + "description": "Match on listener/route configuration/cluster.", + "oneOf": [ + { + "not": { + "anyOf": [ + { + "required": ["listener"] + }, + { + "required": ["routeConfiguration"] + }, + { + "required": ["cluster"] + } + ] + } + }, + { + "required": ["listener"] + }, + { + "required": ["routeConfiguration"] + }, + { + "required": ["cluster"] + } + ], + "properties": { + "cluster": { + "description": "Match on envoy cluster attributes.", + "properties": { + "name": { + "description": "The exact name of the cluster to match.", + "format": "string", + "type": "string" + }, + "portNumber": { + "description": "The service port for which this cluster was generated.", + "type": "integer" + }, + "service": { + "description": "The fully qualified service name for this cluster.", + "format": "string", + "type": "string" + }, + "subset": { + "description": "The subset associated with the service.", + "format": "string", + "type": "string" + } + }, + "type": "object" + }, + "context": { + "description": "The specific config generation context to match on.", + "enum": [ + "ANY", + "SIDECAR_INBOUND", + "SIDECAR_OUTBOUND", + "GATEWAY" + ], + "type": "string" + }, + "listener": { + "description": "Match on envoy listener attributes.", + "properties": { + "filterChain": { + "description": "Match a specific filter chain in a listener.", + "properties": { + "applicationProtocols": { + "description": "Applies only to sidecars.", + "format": "string", + "type": "string" + }, + "destinationPort": { + "description": "The destination_port value used by a filter chain's match condition.", + "type": "integer" + }, + "filter": { + "description": "The name of a specific filter to apply the patch to.", + "properties": { + "name": { + "description": "The filter name to match on.", + "format": "string", + "type": "string" + }, + "subFilter": { + "properties": { + "name": { + "description": "The filter name to match on.", + "format": "string", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "name": { + "description": "The name assigned to the filter chain.", + "format": "string", + "type": "string" + }, + "sni": { + "description": "The SNI value used by a filter chain's match condition.", + "format": "string", + "type": "string" + }, + "transportProtocol": { + "description": "Applies only to `SIDECAR_INBOUND` context.", + "format": "string", + "type": "string" + } + }, + "type": "object" + }, + "name": { + "description": "Match a specific listener by its name.", + "format": "string", + "type": "string" + }, + "portName": { + "format": "string", + "type": "string" + }, + "portNumber": { + "type": "integer" + } + }, + "type": "object" + }, + "proxy": { + "description": "Match on properties associated with a proxy.", + "properties": { + "metadata": { + "additionalProperties": { + "format": "string", + "type": "string" + }, + "type": "object" + }, + "proxyVersion": { + "format": "string", + "type": "string" + } + }, + "type": "object" + }, + "routeConfiguration": { + "description": "Match on envoy HTTP route configuration attributes.", + "properties": { + "gateway": { + "format": "string", + "type": "string" + }, + "name": { + "description": "Route configuration name to match on.", + "format": "string", + "type": "string" + }, + "portName": { + "description": "Applicable only for GATEWAY context.", + "format": "string", + "type": "string" + }, + "portNumber": { + "type": "integer" + }, + "vhost": { + "properties": { + "name": { + "format": "string", + "type": "string" + }, + "route": { + "description": "Match a specific route within the virtual host.", + "properties": { + "action": { + "description": "Match a route with specific action type.", + "enum": [ + "ANY", + "ROUTE", + "REDIRECT", + "DIRECT_RESPONSE" + ], + "type": "string" + }, + "name": { + "format": "string", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "patch": { + "description": "The patch to apply along with the operation.", + "properties": { + "filterClass": { + "description": "Determines the filter insertion order.", + "enum": ["UNSPECIFIED", "AUTHN", "AUTHZ", "STATS"], + "type": "string" + }, + "operation": { + "description": "Determines how the patch should be applied.", + "enum": [ + "INVALID", + "MERGE", + "ADD", + "REMOVE", + "INSERT_BEFORE", + "INSERT_AFTER", + "INSERT_FIRST", + "REPLACE" + ], + "type": "string" + }, + "value": { + "description": "The JSON config of the object being patched.", + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "type": "array" + }, + "workloadSelector": { + "properties": { + "labels": { + "additionalProperties": { + "format": "string", + "type": "string" + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object", + "$schema": "http://json-schema.org/draft-04/schema#" +} diff --git a/templates/oam/workloads/envoyfilter_definition.json b/templates/oam/workloads/envoyfilter_definition.json new file mode 100644 index 000000000..9e33980c2 --- /dev/null +++ b/templates/oam/workloads/envoyfilter_definition.json @@ -0,0 +1,12 @@ +{ + "apiVersion": "core.oam.dev/v1alpha1", + "kind": "WorkloadDefinition", + "metadata": { + "name": "EnvoyFilter" + }, + "spec": { + "definitionRef": { + "name": "envoyfilter.meshery.layer5.io" + } + } +} \ No newline at end of file From 22a49c3b441197f308691b9adcadc4cf843cd7aa Mon Sep 17 00:00:00 2001 From: Utkarsh Srivastava Date: Wed, 16 Jun 2021 13:54:18 +0530 Subject: [PATCH 2/5] register envoyfilter metadata Signed-off-by: Utkarsh Srivastava --- istio/oam/register.go | 1 + 1 file changed, 1 insertion(+) diff --git a/istio/oam/register.go b/istio/oam/register.go index 43c9d6f83..cf63cd53d 100644 --- a/istio/oam/register.go +++ b/istio/oam/register.go @@ -40,6 +40,7 @@ func RegisterWorkloads(runtime, host string) error { "zipkinistioaddon", "jaegeristioaddon", "virtualservice", + "envoyfilter", } oamRDP := []adapter.OAMRegistrantDefinitionPath{} From ebbda19c9091bd3e2ee13aefb97eb67e1f14066b Mon Sep 17 00:00:00 2001 From: Utkarsh Srivastava Date: Wed, 16 Jun 2021 13:54:32 +0530 Subject: [PATCH 3/5] handle envoyfilter component Signed-off-by: Utkarsh Srivastava --- istio/oam.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/istio/oam.go b/istio/oam.go index 5eda1f248..f8184c93d 100644 --- a/istio/oam.go +++ b/istio/oam.go @@ -22,6 +22,7 @@ func (istio *Istio) HandleComponents(comps []v1alpha1.Component, isDel bool) (st compFuncMap := map[string]CompHandler{ "IstioMesh": handleComponentIstioMesh, "VirtualService": handleComponentVirtualService, + "EnvoyFilterIstio": handleComponentEnvoyFilter, "GrafanaIstioAddon": handleComponentIstioAddon, "PrometheusIstioAddon": handleComponentIstioAddon, "ZipkinIstioAddon": handleComponentIstioAddon, @@ -144,6 +145,35 @@ func handleComponentVirtualService(istio *Istio, comp v1alpha1.Component, isDel return msg, istio.applyManifest(yamlByt, isDel, comp.Namespace) } +func handleComponentEnvoyFilter(istio *Istio, comp v1alpha1.Component, isDel bool) (string, error) { + envoyFilter := map[string]interface{}{ + "apiVersion": "networking.istio.io/v1alpha3", + "kind": "EnvoyFilter", + "metadata": map[string]interface{}{ + "name": comp.Name, + "annotations": comp.Annotations, + "labels": comp.Labels, + }, + "spec": comp.Spec.Settings, + } + + // Convert to yaml + yamlByt, err := yaml.Marshal(envoyFilter) + if err != nil { + err = ErrParseVirtualService(err) + istio.Log.Error(err) + return "", err + } + + msg := fmt.Sprintf("configured envoy filter \"%s\" in namespace \"%s\"", comp.Name, comp.Namespace) + if isDel { + msg = fmt.Sprintf("deleted envoy filter config \"%s\" in namespace \"%s\"", comp.Name, comp.Namespace) + } + + return msg, istio.applyManifest(yamlByt, isDel, comp.Namespace) + +} + func handleComponentIstioAddon(istio *Istio, comp v1alpha1.Component, isDel bool) (string, error) { var addonName string From 41fe8e53005db195310a4f0bbc648c5d1e8b96c6 Mon Sep 17 00:00:00 2001 From: Utkarsh Srivastava Date: Wed, 16 Jun 2021 14:07:34 +0530 Subject: [PATCH 4/5] fix title error Signed-off-by: Utkarsh Srivastava --- istio/oam.go | 1 - .../oam/workloads/envoyfilter.meshery.layer5.io.schema.json | 3 ++- templates/oam/workloads/envoyfilter_definition.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/istio/oam.go b/istio/oam.go index f8184c93d..6e4de1ea3 100644 --- a/istio/oam.go +++ b/istio/oam.go @@ -171,7 +171,6 @@ func handleComponentEnvoyFilter(istio *Istio, comp v1alpha1.Component, isDel boo } return msg, istio.applyManifest(yamlByt, isDel, comp.Namespace) - } func handleComponentIstioAddon(istio *Istio, comp v1alpha1.Component, isDel bool) (string, error) { diff --git a/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json b/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json index 1d0ea50e3..9471c516e 100644 --- a/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json +++ b/templates/oam/workloads/envoyfilter.meshery.layer5.io.schema.json @@ -273,5 +273,6 @@ } }, "type": "object", - "$schema": "http://json-schema.org/draft-04/schema#" + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Envoy Filter" } diff --git a/templates/oam/workloads/envoyfilter_definition.json b/templates/oam/workloads/envoyfilter_definition.json index 9e33980c2..7e58fde83 100644 --- a/templates/oam/workloads/envoyfilter_definition.json +++ b/templates/oam/workloads/envoyfilter_definition.json @@ -2,7 +2,7 @@ "apiVersion": "core.oam.dev/v1alpha1", "kind": "WorkloadDefinition", "metadata": { - "name": "EnvoyFilter" + "name": "EnvoyFilterIstio" }, "spec": { "definitionRef": { From 8955835de844d24f127af09bfb6e49e561716a44 Mon Sep 17 00:00:00 2001 From: Utkarsh Srivastava Date: Thu, 17 Jun 2021 18:57:56 +0530 Subject: [PATCH 5/5] refactored core component handler Signed-off-by: Utkarsh Srivastava --- istio/error.go | 12 ++++++------ istio/oam.go | 49 +++++++++++++++++-------------------------------- 2 files changed, 23 insertions(+), 38 deletions(-) diff --git a/istio/error.go b/istio/error.go index bad3f1543..41fc435c5 100644 --- a/istio/error.go +++ b/istio/error.go @@ -86,9 +86,9 @@ var ( // generated when kubernetes client is nil ErrNilClientCode = "istio_test_code" - // ErrParseVirtualServiceCode represents the error code which is - // generated when virtual service parsing fails - ErrParseVirtualServiceCode = "istio_test_code" + // ErrParseIstioCoreComponentCode represents the error code which is + // generated when istio core component manifest parsing fails + ErrParseIstioCoreComponentCode = "istio_test_code" // ErrInvalidOAMComponentTypeCode represents the error code which is // generated when an invalid oam component is requested @@ -191,9 +191,9 @@ func ErrIstioVet(err error) error { return errors.NewDefault(ErrIstioVetCode, err.Error()) } -// ErrParseVirtualService is the error when vsc parsing fails -func ErrParseVirtualService(err error) error { - return errors.NewDefault(ErrParseVirtualServiceCode, err.Error()) +// ErrParseIstioCoreComponent is the error when istio core component manifest parsing fails +func ErrParseIstioCoreComponent(err error) error { + return errors.NewDefault(ErrParseIstioCoreComponentCode, err.Error()) } // ErrInvalidOAMComponentType is the error when the OAM component name is not valid diff --git a/istio/oam.go b/istio/oam.go index 6e4de1ea3..166add9ff 100644 --- a/istio/oam.go +++ b/istio/oam.go @@ -118,37 +118,22 @@ func handleComponentIstioMesh(istio *Istio, comp v1alpha1.Component, isDel bool) } func handleComponentVirtualService(istio *Istio, comp v1alpha1.Component, isDel bool) (string, error) { - virtualSvc := map[string]interface{}{ - "apiVersion": "networking.istio.io/v1beta1", - "kind": "VirtualService", - "metadata": map[string]interface{}{ - "name": comp.Name, - "annotations": comp.Annotations, - "labels": comp.Labels, - }, - "spec": comp.Spec.Settings, - } - - // Convert to yaml - yamlByt, err := yaml.Marshal(virtualSvc) - if err != nil { - err = ErrParseVirtualService(err) - istio.Log.Error(err) - return "", err - } - - msg := fmt.Sprintf("created virtual service \"%s\" in namespace \"%s\"", comp.Name, comp.Namespace) - if isDel { - msg = fmt.Sprintf("deleted virtual service \"%s\" in namespace \"%s\"", comp.Name, comp.Namespace) - } - - return msg, istio.applyManifest(yamlByt, isDel, comp.Namespace) + return handleIstioCoreComponent(istio, comp, isDel, "networking.istio.io/v1beta1", "VirtualService") } func handleComponentEnvoyFilter(istio *Istio, comp v1alpha1.Component, isDel bool) (string, error) { - envoyFilter := map[string]interface{}{ - "apiVersion": "networking.istio.io/v1alpha3", - "kind": "EnvoyFilter", + return handleIstioCoreComponent(istio, comp, isDel, "networking.istio.io/v1alpha3", "EnvoyFilter") +} + +func handleIstioCoreComponent( + istio *Istio, + comp v1alpha1.Component, + isDel bool, + apiVersion, + kind string) (string, error) { + component := map[string]interface{}{ + "apiVersion": apiVersion, + "kind": kind, "metadata": map[string]interface{}{ "name": comp.Name, "annotations": comp.Annotations, @@ -158,16 +143,16 @@ func handleComponentEnvoyFilter(istio *Istio, comp v1alpha1.Component, isDel boo } // Convert to yaml - yamlByt, err := yaml.Marshal(envoyFilter) + yamlByt, err := yaml.Marshal(component) if err != nil { - err = ErrParseVirtualService(err) + err = ErrParseIstioCoreComponent(err) istio.Log.Error(err) return "", err } - msg := fmt.Sprintf("configured envoy filter \"%s\" in namespace \"%s\"", comp.Name, comp.Namespace) + msg := fmt.Sprintf("created %s \"%s\" in namespace \"%s\"", kind, comp.Name, comp.Namespace) if isDel { - msg = fmt.Sprintf("deleted envoy filter config \"%s\" in namespace \"%s\"", comp.Name, comp.Namespace) + msg = fmt.Sprintf("deleted %s config \"%s\" in namespace \"%s\"", kind, comp.Name, comp.Namespace) } return msg, istio.applyManifest(yamlByt, isDel, comp.Namespace)