-
Notifications
You must be signed in to change notification settings - Fork 44
/
cmdutil.go
133 lines (115 loc) · 4.21 KB
/
cmdutil.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
// Copyright 2020 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 cmdutil
import (
"fmt"
"strings"
"time"
cfg "github.com/aws/amazon-ec2-metadata-mock/pkg/config"
e "github.com/aws/amazon-ec2-metadata-mock/pkg/error"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/dynamic"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/events"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/handlers"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/imdsv2"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/spot"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/static"
"github.com/aws/amazon-ec2-metadata-mock/pkg/mock/userdata"
"github.com/aws/amazon-ec2-metadata-mock/pkg/server"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
// BinName is the name of this tool's binary
const BinName = "ec2-metadata-mock"
// handlerPair holds a tuple of a path and its associated handler
type handlerPair struct {
path string
handler server.HandlerType
}
// Contains finds a string in the given array
func Contains(slice []string, val string) bool {
for _, item := range slice {
if item == val {
return true
}
}
return false
}
// PrintFlags prints all flags of a command, if set
func PrintFlags(flags *pflag.FlagSet) {
f := make(map[string]interface{})
flags.Visit(func(flag *pflag.Flag) {
f[flag.Name] = flag.Value
})
if len(f) > 0 {
fmt.Println("\nFlags:")
for key, value := range f {
fmt.Printf("%s: %s\n", key, value)
}
fmt.Println()
}
}
// ValidateRFC3339TimeFormat validates an input time matches RFC3339 format
func ValidateRFC3339TimeFormat(flagName string, input string) error {
if _, err := time.Parse(time.RFC3339, input); err != nil {
return e.FlagValidationError{
FlagName: flagName,
Allowed: "time in RFC3339 format, e.g. 2020-01-07T01:03:47Z",
InvalidValue: input}
}
return nil
}
// RegisterHandlers binds paths to handlers for ALL commands
func RegisterHandlers(cmd *cobra.Command, config cfg.Config) {
handlerPairsToRegister := getHandlerPairs(cmd, config)
for _, handlerPair := range handlerPairsToRegister {
if config.Imdsv2Required {
server.HandleFunc(handlerPair.path, imdsv2.ValidateToken(handlerPair.handler))
} else {
server.HandleFunc(handlerPair.path, handlerPair.handler)
}
}
static.RegisterHandlers(config)
dynamic.RegisterHandlers(config)
userdata.RegisterHandlers(config)
// paths without explicit handler bindings will fallback to CatchAllHandler
server.HandleFuncPrefix("/", handlers.CatchAllHandler)
}
// getHandlerPairs returns a slice of {paths, handlers} to register
func getHandlerPairs(cmd *cobra.Command, config cfg.Config) []handlerPair {
// always register these paths
handlerPairs := []handlerPair{
{path: "/", handler: handlers.ListRoutesHandler},
{path: "/latest", handler: handlers.ListRoutesHandler},
{path: static.ServicePath, handler: handlers.ListRoutesHandler},
{path: dynamic.ServicePath, handler: handlers.ListRoutesHandler},
}
isSpot := strings.Contains(cmd.Name(), "spot")
isEvents := strings.Contains(cmd.Name(), "events")
subCommandHandlers := map[string][]handlerPair{
"spot": {{path: config.Metadata.Paths.Spot, handler: spot.Handler},
{path: config.Metadata.Paths.SpotTerminationTime, handler: spot.Handler},
{path: config.Metadata.Paths.RebalanceRecTime, handler: spot.Handler}},
"events": {{path: config.Metadata.Paths.Events, handler: events.Handler}},
}
if isSpot {
handlerPairs = append(handlerPairs, subCommandHandlers["spot"]...)
} else if isEvents {
handlerPairs = append(handlerPairs, subCommandHandlers["events"]...)
} else {
// root registers all subcommands
for k := range subCommandHandlers {
handlerPairs = append(handlerPairs, subCommandHandlers[k]...)
}
}
return handlerPairs
}