Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 into MESH-1743-DR-bk
  • Loading branch information
sa committed Jun 27, 2022
2 parents 9497273 + f1a43a4 commit b8dd675
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 60 deletions.
151 changes: 147 additions & 4 deletions admiral/pkg/apis/admiral/routes/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ package routes
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http/httptest"
"strings"
"testing"

"github.com/gorilla/mux"
v1 "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1"
"github.com/istio-ecosystem/admiral/admiral/pkg/clusters"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/common"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/istio"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/secret"
"github.com/stretchr/testify/assert"
"io/ioutil"
"istio.io/client-go/pkg/apis/networking/v1alpha3"
istiofake "istio.io/client-go/pkg/clientset/versioned/fake"
"net/http/httptest"
"strings"
"testing"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestReturnSuccessGET(t *testing.T) {
Expand Down Expand Up @@ -221,3 +224,143 @@ func TestGetServiceEntriesByIdentity(t *testing.T) {
})
}
}

func TestGetGlobalTrafficPolicyByIdentityAndEnv(t *testing.T) {
globalTrafficCache := &mockGlobalTrafficCache{
identityCache: map[string]*v1.GlobalTrafficPolicy{
"stage.testID": {
ObjectMeta: meta_v1.ObjectMeta{
Namespace: "stage-testns",
Name: "stage-testapp",
Labels: map[string]string{"identity": "testID", "admiral.io/env": "stage"},
},
},
"default.testID": {
ObjectMeta: meta_v1.ObjectMeta{
Namespace: "default-testns",
Name: "default-testapp",
Labels: map[string]string{"identity": "testID", "admiral.io/env": "stage"},
},
},
},
}
validOpts := RouteOpts{
RemoteRegistry: &clusters.RemoteRegistry{
AdmiralCache: &clusters.AdmiralCache{
SeClusterCache: common.NewMapOfMaps(),
GlobalTrafficCache: globalTrafficCache,
},
},
}
testCases := []struct {
name string
identity string
env string
opts RouteOpts
expectedStatus int
expectedError string
expectedGTPName string
}{
{
name: "nil RemoteRegistry in RouteOpts should result in InternalServerError",
identity: "testID",
env: "stage",
opts: RouteOpts{},
expectedStatus: 500,
expectedError: "invalid remote registry cache",
},
{
name: "nil RemoteRegistry.AdmiralCache in RouteOpts should result in InternalServerError",
identity: "testID",
env: "stage",
opts: RouteOpts{
RemoteRegistry: &clusters.RemoteRegistry{},
},
expectedStatus: 500,
expectedError: "invalid remote registry cache",
},
{
name: "missing identity path param should result in HTTP bad request",
identity: "",
env: "stage",
opts: validOpts,
expectedStatus: 400,
expectedError: "identity not provided as part of the path param",
},
{
name: "missing env query param should return a valid 200 response with a valid GTP payload",
identity: "testID",
env: "",
opts: validOpts,
expectedStatus: 200,
expectedGTPName: "default-testapp",
},
{
name: "querying for an invalid gtp should result in a 404",
identity: "invalidGTP",
env: "stage",
opts: validOpts,
expectedStatus: 404,
expectedError: "globaltraffic policy with identity: invalidGTP and env: stage was not found",
},
{
name: "valid GTP queried should return a valid 200 response with a valid GTP payload",
identity: "testID",
env: "stage",
opts: validOpts,
expectedStatus: 200,
expectedGTPName: "stage-testapp",
},
}

for _, c := range testCases {
t.Run(c.name, func(t *testing.T) {
r := httptest.NewRequest("GET", "http://admiral.test.com/identity/{id}/globaltrafficpolicy?env="+c.env, nil)
r = mux.SetURLVars(r, map[string]string{"identity": c.identity})
w := httptest.NewRecorder()
c.opts.GetGlobalTrafficPolicyByIdentityAndEnv(w, r)
res := w.Result()
data, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Error(err)
}
if res.StatusCode != c.expectedStatus {
t.Errorf("expected http status %d got %d", c.expectedStatus, res.StatusCode)
}
if c.expectedError != "" {
responseJSON := make(map[string]string)
json.Unmarshal(data, &responseJSON)
if responseJSON["error"] != c.expectedError {
t.Errorf("expected error '%s' got '%s'", c.expectedError, responseJSON["error"])
}
} else {
var responseGTP *v1.GlobalTrafficPolicy
json.Unmarshal(data, &responseGTP)
if responseGTP == nil {
t.Error("expected response GTP to be not nil")
}
if c.expectedGTPName != responseGTP.Name {
t.Errorf("expected GTP %s got GTP %s", c.expectedGTPName, responseGTP.Name)
}
}
res.Body.Close()
})
}

}

type mockGlobalTrafficCache struct {
identityCache map[string]*v1.GlobalTrafficPolicy
}

func (m *mockGlobalTrafficCache) GetFromIdentity(identity string, environment string) (*v1.GlobalTrafficPolicy, error) {
return m.identityCache[common.ConstructGtpKey(environment, identity)], nil
}

func (*mockGlobalTrafficCache) Put(*v1.GlobalTrafficPolicy) error {
return nil
}

func (*mockGlobalTrafficCache) Delete(string, string) error {
return nil
}
60 changes: 59 additions & 1 deletion admiral/pkg/apis/admiral/routes/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package routes
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"strings"

"github.com/gorilla/mux"
"github.com/istio-ecosystem/admiral/admiral/pkg/clusters"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/common"
log "github.com/sirupsen/logrus"
"istio.io/client-go/pkg/apis/networking/v1alpha3"
)

Expand Down Expand Up @@ -146,6 +146,49 @@ func (opts *RouteOpts) GetServiceEntriesByCluster(w http.ResponseWriter, r *http
}
}

// GetGlobalTrafficPolicyByIdentityAndEnv handler returns GlobalTrafficPolicy resource based on
// the matching env and identity passed as query parameters
func (opts *RouteOpts) GetGlobalTrafficPolicyByIdentityAndEnv(w http.ResponseWriter, r *http.Request) {

pathParams := mux.Vars(r)
identity, ok := pathParams["identity"]
if !ok || identity == "" {
generateErrorResponse(w, http.StatusBadRequest, "identity not provided as part of the path param")
return
}

env := r.FormValue("env")
if env == "" {
env = "default"
}

if opts.RemoteRegistry == nil || opts.RemoteRegistry.AdmiralCache == nil {
log.Warn("invalid remote registry cache")
generateErrorResponse(w, http.StatusInternalServerError, "invalid remote registry cache")
return
}

gtps := opts.RemoteRegistry.AdmiralCache.GlobalTrafficCache

if gtps == nil {
log.Print("globaltrafficcache not initialized")
generateErrorResponse(w, http.StatusInternalServerError, "invalid globaltrafficcache")
return
}

gtp, err := gtps.GetFromIdentity(identity, env)
if err != nil {
log.Warn(err)
generateErrorResponse(w, http.StatusInternalServerError, err.Error())
}
if gtp == nil {
generateErrorResponse(w, http.StatusNotFound, fmt.Sprintf("globaltraffic policy with identity: %s and env: %s was not found", identity, env))
return
}

generateResponseJSON(w, http.StatusOK, gtp)
}

func (opts *RouteOpts) GetServiceEntriesByIdentity(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

Expand Down Expand Up @@ -186,3 +229,18 @@ func (opts *RouteOpts) GetServiceEntriesByIdentity(w http.ResponseWriter, r *htt
http.Error(w, "Identity not provided as part of the request", http.StatusBadRequest)
}
}

func generateErrorResponse(w http.ResponseWriter, code int, message string) {
generateResponseJSON(w, code, map[string]string{"error": message})
}

func generateResponseJSON(w http.ResponseWriter, code int, payload interface{}) {
response, err := json.Marshal(payload)
if err != nil {
log.Printf("failed to serialize the payload due to %v", err)
response = []byte("{\"error\": \"malformed response payload\"}")
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write(response)
}
12 changes: 10 additions & 2 deletions admiral/pkg/apis/admiral/routes/routes.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package routes

import (
"log"
"net/http"

"github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/filters"
"github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/server"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/common"
"github.com/prometheus/client_golang/prometheus/promhttp"
"k8s.io/client-go/tools/clientcmd"
"log"
"net/http"
)

var Filter = server.Filters{
Expand Down Expand Up @@ -48,6 +49,13 @@ func NewAdmiralAPIServer(opts *RouteOpts) server.Routes {
Pattern: "/identity/{identity}/serviceentries",
HandlerFunc: opts.GetServiceEntriesByIdentity,
},
server.Route{
Name: "Get the GlobalTrafficPolicy based on the env and identity/asset alias",
Method: "GET",
Pattern: "/identity/{identity}/globaltrafficpolicy",
Query: "env",
HandlerFunc: opts.GetGlobalTrafficPolicyByIdentityAndEnv,
},
}
}

Expand Down
5 changes: 4 additions & 1 deletion admiral/pkg/clusters/serviceentry.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,10 @@ func AddServiceEntriesWithDr(cache *AdmiralCache, sourceClusters map[string]stri
splitByEnv := strings.Split(se.Hosts[0], common.Sep)
var env = splitByEnv[0]

globalTrafficPolicy := cache.GlobalTrafficCache.GetFromIdentity(identityId, env)
globalTrafficPolicy, err := cache.GlobalTrafficCache.GetFromIdentity(identityId, env)
if err != nil {
log.Warn(err)
}

for _, sourceCluster := range sourceClusters {

Expand Down
Loading

0 comments on commit b8dd675

Please sign in to comment.