Skip to content

Commit

Permalink
remove license handler from v1
Browse files Browse the repository at this point in the history
  • Loading branch information
willmyrs committed Jan 29, 2025
1 parent d790772 commit 8ed0793
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 61 deletions.
38 changes: 38 additions & 0 deletions ecs-agent/introspection/handlers.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,50 @@
// 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 introspection

import (
"errors"
"net/http"

v1 "github.com/aws/amazon-ecs-agent/ecs-agent/introspection/v1"
"github.com/aws/amazon-ecs-agent/ecs-agent/logger"
"github.com/aws/amazon-ecs-agent/ecs-agent/logger/field"
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
tmdsutils "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils"
)

const (
requestTypeLicense = "introspection/license"
licensePath = "/license"
)

// licenseHandler creates response for '/license' API.
func licenseHandler(agentState v1.AgentState, metricsFactory metrics.EntryFactory) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
text, err := agentState.GetLicenseText()
if err != nil {
logger.Error("Failed to get v1 license.", logger.Fields{
field.Error: err,
})
metricsFactory.New(metrics.IntrospectionInternalServerError).Done(err)
tmdsutils.WriteStringToResponse(w, http.StatusInternalServerError, "", requestTypeLicense)
} else {
tmdsutils.WriteStringToResponse(w, http.StatusOK, text, requestTypeLicense)
}
}
}

// panicHandler handler will gracefully close the connection if a panic occurs, returning
// an internal server error to the client.
func panicHandler(next http.Handler, metricsFactory metrics.EntryFactory) http.Handler {
Expand Down
103 changes: 103 additions & 0 deletions ecs-agent/introspection/handlers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//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 introspection

import (
"errors"
"net/http"
"net/http/httptest"
"testing"

v1 "github.com/aws/amazon-ecs-agent/ecs-agent/introspection/v1"
mock_v1 "github.com/aws/amazon-ecs-agent/ecs-agent/introspection/v1/mocks"
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
mock_metrics "github.com/aws/amazon-ecs-agent/ecs-agent/metrics/mocks"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type IntrospectionResponse interface {
string |
*v1.AgentMetadataResponse |
*v1.TaskResponse |
*v1.TasksResponse
}

type IntrospectionTestCase[R IntrospectionResponse] struct {
Path string
AgentResponse R
Err error
MetricName string
}

const (
licenseText = "Licensed under the Apache License ..."
internalErrorText = "some internal error"
)

func testHandlerSetup[R IntrospectionResponse](t *testing.T, testCase IntrospectionTestCase[R]) (
*gomock.Controller, *mock_v1.MockAgentState, *mock_metrics.MockEntryFactory, *http.Request, *httptest.ResponseRecorder) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

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

req, err := http.NewRequest("GET", testCase.Path, nil)
require.NoError(t, err)
recorder := httptest.NewRecorder()

return ctrl, agentState, metricsFactory, req, recorder
}

func TestLicenseHandler(t *testing.T) {
var performMockRequest = func(t *testing.T, testCase IntrospectionTestCase[string]) *httptest.ResponseRecorder {
mockCtrl, mockAgentState, mockMetricsFactory, req, recorder := testHandlerSetup(t, testCase)
mockAgentState.EXPECT().
GetLicenseText().
Return(testCase.AgentResponse, testCase.Err)
if testCase.Err != nil {
mockEntry := mock_metrics.NewMockEntry(mockCtrl)
mockEntry.EXPECT().Done(testCase.Err)
mockMetricsFactory.EXPECT().
New(testCase.MetricName).Return(mockEntry)
}
licenseHandler(mockAgentState, mockMetricsFactory)(recorder, req)
return recorder
}

t.Run("happy case", func(t *testing.T) {
recorder := performMockRequest(t, IntrospectionTestCase[string]{
Path: licensePath,
AgentResponse: licenseText,
Err: nil,
})
assert.Equal(t, http.StatusOK, recorder.Code)
assert.Equal(t, licenseText, recorder.Body.String())
})

t.Run("internal error", func(t *testing.T) {
recorder := performMockRequest(t, IntrospectionTestCase[string]{
Path: licensePath,
AgentResponse: "",
Err: errors.New(internalErrorText),
MetricName: metrics.IntrospectionInternalServerError,
})
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
assert.Equal(t, "", recorder.Body.String())
})
}
4 changes: 2 additions & 2 deletions ecs-agent/introspection/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func v1HandlersSetup(serverMux *http.ServeMux,
metricsFactory metrics.EntryFactory) {
serverMux.HandleFunc(handlers.V1AgentMetadataPath, handlers.AgentMetadataHandler(agentState, metricsFactory))
serverMux.HandleFunc(handlers.V1TasksMetadataPath, handlers.TasksMetadataHandler(agentState, metricsFactory))
serverMux.HandleFunc(handlers.V1LicensePath, handlers.LicenseHandler(agentState, metricsFactory))
serverMux.HandleFunc(licensePath, licenseHandler(agentState, metricsFactory))
}
func pprofHandlerSetup(serverMux *http.ServeMux) {
serverMux.HandleFunc(pprofBasePath, pprofIndexHandler)
Expand All @@ -120,7 +120,7 @@ func setup(
return nil, errors.New("metrics factory cannot be nil")
}

paths := []string{handlers.V1AgentMetadataPath, handlers.V1TasksMetadataPath, handlers.V1LicensePath}
paths := []string{handlers.V1AgentMetadataPath, handlers.V1TasksMetadataPath, licensePath}

if config.enableRuntimeStats {
paths = append(paths, pprofBasePath, pprofCMDLinePath, pprofProfilePath, pprofSymbolPath, pprofTracePath)
Expand Down
4 changes: 2 additions & 2 deletions ecs-agent/introspection/server_integ_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func TestRoutes(t *testing.T) {
GetLicenseText().
Return(licenseText, nil)

recorder := performMockRequest(t, server, handlers.V1LicensePath)
recorder := performMockRequest(t, server, licensePath)

assert.Equal(t, http.StatusOK, recorder.Code)
assert.Equal(t, string(licenseText), recorder.Body.String())
Expand All @@ -133,7 +133,7 @@ func TestRoutes(t *testing.T) {
mockMetricsFactory.EXPECT().
New(metrics.IntrospectionInternalServerError).Return(mockEntry)

recorder := performMockRequest(t, server, handlers.V1LicensePath)
recorder := performMockRequest(t, server, licensePath)

assert.Equal(t, http.StatusInternalServerError, recorder.Code)
assert.Equal(t, "", recorder.Body.String())
Expand Down
18 changes: 0 additions & 18 deletions ecs-agent/introspection/v1/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,11 @@ const (
dockerShortIDLen = 12
requestTypeAgent = "introspection/agent"
requestTypeTasks = "introspection/tasks"
requestTypeLicense = "introspection/license"

V1LicensePath = "/license"
V1AgentMetadataPath = "/v1/metadata"
V1TasksMetadataPath = "/v1/tasks"
)

// LicenseHandler creates response for '/license' API.
func LicenseHandler(agentState v1.AgentState, metricsFactory metrics.EntryFactory) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
text, err := agentState.GetLicenseText()
if err != nil {
logger.Error("Failed to get v1 license.", logger.Fields{
field.Error: err,
})
metricsFactory.New(metrics.IntrospectionInternalServerError).Done(err)
tmdsutils.WriteStringToResponse(w, http.StatusInternalServerError, "", requestTypeLicense)
} else {
tmdsutils.WriteStringToResponse(w, http.StatusOK, text, requestTypeLicense)
}
}
}

// getHTTPErrorCode returns an appropriate HTTP response status code and body for the error.
func getHTTPErrorCode(err error) (int, string) {
// There was something wrong with the request
Expand Down
39 changes: 0 additions & 39 deletions ecs-agent/introspection/v1/handlers/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import (
)

const (
licenseText = "Licensed under the Apache License ..."
taskARN = "t1"
family = "sleep"
version = "1"
Expand Down Expand Up @@ -479,44 +478,6 @@ func TestTasksHandler(t *testing.T) {

}

func TestLicenseHandler(t *testing.T) {
var performMockRequest = func(t *testing.T, testCase IntrospectionTestCase[string]) *httptest.ResponseRecorder {
mockCtrl, mockAgentState, mockMetricsFactory, req, recorder := testHandlerSetup(t, testCase)
mockAgentState.EXPECT().
GetLicenseText().
Return(testCase.AgentResponse, testCase.Err)
if testCase.Err != nil {
mockEntry := mock_metrics.NewMockEntry(mockCtrl)
mockEntry.EXPECT().Done(testCase.Err)
mockMetricsFactory.EXPECT().
New(testCase.MetricName).Return(mockEntry)
}
LicenseHandler(mockAgentState, mockMetricsFactory)(recorder, req)
return recorder
}

t.Run("happy case", func(t *testing.T) {
recorder := performMockRequest(t, IntrospectionTestCase[string]{
Path: V1LicensePath,
AgentResponse: licenseText,
Err: nil,
})
assert.Equal(t, http.StatusOK, recorder.Code)
assert.Equal(t, licenseText, recorder.Body.String())
})

t.Run("internal error", func(t *testing.T) {
recorder := performMockRequest(t, IntrospectionTestCase[string]{
Path: V1LicensePath,
AgentResponse: "",
Err: errors.New(internalErrorText),
MetricName: metrics.IntrospectionInternalServerError,
})
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
assert.Equal(t, "", recorder.Body.String())
})
}

func TestGetErrorResponse(t *testing.T) {
t.Run("bad request error", func(t *testing.T) {
statusCode, metricName := getHTTPErrorCode(v1.NewErrorBadRequest(internalErrorText))
Expand Down

0 comments on commit 8ed0793

Please sign in to comment.