Skip to content

Commit

Permalink
adding FIS register handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
mye956 committed Aug 6, 2024
1 parent 5c2d1bf commit 3fc3d82
Show file tree
Hide file tree
Showing 3 changed files with 327 additions and 0 deletions.
148 changes: 148 additions & 0 deletions ecs-agent/tmds/handlers/fis/v1/handlers/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package handlers

import (
"fmt"
"net/http"

"github.com/aws/amazon-ecs-agent/ecs-agent/logger"
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
"github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/fis/v1/types"
"github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils"
v4 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4"
state "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state"

"github.com/gorilla/mux"
)

type handler struct {
// TODO: Mutex will be used in a future PR
// mu sync.Mutex
agentState state.AgentState
metricsFactory metrics.EntryFactory
}

// RegisterFISHandlers will initialize all of the Start/Stop/Check fault injection endpoints and register them to the TMDS router
func RegisterFISHandlers(muxRouter *mux.Router, agentState state.AgentState, metricsFactory metrics.EntryFactory) {
handler := handler{
agentState: agentState,
metricsFactory: metricsFactory,
}

// Setting up handler endpoints for network blackhole port fault injections
muxRouter.HandleFunc(
FISNetworkFaultPath(types.BlackHolePortFaultType),
handler.StartNetworkBlackholePort(),
).Methods("PUT")
muxRouter.HandleFunc(
FISNetworkFaultPath(types.BlackHolePortFaultType),
handler.StopBlackHolePort(),
).Methods("DELETE")
muxRouter.HandleFunc(
FISNetworkFaultPath(types.BlackHolePortFaultType),
handler.CheckBlackHolePortStatus(),
).Methods("GET")

// Setting up handler endpoints for network latency fault injections
muxRouter.HandleFunc(
FISNetworkFaultPath(types.LatencyFaultType),
handler.StartLatency(),
).Methods("PUT")
muxRouter.HandleFunc(
FISNetworkFaultPath(types.LatencyFaultType),
handler.StopLatency(),
).Methods("DELETE")
muxRouter.HandleFunc(
FISNetworkFaultPath(types.LatencyFaultType),
handler.CheckLatencyStatus(),
).Methods("GET")

// Setting up handler endpoints for network packet loss fault injections
muxRouter.HandleFunc(
FISNetworkFaultPath(types.PacketLossFaultType),
handler.StartPacketLoss(),
).Methods("PUT")
muxRouter.HandleFunc(
FISNetworkFaultPath(types.PacketLossFaultType),
handler.StopPacketLoss(),
).Methods("DELETE")
muxRouter.HandleFunc(
FISNetworkFaultPath(types.PacketLossFaultType),
handler.CheckPacketLossStatus(),
).Methods("GET")

logger.Debug("FIS Handlers have been set up")

}

// FISNetworkFaultPath will take in a fault type and return the TMDS endpoint path
func FISNetworkFaultPath(fault string) string {
return fmt.Sprintf("/api/%s/fault/v1/%s",
utils.ConstructMuxVar(v4.EndpointContainerIDMuxName, utils.AnythingButSlashRegEx), fault)
}

// TODO
func (h *handler) StartNetworkBlackholePort() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) StopBlackHolePort() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) CheckBlackHolePortStatus() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) StartLatency() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) StopLatency() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) CheckLatencyStatus() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) StartPacketLoss() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) StopPacketLoss() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}

// TODO
func (h *handler) CheckPacketLossStatus() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
}
}
159 changes: 159 additions & 0 deletions ecs-agent/tmds/handlers/fis/v1/handlers/handlers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//go:build unit
// +build unit

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package handlers

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

mock_metrics "github.com/aws/amazon-ecs-agent/ecs-agent/metrics/mocks"
"github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/fis/v1/types"
mock_state "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state/mocks"

"github.com/golang/mock/gomock"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const (
endpointId = "endpointId"
)

// Tests the path for FIS Network Faults API
func TestFISBlackholeFaultPath(t *testing.T) {
assert.Equal(t, "/api/{endpointContainerIDMuxName:[^/]*}/fault/v1/network-blackhole-port", FISNetworkFaultPath(types.BlackHolePortFaultType))
}

func TestFISLatencyFaultPath(t *testing.T) {
assert.Equal(t, "/api/{endpointContainerIDMuxName:[^/]*}/fault/v1/network-latency", FISNetworkFaultPath(types.LatencyFaultType))
}

func TestFISPacketLossFaultPath(t *testing.T) {
assert.Equal(t, "/api/{endpointContainerIDMuxName:[^/]*}/fault/v1/network-packet-loss", FISNetworkFaultPath(types.PacketLossFaultType))
}

func TestRegisterHandler(t *testing.T) {
tcs := []struct {
name string
expectedStatusCode int
fault string
method string
}{
{
name: "PUT blackholeport",
expectedStatusCode: http.StatusOK,
fault: types.BlackHolePortFaultType,
method: "PUT",
},
{
name: "DELETE blackholeport",
expectedStatusCode: http.StatusOK,
fault: types.BlackHolePortFaultType,
method: "DELETE",
},
{
name: "GET blackholeport",
expectedStatusCode: http.StatusOK,
fault: types.BlackHolePortFaultType,
method: "GET",
},
{
name: "PUT latency",
expectedStatusCode: http.StatusOK,
fault: types.LatencyFaultType,
method: "PUT",
},
{
name: "DELETE latency",
expectedStatusCode: http.StatusOK,
fault: types.LatencyFaultType,
method: "DELETE",
},
{
name: "GET latency",
expectedStatusCode: http.StatusOK,
fault: types.BlackHolePortFaultType,
method: "GET",
},
{
name: "PUT packet loss",
expectedStatusCode: http.StatusOK,
fault: types.PacketLossFaultType,
method: "PUT",
},
{
name: "DELETE packet loss",
expectedStatusCode: http.StatusOK,
fault: types.PacketLossFaultType,
method: "DELETE",
},
{
name: "GET packet loss",
expectedStatusCode: http.StatusOK,
fault: types.PacketLossFaultType,
method: "GET",
},
{
name: "PUT unknown",
expectedStatusCode: http.StatusNotFound,
fault: "unknown",
method: "PUT",
},
{
name: "DELETE unknown",
expectedStatusCode: http.StatusNotFound,
fault: "unknown",
method: "DELETE",
},
{
name: "GET unknown",
expectedStatusCode: http.StatusNotFound,
fault: "unknown",
method: "GET",
},
}

for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
// Mocks
ctrl := gomock.NewController(t)
defer ctrl.Finish()

agentState := mock_state.NewMockAgentState(ctrl)
metricsFactory := mock_metrics.NewMockEntryFactory(ctrl)

router := mux.NewRouter()

RegisterFISHandlers(router, agentState, metricsFactory)
var requestBody io.Reader
req, err := http.NewRequest(tc.method, fmt.Sprintf("/api/%s/fault/v1/%s", endpointId, tc.fault),
requestBody)
require.NoError(t, err)

// Send the request and record the response
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, req)

assert.Equal(t, recorder.Code, tc.expectedStatusCode)
})
}

}
20 changes: 20 additions & 0 deletions ecs-agent/tmds/handlers/fis/v1/types/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package types

const (
BlackHolePortFaultType = "network-blackhole-port"
LatencyFaultType = "network-latency"
PacketLossFaultType = "network-packet-loss"
)

0 comments on commit 3fc3d82

Please sign in to comment.