Skip to content

Commit

Permalink
Merge pull request #6 from akkeris/COBRA-5020
Browse files Browse the repository at this point in the history
COBRA-5020: Add "ignorelist" for ignoring specific labeled services
  • Loading branch information
sbeck14 authored Mar 11, 2022
2 parents a0aca44 + dad51ec commit 0b87793
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 86 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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`
28 changes: 19 additions & 9 deletions process.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ 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"
"k8s.io/apimachinery/pkg/watch"
"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() {
Expand Down Expand Up @@ -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

Expand All @@ -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)
}
}

Expand Down
154 changes: 84 additions & 70 deletions services/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}

Expand All @@ -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 {
Expand All @@ -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)

}

Expand All @@ -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"
Expand Down Expand Up @@ -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
}

30 changes: 23 additions & 7 deletions utils/variables.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

package utils

import (
"fmt"
"os"
"strings"
"fmt"

"k8s.io/client-go/rest"
)

Expand All @@ -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
Expand All @@ -24,25 +25,40 @@ 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() {
Blacklist = make(map[string]bool)
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, ","))
}

0 comments on commit 0b87793

Please sign in to comment.