blob: 86ba097a37895c64de479e1dbe11226aac73fed9 [file] [log] [blame]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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 configfetcher
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/golang/glog"
"github.com/golang/protobuf/proto"
"policy-manager/protos"
)
// Tests that all metadata keys are parsed and applied correctly.
func TestGetUserConfigFromMetadata(t *testing.T) {
tests := []struct {
// Name of the test case
name string
// Key:Value pairs present in instance metadata.
instanceMetadata map[string]string
// Key:Value pairs present in project metadata.
projectMetadata map[string]string
// Expected InstanceConfig to be returned
expectedConfig *protos.InstanceConfig
}{
{
"NoMetadataKeys",
map[string]string{},
map[string]string{},
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"UpdateStrategyPresent",
map[string]string{gciKeyUpdateStrategy: "update-strategy-1"},
map[string]string{},
&protos.InstanceConfig{
UpdateStrategy: proto.String(""),
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"MultipleSettingsPresent",
map[string]string{
gciKeyUpdateStrategy: "update-strategy-2",
gciKeyMetricsEnabled: "true",
},
map[string]string{
gciKeyUpdateStrategy: "update_disabled",
},
&protos.InstanceConfig{
UpdateStrategy: proto.String(""),
MetricsEnabled: proto.Bool(true),
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"InvalidBoolValueIgnored",
map[string]string{
gciKeyMetricsEnabled: "no",
keyGoogleLoggingEnabled: "yes",
},
map[string]string{},
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"LegacyConfigKeyPresent",
map[string]string{
gciLegacyConfigKey: "{\"update_strategy\":\"update-strategy-3\"}",
gciKeyUpdateStrategy: "update-strategy-4",
},
map[string]string{},
&protos.InstanceConfig{
UpdateStrategy: proto.String("update-strategy-3"),
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"LoggingButIngoreMonitoring",
map[string]string{
keyGoogleLoggingEnabled: "true",
},
map[string]string{
keyGoogleLoggingEnabled: "false",
},
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
Enforced: proto.Bool(true),
LoggingEnabled: proto.Bool(true),
},
},
},
{
"MonitoringButIngoreLogging",
map[string]string{
keyGoogleMonitoringEnabled: "true",
},
map[string]string{
keyGoogleMonitoringEnabled: "false",
},
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
Enforced: proto.Bool(true),
MonitoringEnabled: proto.Bool(true),
},
},
},
{
"SpecifiedNoLogging",
map[string]string{
keyGoogleLoggingEnabled: "false",
},
map[string]string{
keyGoogleLoggingEnabled: "true",
},
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
LoggingEnabled: proto.Bool(false),
},
},
},
{
"LoggingAndMonitoring",
map[string]string{
keyGoogleMonitoringEnabled: "true",
},
map[string]string{
keyGoogleLoggingEnabled: "true",
},
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
Enforced: proto.Bool(true),
LoggingEnabled: proto.Bool(true),
MonitoringEnabled: proto.Bool(true),
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualConfig, err := getUserConfigFromMetadata(test.instanceMetadata, test.projectMetadata)
if err != nil {
t.Errorf("got unexpected error: %s", err)
}
if !proto.Equal(actualConfig, test.expectedConfig) {
t.Errorf("got %s, expect %s",
proto.MarshalTextString(actualConfig),
proto.MarshalTextString(test.expectedConfig))
}
})
}
}
// Tests that getUserConfig() calls metadata client and
// returns correct config settings.
func TestGetUserConfig(t *testing.T) {
tests := []struct {
// Name of the test case
name string
// The instance metadata returned by metatdata client
instanceMetadata string
// The project metadata returned by metatdata client
projectMetadata string
// The expected config settings to be returned
expectedConfig *protos.InstanceConfig
}{
{
"NoMetadata",
"{}",
"{}",
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"NormalUpdate",
`{
"cos-metrics-enabled": "true",
"cos-update-strategy": ""
}`,
`{
"cos-update-strategy": "update_disabled"
}`,
&protos.InstanceConfig{
UpdateStrategy: proto.String(""),
MetricsEnabled: proto.Bool(true),
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"MixedUpdate",
`{
"cos-update-strategy": "update_disabled",
"key1": "value1",
"kdy2": "value2"
}`,
`{
"cos-update-strategy": ""
}`,
&protos.InstanceConfig{
UpdateStrategy: proto.String("update_disabled"),
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"NoCosMetadataUpdate",
`{
"key1": "value1",
"kdy2": "value2"
}`,
`{
"key3": "value3"
}`,
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{},
},
},
{
"LoggingButNoMonitoring",
`{
"google-logging-enabled": "true",
"key1": "value1",
"kdy2": "value2"
}`,
`{
"google-monitoring-enabled": "false"
}`,
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
Enforced: proto.Bool(true),
LoggingEnabled: proto.Bool(true),
MonitoringEnabled: proto.Bool(false),
},
},
},
{
"MonitoringButIgnoreLogging",
`{
"google-monitoring-enabled": "true",
"key1": "value1",
"kdy2": "value2"
}`,
`{
"key3": "value3"
}`,
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
Enforced: proto.Bool(true),
MonitoringEnabled: proto.Bool(true),
},
},
},
{
"LoggingAndMonitoring",
`{
"google-logging-enabled": "true"
}`,
`{
"google-monitoring-enabled": "true"
}`,
&protos.InstanceConfig{
HealthMonitorConfig: &protos.HealthMonitorConfig{
Enforced: proto.Bool(true),
LoggingEnabled: proto.Bool(true),
MonitoringEnabled: proto.Bool(true),
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// Set up a test server.
instanceHandler := func(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte(test.instanceMetadata)); err != nil {
glog.Errorf("write %q failed: %v", r.URL.Path, err)
}
}
projectHandler := func(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte(test.projectMetadata)); err != nil {
glog.Errorf("write %q failed: %v", r.URL.Path, err)
}
}
mux := http.NewServeMux()
mux.HandleFunc("/instance/attributes/", instanceHandler)
mux.HandleFunc("/project/attributes/", projectHandler)
ts := httptest.NewServer(mux)
actualConfig, _, _, err := getUserConfig("", "", ts.URL)
if err != nil {
t.Errorf("got unexpected error: %s", err)
}
if !proto.Equal(actualConfig, test.expectedConfig) {
t.Errorf("FAILED '%s': got %s, expect %s",
test.name,
proto.MarshalTextString(actualConfig),
proto.MarshalTextString(test.expectedConfig))
}
})
}
}