| package config |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| import ( |
| "encoding/json" |
| "flag" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "strings" |
| "testing" |
| ) |
| |
| const ( |
| logError = "/var/log/traffic_ops/error.log" |
| logWarning = "/var/log/traffic_ops/warning.log" |
| logInfo = "/var/log/traffic_ops/info.log" |
| logDebug = "/var/log/traffic_ops/debug.log" |
| logEvent = "/var/log/traffic_ops/event.log" |
| ) |
| |
| var debugLogging = flag.Bool("debug", false, "enable debug logging in test") |
| |
| var cfg = Config{ |
| URL: nil, |
| ConfigHypnotoad: ConfigHypnotoad{}, |
| ConfigTrafficOpsGolang: ConfigTrafficOpsGolang{ |
| LogLocationError: logError, |
| LogLocationWarning: logWarning, |
| LogLocationInfo: logInfo, |
| LogLocationDebug: logDebug, |
| LogLocationEvent: logEvent, |
| }, |
| DB: ConfigDatabase{}, |
| Secrets: []string{}, |
| } |
| |
| func TestLogLocation(t *testing.T) { |
| if cfg.ErrorLog() != logError { |
| t.Error("ErrorLog should be ", logError) |
| } |
| if cfg.WarningLog() != logWarning { |
| t.Error("WarningLog should be ", logWarning) |
| } |
| if cfg.InfoLog() != logInfo { |
| t.Error("InfoLog should be ", logInfo) |
| } |
| if cfg.DebugLog() != logDebug { |
| t.Error("DebugLog should be ", logDebug) |
| } |
| if cfg.EventLog() != logEvent { |
| t.Error("EventLog should be ", logEvent) |
| } |
| } |
| |
| func tempFileWith(content []byte) (string, error) { |
| tmpfile, err := ioutil.TempFile("", "badcdn.conf") |
| if err != nil { |
| return "", err |
| } |
| if _, err := tmpfile.Write(content); err != nil { |
| return "", err |
| } |
| if err := tmpfile.Close(); err != nil { |
| return "", err |
| } |
| return tmpfile.Name(), nil |
| } |
| |
| const ( |
| goodConfig = ` |
| { |
| "hypnotoad" : { |
| "listen" : [ |
| "https://[::]:60443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED" |
| ], |
| "user" : "trafops", |
| "group" : "trafops", |
| "heartbeat_timeout" : 20, |
| "pid_file" : "/var/run/traffic_ops.pid", |
| "workers" : 12 |
| }, |
| "user_cache_refresh_interval_sec": 30, |
| "server_update_status_cache_refresh_interval_sec": 15, |
| "disable_auto_cert_deletion": true, |
| "traffic_ops_golang" : { |
| "port" : "443", |
| "proxy_timeout" : 60, |
| "proxy_keep_alive" : 60, |
| "proxy_tls_timeout" : 60, |
| "proxy_read_header_timeout" : 60, |
| "read_timeout" : 60, |
| "read_header_timeout" : 60, |
| "write_timeout" : 60, |
| "idle_timeout" : 60, |
| "routing_blacklist": { |
| "ignore_unknown_routes": true, |
| "disabled_routes": [4, 5, 6] |
| }, |
| "traffic_vault_backend": "something", |
| "traffic_vault_config": { |
| "foo": "bar" |
| }, |
| "log_location_error": "stderr", |
| "log_location_warning": "stdout", |
| "log_location_info": "stdout", |
| "log_location_debug": "stdout", |
| "log_location_event": "access.log" |
| }, |
| "cors" : { |
| "access_control_allow_origin" : "*" |
| }, |
| "to" : { |
| "base_url" : "http://localhost:3000", |
| "email_from" : "no-reply@traffic-ops-domain.com", |
| "no_account_found_msg" : "A Traffic Ops user account is required for access. Please contact your Traffic Ops user administrator." |
| }, |
| "portal" : { |
| "base_url" : "http://localhost:8080/!#/", |
| "email_from" : "no-reply@traffic-portal-domain.com", |
| "pass_reset_path" : "user", |
| "user_register_path" : "user" |
| }, |
| "secrets" : [ |
| "mONKEYDOmONKEYSEE." |
| ], |
| "inactivity_timeout" : 60 |
| } |
| ` |
| |
| goodDbConfig = ` |
| { |
| "description": "Local PostgreSQL database on port 5432", |
| "dbname": "traffic_ops", |
| "hostname": "localhost", |
| "user": "traffic_ops", |
| "password": "password", |
| "port": "5432", |
| "type": "Pg" |
| } |
| ` |
| ) |
| |
| func TestLoadConfig(t *testing.T) { |
| var err error |
| var exp string |
| version := "Test Version" |
| |
| // set up config paths |
| badPath := "/invalid-path/no-file-exists-here" |
| badCfg, err := tempFileWith([]byte("no way this is valid json...")) |
| if err != nil { |
| t.Errorf("cannot create temp file: %v", err) |
| } |
| defer os.Remove(badCfg) // clean up |
| |
| goodCfg, err := tempFileWith([]byte(goodConfig)) |
| if err != nil { |
| t.Errorf("cannot create temp file: %v", err) |
| } |
| defer os.Remove(goodCfg) // clean up |
| |
| goodDbCfg, err := tempFileWith([]byte(goodDbConfig)) |
| if err != nil { |
| t.Errorf("cannot create temp file: %v", err) |
| } |
| defer os.Remove(goodDbCfg) // clean up |
| |
| // test bad paths |
| _, errs, blockStartup := LoadConfig(badPath, badPath, version) |
| exp = fmt.Sprintf("Loading cdn config from '%s'", badPath) |
| if !strings.HasPrefix(errs[0].Error(), exp) { |
| t.Error("expected", exp, "got", errs[0].Error()) |
| } |
| if blockStartup != true { |
| t.Error("expected blockStartup to be true but it was ", blockStartup) |
| } |
| |
| // bad json in cdn.conf |
| _, errs, blockStartup = LoadConfig(badCfg, badCfg, version) |
| exp = fmt.Sprintf("Loading cdn config from '%s': unmarshalling '%s'", badCfg, badCfg) |
| if !strings.HasPrefix(errs[0].Error(), exp) { |
| t.Error("expected", exp, "got", errs[0].Error()) |
| } |
| if blockStartup != true { |
| t.Error("expected blockStartup to be true but it was ", blockStartup) |
| } |
| |
| // good cdn.conf, bad db conf |
| _, errs, blockStartup = LoadConfig(goodCfg, badPath, version) |
| exp = fmt.Sprintf("reading db conf '%s'", badPath) |
| if !strings.HasPrefix(errs[0].Error(), exp) { |
| t.Error("expected", exp, "got", errs[0].Error()) |
| } |
| if blockStartup != true { |
| t.Error("expected blockStartup to be true but it was ", blockStartup) |
| } |
| |
| // good cdn.conf, bad json in database.conf |
| _, errs, blockStartup = LoadConfig(goodCfg, badCfg, version) |
| exp = fmt.Sprintf("unmarshalling '%s'", badCfg) |
| if !strings.HasPrefix(errs[0].Error(), exp) { |
| t.Error("expected", exp, "got", errs[0].Error()) |
| } |
| if blockStartup != true { |
| t.Error("expected blockStartup to be true but it was ", blockStartup) |
| } |
| |
| // good cdn.conf, good database.conf |
| cfg, errs, blockStartup = LoadConfig(goodCfg, goodDbCfg, version) |
| if len(errs) != 0 { |
| t.Error("Good config -- unexpected errors: ", errs) |
| } |
| if blockStartup != false { |
| t.Error("expected blockStartup to be false but it was ", blockStartup) |
| } |
| if !cfg.DisableAutoCertDeletion { |
| t.Errorf("expected disable_auto_cert_deletion to be true, actual: false") |
| } |
| |
| if cfg.TrafficVaultBackend != "something" { |
| t.Errorf("expected traffic_vault_backend to be 'something', actual: '%s'", cfg.TrafficVaultBackend) |
| } |
| if cfg.UserCacheRefreshIntervalSec != 30 { |
| t.Errorf("expected user_cache_refresh_interval_sec: 30, actual: %d", cfg.UserCacheRefreshIntervalSec) |
| } |
| if cfg.ServerUpdateStatusCacheRefreshIntervalSec != 15 { |
| t.Errorf("expected server_update_status_cache_refresh_interval_sec: 15, actual: %d", cfg.ServerUpdateStatusCacheRefreshIntervalSec) |
| } |
| tvConfig := make(map[string]string) |
| err = json.Unmarshal(cfg.TrafficVaultConfig, &tvConfig) |
| if err != nil { |
| t.Errorf("unmarshalling traffic_vault_config - expected: no error, actual: %s", err.Error()) |
| } |
| if tvConfig["foo"] != "bar" { |
| t.Errorf("unmarshalling traffic_vault_config - expected: foo = bar, actual: foo = %s", tvConfig["foo"]) |
| } |
| |
| if *debugLogging { |
| fmt.Printf("Cfg: %+v\n", cfg) |
| } |
| |
| if cfg.CertPath != "/etc/pki/tls/certs/localhost.crt" { |
| t.Error("Expected KeyPath() == /etc/pki/tls/private/localhost.key") |
| } |
| |
| if cfg.KeyPath != "/etc/pki/tls/private/localhost.key" { |
| t.Error("Expected KeyPath() == /etc/pki/tls/private/localhost.key") |
| } |
| } |
| |
| func TestValidateRoutingBlacklist(t *testing.T) { |
| type testCase struct { |
| Input RoutingBlacklist |
| ExpectErr bool |
| } |
| testCases := []testCase{ |
| { |
| Input: RoutingBlacklist{ |
| DisabledRoutes: nil, |
| }, |
| ExpectErr: false, |
| }, |
| { |
| Input: RoutingBlacklist{ |
| DisabledRoutes: []int{4, 5, 6}, |
| }, |
| ExpectErr: false, |
| }, |
| { |
| Input: RoutingBlacklist{ |
| DisabledRoutes: []int{4, 5, 6}, |
| }, |
| ExpectErr: false, |
| }, |
| { |
| Input: RoutingBlacklist{ |
| DisabledRoutes: nil, |
| }, |
| ExpectErr: false, |
| }, |
| { |
| Input: RoutingBlacklist{ |
| DisabledRoutes: []int{2, 2, 4}, |
| }, |
| ExpectErr: true, |
| }, |
| { |
| Input: RoutingBlacklist{ |
| DisabledRoutes: []int{4, 4, 6}, |
| }, |
| ExpectErr: true, |
| }, |
| } |
| for _, tc := range testCases { |
| if err := ValidateRoutingBlacklist(tc.Input); err != nil && !tc.ExpectErr { |
| t.Errorf("Expected: no error, actual: %v", err) |
| } else if err == nil && tc.ExpectErr { |
| t.Errorf("Expected: non-nil error, actual: nil") |
| } |
| } |
| } |