Skip to content

Commit cdb90ec

Browse files
committed
tags fixes and add support for filter name prefix
1 parent 49a0c57 commit cdb90ec

File tree

8 files changed

+145
-52
lines changed

8 files changed

+145
-52
lines changed

cluster-autoscaler/cloudprovider/kamatera/README.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,19 @@ You can see an example of the cloud config file at [examples/deployment.yaml](ex
3030

3131
it is an INI file with the following fields:
3232

33-
| Key | Value | Mandatory | Default |
34-
|-----|-------|-----------|---------|
35-
| global/kamatera-api-client-id | Kamatera API Client ID | yes | none |
36-
| global/kamatera-api-secret | Kamatera API Secret | yes | none |
37-
| global/cluster-name | **max 15 characters: english letters, numbers, dash, underscore, space, dot**: distinct string used to set the cluster server tag | yes | none |
38-
| global/default-min-size | default minimum size of a node group (must be > 0) | no | 1 |
39-
| global/default-max-size | default maximum size of a node group | no | 254 |
40-
| global/default-<SERVER_CONFIG_KEY> | replace <SERVER_CONFIG_KEY> with the relevant configuration key | see below | see below |
41-
| nodegroup \"name\" | **max 15 characters: english letters, numbers, dash, underscore, space, dot**: distinct string within the cluster used to set the node group server tag | yes | none |
42-
| nodegroup \"name\"/min-size | minimum size for a specific node group | no | global/defaut-min-size |
43-
| nodegroup \"name\"/max-size | maximum size for a specific node group | no | global/defaut-min-size |
44-
| nodegroup \"name\"/<SERVER_CONFIG_KEY> | replace <SERVER_CONFIG_KEY> with the relevant configuration key | no | global/default-<SERVER_CONFIG_KEY> |
33+
| Key | Value | Mandatory | Default |
34+
|----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|------------------------------------|
35+
| global/kamatera-api-client-id | Kamatera API Client ID | yes | none |
36+
| global/kamatera-api-secret | Kamatera API Secret | yes | none |
37+
| global/cluster-name | **max 15 characters: english letters, numbers, dash, underscore, space, dot**: distinct string used to set the cluster server tag | yes | none |
38+
| global/filter-name-prefix | autoscaler will only handle server names that start with this prefix | no | none |
39+
| global/default-min-size | default minimum size of a node group (must be > 0) | no | 1 |
40+
| global/default-max-size | default maximum size of a node group | no | 254 |
41+
| global/default-<SERVER_CONFIG_KEY> | replace <SERVER_CONFIG_KEY> with the relevant configuration key | see below | see below |
42+
| nodegroup \"name\" | **max 15 characters: english letters, numbers, dash, underscore, space, dot**: distinct string within the cluster used to set the node group server tag | yes | none |
43+
| nodegroup \"name\"/min-size | minimum size for a specific node group | no | global/defaut-min-size |
44+
| nodegroup \"name\"/max-size | maximum size for a specific node group | no | global/defaut-min-size |
45+
| nodegroup \"name\"/<SERVER_CONFIG_KEY> | replace <SERVER_CONFIG_KEY> with the relevant configuration key | no | global/default-<SERVER_CONFIG_KEY> |
4546

4647
### Server configuration keys
4748

cluster-autoscaler/cloudprovider/kamatera/kamatera_api_client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222

2323
// kamateraAPIClient is the interface used to call kamatera API
2424
type kamateraAPIClient interface {
25-
ListServers(ctx context.Context, instances map[string]*Instance) ([]Server, error)
25+
ListServers(ctx context.Context, instances map[string]*Instance, namePrefix string) ([]Server, error)
2626
DeleteServer(ctx context.Context, name string) error
2727
CreateServers(ctx context.Context, count int, config ServerConfig) ([]Server, error)
2828
}

cluster-autoscaler/cloudprovider/kamatera/kamatera_api_client_rest.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ type KamateraApiClientRest struct {
8282
}
8383

8484
// ListServers returns a list of all servers in the relevant account and fetches their tags
85-
func (c *KamateraApiClientRest) ListServers(ctx context.Context, instances map[string]*Instance) ([]Server, error) {
85+
func (c *KamateraApiClientRest) ListServers(ctx context.Context, instances map[string]*Instance, namePrefix string) ([]Server, error) {
8686
res, err := request(
8787
ctx,
8888
ProviderConfig{ApiUrl: c.url, ApiClientID: c.clientId, ApiSecret: c.secret},
@@ -97,16 +97,18 @@ func (c *KamateraApiClientRest) ListServers(ctx context.Context, instances map[s
9797
for _, server := range res.([]interface{}) {
9898
server := server.(map[string]interface{})
9999
serverName := server["name"].(string)
100-
serverPowerOn := server["power"].(string) == "on"
101-
serverTags, err := c.getServerTags(ctx, serverName, instances)
102-
if err != nil {
103-
return nil, err
100+
if len(namePrefix) == 0 || strings.HasPrefix(serverName, namePrefix) {
101+
serverPowerOn := server["power"].(string) == "on"
102+
serverTags, err := c.getServerTags(ctx, serverName, instances)
103+
if err != nil {
104+
return nil, err
105+
}
106+
servers = append(servers, Server{
107+
Name: serverName,
108+
Tags: serverTags,
109+
PowerOn: serverPowerOn,
110+
})
104111
}
105-
servers = append(servers, Server{
106-
Name: serverName,
107-
Tags: serverTags,
108-
PowerOn: serverPowerOn,
109-
})
110112
}
111113
return servers, nil
112114
}
@@ -235,7 +237,7 @@ func (c *KamateraApiClientRest) getServerTags(ctx context.Context, serverName st
235237
if err != nil {
236238
return nil, err
237239
}
238-
var tags []string
240+
tags := make([]string, 0)
239241
for _, row := range res.([]interface{}) {
240242
row := row.(map[string]interface{})
241243
tags = append(tags, row["tag name"].(string))

cluster-autoscaler/cloudprovider/kamatera/kamatera_api_client_rest_test.go

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestApiClientRest_ListServers_NoServers(t *testing.T) {
4040
"application/json",
4141
`[]`,
4242
).Once()
43-
servers, err := client.ListServers(ctx, map[string]*Instance{})
43+
servers, err := client.ListServers(ctx, map[string]*Instance{}, "")
4444
assert.NoError(t, err)
4545
assert.Equal(t, 0, len(servers))
4646
mock.AssertExpectationsForObjects(t, server)
@@ -54,13 +54,15 @@ func TestApiClientRest_ListServers(t *testing.T) {
5454
newServerName1 := mockKamateraServerName()
5555
cachedServerName2 := mockKamateraServerName()
5656
cachedServerName3 := mockKamateraServerName()
57+
cachedServerName4 := mockKamateraServerName()
5758
server.On("handle", "/service/servers").Return(
5859
"application/json",
5960
fmt.Sprintf(`[
6061
{"name": "%s", "power": "on"},
6162
{"name": "%s", "power": "on"},
62-
{"name": "%s", "power": "off"}
63-
]`, newServerName1, cachedServerName2, cachedServerName3),
63+
{"name": "%s", "power": "off"},
64+
{"name": "%s", "power": "on"}
65+
]`, newServerName1, cachedServerName2, cachedServerName3, cachedServerName4),
6466
).On("handle", "/server/tags").Return(
6567
"application/json",
6668
`[{"tag name": "test-tag"}, {"tag name": "other-test-tag"}]`,
@@ -78,9 +80,15 @@ func TestApiClientRest_ListServers(t *testing.T) {
7880
PowerOn: true,
7981
Tags: []string{"another-tag", "my-other-tag"},
8082
},
81-
})
83+
cachedServerName4: {
84+
Id: cachedServerName4,
85+
Status: &cloudprovider.InstanceStatus{State: cloudprovider.InstanceRunning},
86+
PowerOn: true,
87+
Tags: []string{},
88+
},
89+
}, "")
8290
assert.NoError(t, err)
83-
assert.Equal(t, 3, len(servers))
91+
assert.Equal(t, 4, len(servers))
8492
assert.Equal(t, servers, []Server{
8593
{
8694
Name: newServerName1,
@@ -97,10 +105,85 @@ func TestApiClientRest_ListServers(t *testing.T) {
97105
Tags: []string{"another-tag", "my-other-tag"},
98106
PowerOn: false,
99107
},
108+
{
109+
Name: cachedServerName4,
110+
Tags: []string{},
111+
PowerOn: true,
112+
},
113+
})
114+
mock.AssertExpectationsForObjects(t, server)
115+
}
116+
117+
func TestApiClientRest_ListServersNamePrefix(t *testing.T) {
118+
server := NewHttpServerMock(MockFieldContentType, MockFieldResponse)
119+
defer server.Close()
120+
ctx := context.Background()
121+
client := NewKamateraApiClientRest(mockKamateraClientId, mockKamateraSecret, server.URL)
122+
newServerName1 := "prefixa" + mockKamateraServerName()
123+
newServerName2 := "prefixb" + mockKamateraServerName()
124+
server.On("handle", "/service/servers").Return(
125+
"application/json",
126+
fmt.Sprintf(`[
127+
{"name": "%s", "power": "on"},
128+
{"name": "%s", "power": "on"}
129+
]`, newServerName1, newServerName2),
130+
).On("handle", "/server/tags").Return(
131+
"application/json",
132+
`[{"tag name": "test-tag"}, {"tag name": "other-test-tag"}]`,
133+
)
134+
servers, err := client.ListServers(ctx, map[string]*Instance{}, "prefixb")
135+
assert.NoError(t, err)
136+
assert.Equal(t, 1, len(servers))
137+
assert.Equal(t, servers, []Server{
138+
{
139+
Name: newServerName2,
140+
Tags: []string{"test-tag", "other-test-tag"},
141+
PowerOn: true,
142+
},
143+
})
144+
mock.AssertExpectationsForObjects(t, server)
145+
}
146+
147+
func TestApiClientRest_ListServersNoTags(t *testing.T) {
148+
server := NewHttpServerMock(MockFieldContentType, MockFieldResponse)
149+
defer server.Close()
150+
ctx := context.Background()
151+
client := NewKamateraApiClientRest(mockKamateraClientId, mockKamateraSecret, server.URL)
152+
newServerName1 := mockKamateraServerName()
153+
server.On("handle", "/service/servers").Return(
154+
"application/json", fmt.Sprintf(`[{"name": "%s", "power": "on"}]`, newServerName1),
155+
).On("handle", "/server/tags").Return(
156+
"application/json", `[]`,
157+
)
158+
servers, err := client.ListServers(ctx, map[string]*Instance{}, "")
159+
assert.NoError(t, err)
160+
assert.Equal(t, 1, len(servers))
161+
assert.Equal(t, servers, []Server{
162+
{
163+
Name: newServerName1,
164+
Tags: []string{},
165+
PowerOn: true,
166+
},
100167
})
101168
mock.AssertExpectationsForObjects(t, server)
102169
}
103170

171+
func TestApiClientRest_ListServersTagsError(t *testing.T) {
172+
server := NewHttpServerMock(MockFieldContentType, MockFieldResponse, MockFieldStatusCode)
173+
defer server.Close()
174+
ctx := context.Background()
175+
client := NewKamateraApiClientRest(mockKamateraClientId, mockKamateraSecret, server.URL)
176+
newServerName1 := mockKamateraServerName()
177+
server.On("handle", "/service/servers").Return(
178+
"application/json", fmt.Sprintf(`[{"name": "%s", "power": "on"}]`, newServerName1), 200,
179+
).On("handle", "/server/tags").Return(
180+
"application/json", `{"message":"Failed to run command method (serverTags)"}`, 500,
181+
)
182+
servers, err := client.ListServers(ctx, map[string]*Instance{}, "")
183+
assert.Error(t, err)
184+
assert.Nil(t, servers)
185+
}
186+
104187
func TestApiClientRest_DeleteServer(t *testing.T) {
105188
server := NewHttpServerMock(MockFieldContentType, MockFieldResponse)
106189
defer server.Close()

cluster-autoscaler/cloudprovider/kamatera/kamatera_cloud_config.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ type nodeGroupConfig struct {
5252

5353
// kamateraConfig holds the configuration for the Kamatera provider.
5454
type kamateraConfig struct {
55-
apiClientId string
56-
apiSecret string
57-
apiUrl string
58-
clusterName string
59-
defaultMinSize int
60-
defaultMaxSize int
61-
nodeGroupCfg map[string]*nodeGroupConfig // key is the node group name
55+
apiClientId string
56+
apiSecret string
57+
apiUrl string
58+
clusterName string
59+
filterNamePrefix string
60+
defaultMinSize int
61+
defaultMaxSize int
62+
nodeGroupCfg map[string]*nodeGroupConfig // key is the node group name
6263
}
6364

6465
// GcfgGlobalConfig is the gcfg representation of the global section in the cloud config file for Kamatera.
@@ -67,6 +68,7 @@ type GcfgGlobalConfig struct {
6768
KamateraApiSecret string `gcfg:"kamatera-api-secret"`
6869
KamateraApiUrl string `gcfg:"kamatera-api-url"`
6970
ClusterName string `gcfg:"cluster-name"`
71+
FilterNamePrefix string `gcfg:"filter-name-prefix"`
7072
DefaultMinSize string `gcfg:"default-min-size"`
7173
DefaultMaxSize string `gcfg:"default-max-size"`
7274
DefaultNamePrefix string `gcfg:"default-name-prefix"`
@@ -143,6 +145,8 @@ func buildCloudConfig(config io.Reader) (*kamateraConfig, error) {
143145
return nil, fmt.Errorf("cluster name must be at most 15 characters long")
144146
}
145147

148+
filterNamePrefix := gcfgCloudConfig.Global.FilterNamePrefix
149+
146150
// get the default min and max size as defined in the global section of the config file
147151
defaultMinSize, defaultMaxSize, err := getSizeLimits(
148152
gcfgCloudConfig.Global.DefaultMinSize,
@@ -242,13 +246,14 @@ func buildCloudConfig(config io.Reader) (*kamateraConfig, error) {
242246
}
243247

244248
return &kamateraConfig{
245-
clusterName: clusterName,
246-
apiClientId: apiClientId,
247-
apiSecret: apiSecret,
248-
apiUrl: apiUrl,
249-
defaultMinSize: defaultMinSize,
250-
defaultMaxSize: defaultMaxSize,
251-
nodeGroupCfg: nodeGroupCfg,
249+
clusterName: clusterName,
250+
apiClientId: apiClientId,
251+
apiSecret: apiSecret,
252+
apiUrl: apiUrl,
253+
filterNamePrefix: filterNamePrefix,
254+
defaultMinSize: defaultMinSize,
255+
defaultMaxSize: defaultMaxSize,
256+
nodeGroupCfg: nodeGroupCfg,
252257
}, nil
253258
}
254259

cluster-autoscaler/cloudprovider/kamatera/kamatera_manager.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func (m *manager) refresh() error {
6363
servers, err := m.client.ListServers(
6464
context.Background(),
6565
m.instances,
66+
m.config.filterNamePrefix,
6667
)
6768
if err != nil {
6869
return fmt.Errorf("failed to get list of Kamatera servers from Kamatera API: %v", err)

cluster-autoscaler/cloudprovider/kamatera/kamatera_manager_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func TestManager_refresh(t *testing.T) {
4949
kamatera-api-client-id=1a222bbb3ccc44d5555e6ff77g88hh9i
5050
kamatera-api-secret=9ii88h7g6f55555ee4444444dd33eee2
5151
cluster-name=aaabbb
52+
filter-name-prefix=myprefix
5253
default-datacenter=IL
5354
default-image=ubuntu
5455
default-cpu=1a
@@ -72,12 +73,12 @@ max-size=5
7273
m.client = &client
7374
ctx := context.Background()
7475

75-
serverName1 := mockKamateraServerName()
76-
serverName2 := mockKamateraServerName()
77-
serverName3 := mockKamateraServerName()
78-
serverName4 := mockKamateraServerName()
76+
serverName1 := "myprefix" + mockKamateraServerName()
77+
serverName2 := "myprefix" + mockKamateraServerName()
78+
serverName3 := "myprefix" + mockKamateraServerName()
79+
serverName4 := "myprefix" + mockKamateraServerName()
7980
client.On(
80-
"ListServers", ctx, m.instances,
81+
"ListServers", ctx, m.instances, "myprefix",
8182
).Return(
8283
[]Server{
8384
{Name: serverName1, Tags: []string{fmt.Sprintf("%s%s", clusterServerTagPrefix, "aaabbb"), fmt.Sprintf("%s%s", nodeGroupTagPrefix, "ng1")}},
@@ -95,7 +96,7 @@ max-size=5
9596

9697
// test api error
9798
client.On(
98-
"ListServers", ctx, m.instances,
99+
"ListServers", ctx, m.instances, "myprefix",
99100
).Return(
100101
[]Server{},
101102
fmt.Errorf("error on API call"),
@@ -143,7 +144,7 @@ cluster-name=aaabbb
143144
ctx := context.Background()
144145
serverName1 := mockKamateraServerName()
145146
client.On(
146-
"ListServers", ctx, m.instances,
147+
"ListServers", ctx, m.instances, "",
147148
).Return(
148149
[]Server{
149150
{Name: serverName1, Tags: []string{fmt.Sprintf("%s%s", clusterServerTagPrefix, "aaabbb"), fmt.Sprintf("%s%s", nodeGroupTagPrefix, "ng1")}},

cluster-autoscaler/cloudprovider/kamatera/kamatera_utils_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ func (c *kamateraClientMock) SetBaseURL(baseURL string) {
5656
c.Called(baseURL)
5757
}
5858

59-
func (c *kamateraClientMock) ListServers(ctx context.Context, instances map[string]*Instance) ([]Server, error) {
60-
args := c.Called(ctx, instances)
59+
func (c *kamateraClientMock) ListServers(ctx context.Context, instances map[string]*Instance, namePrefix string) ([]Server, error) {
60+
args := c.Called(ctx, instances, namePrefix)
6161
return args.Get(0).([]Server), args.Error(1)
6262
}
6363

0 commit comments

Comments
 (0)