/
metadata_handler.go
139 lines (119 loc) · 6.66 KB
/
metadata_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2019 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"
"net/http"
"github.com/awslabs/amazon-ecs-local-container-endpoints/local-container-endpoints/clients/docker"
"github.com/awslabs/amazon-ecs-local-container-endpoints/local-container-endpoints/config"
"github.com/gorilla/mux"
)
// MetadataService vends docker metadata to containers
type MetadataService struct {
dockerClient docker.Client
baseTaskMetadata map[string]interface{}
baseContainerMetadata map[string]interface{}
containerInstanceTags map[string]string
taskTags map[string]string
}
// NewMetadataService returns a struct that handles metadata requests
func NewMetadataService(taskMetadata, contMetadata map[string]interface{}) (*MetadataService, error) {
dockerClient, err := docker.NewDockerClient()
if err != nil {
return nil, err
}
return NewMetadataServiceWithClient(dockerClient, taskMetadata, contMetadata)
}
// NewMetadataServiceWithClient returns a struct that handles metadata requests using the given Docker Client
func NewMetadataServiceWithClient(dockerClient docker.Client, taskMetadata, contMetadata map[string]interface{}) (*MetadataService, error) {
metadata := &MetadataService{
dockerClient: dockerClient,
}
metadata.baseContainerMetadata = contMetadata
metadata.baseTaskMetadata = taskMetadata
// TODO: re-enable tagging when supporting the new V2 and V3 metdata with Tags paths
// if ciTagVal := os.Getenv(config.ContainerInstanceTagsVar); ciTagVal != "" {
// tags, err := utils.GetTagsMap(ciTagVal)
// if err != nil {
// return nil, err
// }
// metadata.containerInstanceTags = tags
// }
//
// if taskTagVal := os.Getenv(config.TaskTagsVar); taskTagVal != "" {
// tags, err := utils.GetTagsMap(taskTagVal)
// if err != nil {
// return nil, err
// }
// metadata.taskTags = tags
// }
return metadata, nil
}
// SetupV2Routes sets up the V2 Metadata routes
func (service *MetadataService) SetupV2Routes(router *mux.Router) {
router.HandleFunc(config.V2TaskMetadataPath, ServeHTTP(service.getMetadataHandler(requestTypeTaskMetadata)))
router.HandleFunc(config.V2TaskMetadataPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeTaskMetadata)))
router.HandleFunc(config.V2TaskStatsPath, ServeHTTP(service.getMetadataHandler(requestTypeTaskStats)))
router.HandleFunc(config.V2TaskStatsPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeTaskStats)))
router.HandleFunc(config.V2ContainerMetadataPath, ServeHTTP(service.getMetadataHandler(requestTypeContainerMetadata)))
router.HandleFunc(config.V2ContainerMetadataPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeContainerMetadata)))
router.HandleFunc(config.V2ContainerStatsPath, ServeHTTP(service.getMetadataHandler(requestTypeContainerStats)))
router.HandleFunc(config.V2ContainerStatsPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeContainerStats)))
}
// SetupV3Routes sets up the V3 Metadata routes
func (service *MetadataService) SetupV3Routes(router *mux.Router) {
router.HandleFunc(config.V3ContainerMetadataPath, ServeHTTP(service.getMetadataHandler(requestTypeContainerMetadata)))
router.HandleFunc(config.V3ContainerMetadataPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeContainerMetadata)))
router.HandleFunc(config.V3ContainerMetadataPathWithIdentifier, ServeHTTP(service.getMetadataHandler(requestTypeContainerMetadata)))
router.HandleFunc(config.V3ContainerMetadataPathWithIdentifierAndSlash, ServeHTTP(service.getMetadataHandler(requestTypeContainerMetadata)))
router.HandleFunc(config.V3ContainerStatsPath, ServeHTTP(service.getMetadataHandler(requestTypeContainerStats)))
router.HandleFunc(config.V3ContainerStatsPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeContainerStats)))
router.HandleFunc(config.V3ContainerStatsPathWithIdentifier, ServeHTTP(service.getMetadataHandler(requestTypeContainerStats)))
router.HandleFunc(config.V3ContainerStatsPathWithIdentifierAndSlash, ServeHTTP(service.getMetadataHandler(requestTypeContainerStats)))
router.HandleFunc(config.V3TaskMetadataPath, ServeHTTP(service.getMetadataHandler(requestTypeTaskMetadata)))
router.HandleFunc(config.V3TaskMetadataPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeTaskMetadata)))
router.HandleFunc(config.V3TaskMetadataPathWithIdentifier, ServeHTTP(service.getMetadataHandler(requestTypeTaskMetadata)))
router.HandleFunc(config.V3TaskMetadataPathWithIdentifierWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeTaskMetadata)))
router.HandleFunc(config.V3TaskStatsPath, ServeHTTP(service.getMetadataHandler(requestTypeTaskStats)))
router.HandleFunc(config.V3TaskStatsPathWithSlash, ServeHTTP(service.getMetadataHandler(requestTypeTaskStats)))
router.HandleFunc(config.V3TaskStatsPathWithIdentifier, ServeHTTP(service.getMetadataHandler(requestTypeTaskStats)))
router.HandleFunc(config.V3TaskStatsPathWithIdentifierAndSlash, ServeHTTP(service.getMetadataHandler(requestTypeTaskStats)))
}
// getMetadataHandler returns a metadata handler given a requestType
func (service *MetadataService) getMetadataHandler(requestType int) func(w http.ResponseWriter, r *http.Request) error {
return func(w http.ResponseWriter, r *http.Request) error {
callerIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
// Failed to get the callerIP
callerIP = ""
}
vars := mux.Vars(r)
identifier := vars["identifier"]
return service.handleRequest(requestType, w, identifier, callerIP)
}
}
func (service *MetadataService) handleRequest(requestType int, w http.ResponseWriter, identifier string, callerIP string) error {
switch requestType {
case requestTypeTaskMetadata:
return service.taskMetadataResponse(w, identifier, callerIP)
case requestTypeTaskStats:
return service.taskStatsResponse(w, identifier, callerIP)
case requestTypeContainerStats:
return service.containerStatsResponse(w, identifier, callerIP)
case requestTypeContainerMetadata:
return service.containerMetadataResponse(w, identifier, callerIP)
}
// This should never run, but explicitly returning an error here helps make it easy to find bugs
return fmt.Errorf("There's a bug in this code: Invalid request type %d", requestType)
}