Skip to content

Commit

Permalink
Add instance restart route
Browse files Browse the repository at this point in the history
  • Loading branch information
J12934 committed Nov 2, 2024
1 parent 67e638e commit 83b8296
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
55 changes: 55 additions & 0 deletions balancer/routes/adminRestartInstance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package routes

import (
"fmt"
"net/http"

"github.com/juice-shop/multi-juicer/balancer/pkg/bundle"
"github.com/juice-shop/multi-juicer/balancer/pkg/teamcookie"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func handleAdminRestartInstance(bundle *bundle.Bundle) http.Handler {
return http.HandlerFunc(
func(responseWriter http.ResponseWriter, req *http.Request) {
team, err := teamcookie.GetTeamFromRequest(bundle, req)
if err != nil || team != "admin" {
http.Error(responseWriter, "", http.StatusUnauthorized)
return
}

teamToRestart := req.PathValue("team")

// find pod for service

pods, err := bundle.ClientSet.CoreV1().Pods(bundle.RuntimeEnvironment.Namespace).List(req.Context(), metav1.ListOptions{
LabelSelector: fmt.Sprintf("app.kubernetes.io/name=juice-shop,app.kubernetes.io/part-of=multi-juicer,team=%s", teamToRestart),
})

if err != nil {
bundle.Log.Printf("Failed to list pods for team '%s': %s", teamToRestart, err)
http.Error(responseWriter, "", http.StatusInternalServerError)
return
}

if len(pods.Items) != 1 {
http.Error(responseWriter, "", http.StatusNotFound)
return
}

// delete pod
pod := pods.Items[0]

err = bundle.ClientSet.CoreV1().Pods(bundle.RuntimeEnvironment.Namespace).Delete(req.Context(), pod.Name, metav1.DeleteOptions{})

if err != nil {
bundle.Log.Printf("Failed to restart pods for team '%s': %s", teamToRestart, err)
http.Error(responseWriter, "", http.StatusInternalServerError)
return
}

responseWriter.WriteHeader(http.StatusOK)
responseWriter.Write([]byte{})
},
)
}
80 changes: 80 additions & 0 deletions balancer/routes/adminRestartInstance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package routes

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/juice-shop/multi-juicer/balancer/pkg/testutil"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes/fake"
)

func TestAdminRestartInstanceHandler(t *testing.T) {
createPodForTeam := func(team string) *corev1.Pod {
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("juiceshop-%s", team),
Namespace: "test-namespace",
Labels: map[string]string{
"app.kubernetes.io/name": "juice-shop",
"app.kubernetes.io/part-of": "multi-juicer",
"team": team,
},
},
Spec: corev1.PodSpec{},
}
}

t.Run("restarting instances requires admin login", func(t *testing.T) {
req, _ := http.NewRequest("POST", "/balancer/admin/teams/foobar/restart", nil)
req.Header.Set("Cookie", fmt.Sprintf("team=%s", testutil.SignTestTeamname("some team")))
rr := httptest.NewRecorder()

server := http.NewServeMux()

clientset := fake.NewSimpleClientset(createPodForTeam("foobar"))
bundle := testutil.NewTestBundleWithCustomFakeClient(clientset)
AddRoutes(server, bundle)

server.ServeHTTP(rr, req)

assert.Equal(t, http.StatusUnauthorized, rr.Code)
assert.Equal(t, "\n", rr.Body.String())
})

t.Run("restart instances deletes the pod for the instance", func(t *testing.T) {
req, _ := http.NewRequest("POST", "/balancer/admin/teams/foobar/restart", nil)
req.Header.Set("Cookie", fmt.Sprintf("team=%s", testutil.SignTestTeamname("admin")))
rr := httptest.NewRecorder()

server := http.NewServeMux()

clientset := fake.NewSimpleClientset(createPodForTeam("foobar"), createPodForTeam("other-team"))
bundle := testutil.NewTestBundleWithCustomFakeClient(clientset)
AddRoutes(server, bundle)

server.ServeHTTP(rr, req)

assert.Equal(t, http.StatusOK, rr.Code)
assert.Equal(t, "", rr.Body.String())

actions := clientset.Actions()

assert.Len(t, actions, 2)

assert.Equal(t, "list", actions[0].GetVerb())
assert.Equal(t, schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}, actions[0].GetResource())
assert.Equal(t, "delete", actions[1].GetVerb())
assert.Equal(t, schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}, actions[1].GetResource())

pods, err := clientset.CoreV1().Pods("test-namespace").List(context.Background(), metav1.ListOptions{})
assert.Nil(t, err)
assert.Len(t, pods.Items, 1)
})
}
1 change: 1 addition & 0 deletions balancer/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func AddRoutes(

router.Handle("GET /balancer/admin/all", handleAdminListInstances(bundle))
router.Handle("DELETE /balancer/admin/teams/{team}/delete", handleAdminDeleteInstance(bundle))
router.Handle("POST /balancer/admin/teams/{team}/restart", handleAdminRestartInstance(bundle))

router.HandleFunc("GET /balancer/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
Expand Down

0 comments on commit 83b8296

Please sign in to comment.