From f5f853ff1de1a9aa36ef54e2da1edf9967a51c37 Mon Sep 17 00:00:00 2001 From: Sam Beckett Date: Fri, 11 Mar 2022 09:39:49 -0700 Subject: [PATCH 1/3] add debug output on install/delete vs errors --- services/actions.go | 154 ++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/services/actions.go b/services/actions.go index c95460e..139d1e5 100644 --- a/services/actions.go +++ b/services/actions.go @@ -7,23 +7,24 @@ import ( "fmt" "io/ioutil" "net/http" - corev1 "k8s.io/api/core/v1" - utils "service-watcher-istio/utils" + utils "service-watcher-istio/utils" + + corev1 "k8s.io/api/core/v1" ) type Spacespec struct { - Name string `json:"name"}` - Internal bool `json:"internal"}` + Name string `json:"name"}` + Internal bool `json:"internal"}` } type HeaderOperationsspec struct { - Set map[string]string `json:"set,omitempty"` - Add map[string]string `json:"add,omitempty"` - Remove []string `json:"remove,omitempty"` + Set map[string]string `json:"set,omitempty"` + Add map[string]string `json:"add,omitempty"` + Remove []string `json:"remove,omitempty"` } type Headersspec struct { - Request HeaderOperationsspec `json:"request,omitempty"` + Request HeaderOperationsspec `json:"request,omitempty"` Response HeaderOperationsspec `json:"response,omitempty"` } @@ -42,7 +43,7 @@ type Virtualservice struct { } type HTTPSpec struct { - Route []Routespec `json:"route"` + Route []Routespec `json:"route"` Headers Headersspec `json:"headers,omitempty"` } type Routespec struct { @@ -54,26 +55,22 @@ type Routespec struct { } `json:"destination"` } - - func InstallGatewayVirtualservice(obj interface{}) { - - servicename := obj.(*corev1.Service).ObjectMeta.Name - namespace := obj.(*corev1.Service).ObjectMeta.Namespace - vsnamespace := "sites-system" - port := obj.(*corev1.Service).Spec.Ports[0].Port + servicename := obj.(*corev1.Service).ObjectMeta.Name + namespace := obj.(*corev1.Service).ObjectMeta.Namespace + vsnamespace := "sites-system" + port := obj.(*corev1.Service).Spec.Ports[0].Port InstallVirtualService(servicename, namespace, port, vsnamespace) } func DeleteGatewayVirtualservice(obj interface{}) { - - servicename := obj.(*corev1.Service).ObjectMeta.Name - namespace := obj.(*corev1.Service).ObjectMeta.Namespace - vsnamespace :="sites-system" - DeleteVirtualservice(servicename, namespace, vsnamespace) + servicename := obj.(*corev1.Service).ObjectMeta.Name + namespace := obj.(*corev1.Service).ObjectMeta.Namespace + vsnamespace := "sites-system" + DeleteVirtualservice(servicename, namespace, vsnamespace) } @@ -84,22 +81,22 @@ func InstallVirtualService(servicename string, namespace string, port int32, vsn appname = servicename } var url string - var gateway string + var gateway string internal := isInternal(namespace) if internal { url = appname + "." + utils.InsideDomain - gateway = "apps-private" + gateway = "apps-private" } if !internal { url = appname + "." + utils.DefaultDomain - gateway = "apps-public" + gateway = "apps-public" } var v Virtualservice v.APIVersion = "networking.istio.io/v1alpha3" v.Kind = "VirtualService" v.Metadata.Name = servicename + "-" + namespace v.Metadata.Namespace = vsnamespace - v.Spec.Gateways = append(v.Spec.Gateways, gateway ) + v.Spec.Gateways = append(v.Spec.Gateways, gateway) v.Spec.Hosts = append(v.Spec.Hosts, url) var r Routespec r.Destination.Host = servicename + "." + namespace + ".svc.cluster.local" @@ -140,54 +137,71 @@ func InstallVirtualService(servicename string, namespace string, port int32, vsn } defer resp.Body.Close() fmt.Println("install virtual service response: " + resp.Status) + if resp.StatusCode >= 500 && resp.StatusCode < 600 { + fmt.Println("Error installing virtual service") + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Println("Unable to read error body") + } else { + fmt.Println(string(bodyBytes)) + } + } } -func DeleteVirtualservice(servicename string, namespace string, vsnamespace string){ - req, err := http.NewRequest("DELETE", utils.Kubernetesapiurl+"/apis/networking.istio.io/v1alpha3/namespaces/"+vsnamespace+"/virtualservices/"+servicename+"-"+namespace, nil) - if err != nil { - fmt.Println("Error creating request") - fmt.Println(err) - } - req.Header.Add("Content-type", "application/json") - req.Header.Add("Authorization", "Bearer "+utils.Kubetoken) - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - client := &http.Client{Transport: tr} - - resp, doerr := client.Do(req) - fmt.Printf("%+v\n", resp) - if doerr != nil { - fmt.Println("Do error") - fmt.Println(doerr) - } - defer resp.Body.Close() - fmt.Println("delete virtual service response: " + resp.Status) - } +func DeleteVirtualservice(servicename string, namespace string, vsnamespace string) { + req, err := http.NewRequest("DELETE", utils.Kubernetesapiurl+"/apis/networking.istio.io/v1alpha3/namespaces/"+vsnamespace+"/virtualservices/"+servicename+"-"+namespace, nil) + if err != nil { + fmt.Println("Error creating request") + fmt.Println(err) + } + req.Header.Add("Content-type", "application/json") + req.Header.Add("Authorization", "Bearer "+utils.Kubetoken) + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} + + resp, doerr := client.Do(req) + fmt.Printf("%+v\n", resp) + if doerr != nil { + fmt.Println("Do error") + fmt.Println(doerr) + } + defer resp.Body.Close() + fmt.Println("delete virtual service response: " + resp.Status) + if resp.StatusCode >= 500 && resp.StatusCode < 600 { + fmt.Println("Error deleting virtual service") + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Println("Unable to read error body") + } else { + fmt.Println(string(bodyBytes)) + } + } +} func isInternal(space string) bool { - req, err := http.NewRequest("GET", utils.Regionapilocation+"/v1/space/"+space, nil) - req.SetBasicAuth(utils.Regionapiusername, utils.Regionapipassword) - if err != nil { - fmt.Println(err) - } - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - client := &http.Client{Transport: tr} - resp, err := client.Do(req) - if err != nil { - fmt.Println(err) - } - defer resp.Body.Close() - bb, err := ioutil.ReadAll(resp.Body) - var spaceobject Spacespec - uerr := json.Unmarshal(bb, &spaceobject) - if uerr != nil { - fmt.Println(uerr) - } - fmt.Printf("ISINTERNAL: %v\n",spaceobject.Internal) - return spaceobject.Internal + req, err := http.NewRequest("GET", utils.Regionapilocation+"/v1/space/"+space, nil) + req.SetBasicAuth(utils.Regionapiusername, utils.Regionapipassword) + if err != nil { + fmt.Println(err) + } + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} + resp, err := client.Do(req) + if err != nil { + fmt.Println(err) + } + defer resp.Body.Close() + bb, err := ioutil.ReadAll(resp.Body) + var spaceobject Spacespec + uerr := json.Unmarshal(bb, &spaceobject) + if uerr != nil { + fmt.Println(uerr) + } + fmt.Printf("ISINTERNAL: %v\n", spaceobject.Internal) + return spaceobject.Internal } - From ad0e94bbee2f06c48daea1395f86f3bce44446a7 Mon Sep 17 00:00:00 2001 From: Sam Beckett Date: Fri, 11 Mar 2022 10:07:26 -0700 Subject: [PATCH 2/3] add ignorelist for ignoring labeled services --- process.go | 28 +++++++++++++++++++--------- utils/variables.go | 30 +++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/process.go b/process.go index b670b9b..5b975cc 100644 --- a/process.go +++ b/process.go @@ -3,10 +3,16 @@ package main import ( "encoding/json" "fmt" + "os" + k8sconfig "service-watcher-istio/k8sconfig" + services "service-watcher-istio/services" + utils "service-watcher-istio/utils" + "time" + "github.com/stackimpact/stackimpact-go" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" api "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" @@ -14,11 +20,6 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/clientcmd" - "os" - k8sconfig "service-watcher-istio/k8sconfig" - services "service-watcher-istio/services" - utils "service-watcher-istio/utils" - "time" ) func main() { @@ -75,7 +76,7 @@ func printEventAdd(obj interface{}) { now := v1.Now().Unix() diff := now - created - if diff < 300 && !Blacklisted(obj.(*corev1.Service).ObjectMeta.Namespace) { + if diff < 300 && !Blacklisted(obj.(*corev1.Service).ObjectMeta.Namespace) && !Ignored(obj.(*corev1.Service).ObjectMeta.Labels) { fmt.Println("ADD") var err error @@ -95,18 +96,27 @@ func Blacklisted(namespace string) bool { } +func Ignored(labels map[string]string) bool { + for label := range labels { + if utils.IgnoreList[label] { + return true + } + } + return false +} + func printEventDelete(obj interface{}) { fmt.Println("DELETE") _, isService := obj.(*corev1.Service) if isService { - if !Blacklisted(obj.(*corev1.Service).ObjectMeta.Namespace) { + if !Blacklisted(obj.(*corev1.Service).ObjectMeta.Namespace) && !Ignored(obj.(*corev1.Service).ObjectMeta.Labels) { var err error _, err = json.Marshal(obj) if err != nil { fmt.Println(err) return } - services.DeleteGatewayVirtualservice(obj) + services.DeleteGatewayVirtualservice(obj) } } diff --git a/utils/variables.go b/utils/variables.go index c0f6325..1d64e28 100644 --- a/utils/variables.go +++ b/utils/variables.go @@ -1,10 +1,10 @@ - package utils import ( + "fmt" "os" "strings" - "fmt" + "k8s.io/client-go/rest" ) @@ -13,6 +13,7 @@ var DefaultDomain string var InsideDomain string var Kubernetesapiurl string var Blacklist map[string]bool +var IgnoreList map[string]bool var Client rest.Interface var Regionapilocation string var Regionapiusername string @@ -24,11 +25,12 @@ func SetSecrets() { DefaultDomain = os.Getenv("DEFAULT_DOMAIN") InsideDomain = os.Getenv("INSIDE_DOMAIN") Kubernetesapiurl = os.Getenv("KUBERNETES_API_SERVER") - Regionapiusername = os.Getenv("REGIONAPI_USERNAME") - Regionapipassword = os.Getenv("REGIONAPI_PASSWORD") - Regionapilocation = os.Getenv("REGIONAPI_URL") + Regionapiusername = os.Getenv("REGIONAPI_USERNAME") + Regionapipassword = os.Getenv("REGIONAPI_PASSWORD") + Regionapilocation = os.Getenv("REGIONAPI_URL") initBlacklist() + initIgnoreList() } func initBlacklist() { @@ -36,13 +38,27 @@ func initBlacklist() { blackliststring := os.Getenv("NAMESPACE_BLACKLIST") blacklistslice := strings.Split(blackliststring, ",") for _, element := range blacklistslice { - Blacklist[element] = true + Blacklist[element] = true } keys := make([]string, 0, len(Blacklist)) for k := range Blacklist { - keys = append(keys, k) + keys = append(keys, k) } fmt.Printf("Setting blacklist to %v\n", strings.Join(keys, ",")) } + +func initIgnoreList() { + IgnoreList = make(map[string]bool) + ignoreliststring := os.Getenv("IGNORE_LABELS") + ignorelistslice := strings.Split(ignoreliststring, ",") + for _, element := range ignorelistslice { + IgnoreList[element] = true + } + keys := make([]string, 0, len(IgnoreList)) + for k := range IgnoreList { + keys = append(keys, k) + } + fmt.Printf("Setting ignoreList to %v\n", strings.Join(keys, ",")) +} From dad51ec638dfba5d4e0ef30b93bb8205b2231608 Mon Sep 17 00:00:00 2001 From: Sam Beckett Date: Fri, 11 Mar 2022 10:33:24 -0700 Subject: [PATCH 3/3] add readme --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..b6b4a46 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# service-watcher-istio + +Watches for new Kubernetes services for Akkeris apps, and creates Istio VirtualService entries to expose them outside the cluster. + +## Environment Variables Descriptions + +- `NAMESPACE_BLACKLIST`: Do not create virtualservices for services in any namespace in this list. Should be a comma-separated string. +- `IGNORE_LABELS`: Do not create virtualservices for any service with a label on this list. Should be a comma-separated string. + +## Example/Suggested Environment Variables + +This should give you a good starting point. If you find that undesired virtualservices are still being made, you can expand these lists with other namespaces or labels. + +**NAMESPACE_BLACKLIST** + +`flux,cattle-system,cattle-prometheus,kube-system,kube-public,testcafe,akkeris-system,istio-system,nginx-ingress-i,prometheus,sites-system,velero` + +**IGNORE_LABELS** + +`akkeris.io/container-ports` \ No newline at end of file