From 1f86770456f26d93a78509099f11b2c635d09ac6 Mon Sep 17 00:00:00 2001 From: Lang Martin Date: Thu, 4 Apr 2019 15:12:07 -0400 Subject: [PATCH] config_parse_test test direct hcl parsing --- command/agent/config_parse_test.go | 1093 +++++++---------- command/agent/testdata/config-slices-alt.json | 67 + command/agent/testdata/config-slices.hcl | 13 + command/agent/testdata/config-slices.json | 41 + command/agent/testdata/non-optional.json | 7 + .../agent/testdata/obj-len-one-server.json | 7 + command/agent/testdata/obj-len-one.hcl | 5 + command/agent/testdata/obj-len-one.json | 8 + 8 files changed, 626 insertions(+), 615 deletions(-) create mode 100644 command/agent/testdata/config-slices-alt.json create mode 100644 command/agent/testdata/config-slices.hcl create mode 100644 command/agent/testdata/config-slices.json create mode 100644 command/agent/testdata/non-optional.json create mode 100644 command/agent/testdata/obj-len-one-server.json create mode 100644 command/agent/testdata/obj-len-one.hcl create mode 100644 command/agent/testdata/obj-len-one.json diff --git a/command/agent/config_parse_test.go b/command/agent/config_parse_test.go index b58f89730..dba20dca2 100644 --- a/command/agent/config_parse_test.go +++ b/command/agent/config_parse_test.go @@ -7,9 +7,348 @@ import ( "github.com/hashicorp/nomad/helper" "github.com/hashicorp/nomad/nomad/structs/config" + "github.com/kr/pretty" "github.com/stretchr/testify/require" ) +var basicConfig = &Config{ + Region: "foobar", + Datacenter: "dc2", + NodeName: "my-web", + DataDir: "/tmp/nomad", + PluginDir: "/tmp/nomad-plugins", + LogLevel: "ERR", + LogJson: true, + BindAddr: "192.168.0.1", + EnableDebug: true, + Ports: &Ports{ + HTTP: 1234, + RPC: 2345, + Serf: 3456, + }, + Addresses: &Addresses{ + HTTP: "127.0.0.1", + RPC: "127.0.0.2", + Serf: "127.0.0.3", + }, + AdvertiseAddrs: &AdvertiseAddrs{ + RPC: "127.0.0.3", + Serf: "127.0.0.4", + }, + Client: &ClientConfig{ + Enabled: true, + StateDir: "/tmp/client-state", + AllocDir: "/tmp/alloc", + Servers: []string{"a.b.c:80", "127.0.0.1:1234"}, + NodeClass: "linux-medium-64bit", + ServerJoin: &ServerJoin{ + RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, + RetryInterval: time.Duration(15) * time.Second, + RetryMaxAttempts: 3, + }, + Meta: map[string]string{ + "foo": "bar", + "baz": "zip", + }, + Options: map[string]string{ + "foo": "bar", + "baz": "zip", + }, + ChrootEnv: map[string]string{ + "/opt/myapp/etc": "/etc", + "/opt/myapp/bin": "/bin", + }, + NetworkInterface: "eth0", + NetworkSpeed: 100, + CpuCompute: 4444, + MemoryMB: 0, + MaxKillTimeout: "10s", + ClientMinPort: 1000, + ClientMaxPort: 2000, + Reserved: &Resources{ + CPU: 10, + MemoryMB: 10, + DiskMB: 10, + ReservedPorts: "1,100,10-12", + }, + GCInterval: 6 * time.Second, + GCParallelDestroys: 6, + GCDiskUsageThreshold: 82, + GCInodeUsageThreshold: 91, + GCMaxAllocs: 50, + NoHostUUID: helper.BoolToPtr(false), + }, + Server: &ServerConfig{ + Enabled: true, + AuthoritativeRegion: "foobar", + BootstrapExpect: 5, + DataDir: "/tmp/data", + ProtocolVersion: 3, + RaftProtocol: 3, + NumSchedulers: helper.IntToPtr(2), + EnabledSchedulers: []string{"test"}, + NodeGCThreshold: "12h", + EvalGCThreshold: "12h", + JobGCThreshold: "12h", + DeploymentGCThreshold: "12h", + HeartbeatGrace: 30 * time.Second, + MinHeartbeatTTL: 33 * time.Second, + MaxHeartbeatsPerSecond: 11.0, + RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, + StartJoin: []string{"1.1.1.1", "2.2.2.2"}, + RetryInterval: 15 * time.Second, + RejoinAfterLeave: true, + RetryMaxAttempts: 3, + NonVotingServer: true, + RedundancyZone: "foo", + UpgradeVersion: "0.8.0", + EncryptKey: "abc", + ServerJoin: &ServerJoin{ + RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, + RetryInterval: time.Duration(15) * time.Second, + RetryMaxAttempts: 3, + }, + }, + ACL: &ACLConfig{ + Enabled: true, + TokenTTL: 60 * time.Second, + PolicyTTL: 60 * time.Second, + ReplicationToken: "foobar", + }, + Telemetry: &Telemetry{ + StatsiteAddr: "127.0.0.1:1234", + StatsdAddr: "127.0.0.1:2345", + PrometheusMetrics: true, + DisableHostname: true, + UseNodeName: false, + CollectionInterval: "3s", + collectionInterval: 3 * time.Second, + PublishAllocationMetrics: true, + PublishNodeMetrics: true, + DisableTaggedMetrics: true, + BackwardsCompatibleMetrics: true, + }, + LeaveOnInt: true, + LeaveOnTerm: true, + EnableSyslog: true, + SyslogFacility: "LOCAL1", + DisableUpdateCheck: helper.BoolToPtr(true), + DisableAnonymousSignature: true, + Consul: &config.ConsulConfig{ + ServerServiceName: "nomad", + ServerHTTPCheckName: "nomad-server-http-health-check", + ServerSerfCheckName: "nomad-server-serf-health-check", + ServerRPCCheckName: "nomad-server-rpc-health-check", + ClientServiceName: "nomad-client", + ClientHTTPCheckName: "nomad-client-http-health-check", + Addr: "127.0.0.1:9500", + Token: "token1", + Auth: "username:pass", + EnableSSL: &trueValue, + VerifySSL: &trueValue, + CAFile: "/path/to/ca/file", + CertFile: "/path/to/cert/file", + KeyFile: "/path/to/key/file", + ServerAutoJoin: &trueValue, + ClientAutoJoin: &trueValue, + AutoAdvertise: &trueValue, + ChecksUseAdvertise: &trueValue, + Timeout: 5 * time.Second, + }, + Vault: &config.VaultConfig{ + Addr: "127.0.0.1:9500", + AllowUnauthenticated: &trueValue, + ConnectionRetryIntv: config.DefaultVaultConnectRetryIntv, + Enabled: &falseValue, + Role: "test_role", + TLSCaFile: "/path/to/ca/file", + TLSCaPath: "/path/to/ca", + TLSCertFile: "/path/to/cert/file", + TLSKeyFile: "/path/to/key/file", + TLSServerName: "foobar", + TLSSkipVerify: &trueValue, + TaskTokenTTL: "1s", + Token: "12345", + }, + TLSConfig: &config.TLSConfig{ + EnableHTTP: true, + EnableRPC: true, + VerifyServerHostname: true, + CAFile: "foo", + CertFile: "bar", + KeyFile: "pipe", + RPCUpgradeMode: true, + VerifyHTTPSClient: true, + TLSPreferServerCipherSuites: true, + TLSCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + TLSMinVersion: "tls12", + }, + HTTPAPIResponseHeaders: map[string]string{ + "Access-Control-Allow-Origin": "*", + }, + Sentinel: &config.SentinelConfig{ + Imports: []*config.SentinelImport{ + { + Name: "foo", + Path: "foo", + Args: []string{"a", "b", "c"}, + }, + { + Name: "bar", + Path: "bar", + Args: []string{"x", "y", "z"}, + }, + }, + }, + Autopilot: &config.AutopilotConfig{ + CleanupDeadServers: &trueValue, + ServerStabilizationTime: 23057 * time.Second, + LastContactThreshold: 12705 * time.Second, + MaxTrailingLogs: 17849, + EnableRedundancyZones: &trueValue, + DisableUpgradeMigration: &trueValue, + EnableCustomUpgrades: &trueValue, + }, + Plugins: []*config.PluginConfig{ + { + Name: "docker", + Args: []string{"foo", "bar"}, + Config: map[string]interface{}{ + "foo": "bar", + "nested": []map[string]interface{}{ + { + "bam": 2, + }, + }, + }, + }, + { + Name: "exec", + Config: map[string]interface{}{ + "foo": true, + }, + }, + }, +} + +var pluginConfig = &Config{ + Region: "", + Datacenter: "", + NodeName: "", + DataDir: "", + PluginDir: "", + LogLevel: "", + BindAddr: "", + EnableDebug: false, + Ports: nil, + Addresses: nil, + AdvertiseAddrs: nil, + Client: &ClientConfig{ + Enabled: false, + StateDir: "", + AllocDir: "", + Servers: nil, + NodeClass: "", + Meta: nil, + Options: nil, + ChrootEnv: nil, + NetworkInterface: "", + NetworkSpeed: 0, + CpuCompute: 0, + MemoryMB: 5555, + MaxKillTimeout: "", + ClientMinPort: 0, + ClientMaxPort: 0, + Reserved: nil, + GCInterval: 0, + GCParallelDestroys: 0, + GCDiskUsageThreshold: 0, + GCInodeUsageThreshold: 0, + GCMaxAllocs: 0, + NoHostUUID: nil, + }, + Server: nil, + ACL: nil, + Telemetry: nil, + LeaveOnInt: false, + LeaveOnTerm: false, + EnableSyslog: false, + SyslogFacility: "", + DisableUpdateCheck: nil, + DisableAnonymousSignature: false, + Consul: nil, + Vault: nil, + TLSConfig: nil, + HTTPAPIResponseHeaders: nil, + Sentinel: nil, + Plugins: []*config.PluginConfig{ + { + Name: "docker", + Config: map[string]interface{}{ + "allow_privileged": true, + }, + }, + { + Name: "raw_exec", + Config: map[string]interface{}{ + "enabled": true, + }, + }, + }, +} + +var nonoptConfig = &Config{ + Region: "", + Datacenter: "", + NodeName: "", + DataDir: "", + PluginDir: "", + LogLevel: "", + BindAddr: "", + EnableDebug: false, + Ports: nil, + Addresses: nil, + AdvertiseAddrs: nil, + Client: &ClientConfig{ + Enabled: false, + StateDir: "", + AllocDir: "", + Servers: nil, + NodeClass: "", + Meta: nil, + Options: nil, + ChrootEnv: nil, + NetworkInterface: "", + NetworkSpeed: 0, + CpuCompute: 0, + MemoryMB: 5555, + MaxKillTimeout: "", + ClientMinPort: 0, + ClientMaxPort: 0, + Reserved: nil, + GCInterval: 0, + GCParallelDestroys: 0, + GCDiskUsageThreshold: 0, + GCInodeUsageThreshold: 0, + GCMaxAllocs: 0, + NoHostUUID: nil, + }, + Server: nil, + ACL: nil, + Telemetry: nil, + LeaveOnInt: false, + LeaveOnTerm: false, + EnableSyslog: false, + SyslogFacility: "", + DisableUpdateCheck: nil, + DisableAnonymousSignature: false, + Consul: nil, + Vault: nil, + TLSConfig: nil, + HTTPAPIResponseHeaders: nil, + Sentinel: nil, +} + func TestConfig_Parse(t *testing.T) { t.Parallel() cases := []struct { @@ -19,637 +358,27 @@ func TestConfig_Parse(t *testing.T) { }{ { "basic.hcl", - &Config{ - Region: "foobar", - Datacenter: "dc2", - NodeName: "my-web", - DataDir: "/tmp/nomad", - PluginDir: "/tmp/nomad-plugins", - LogLevel: "ERR", - LogJson: true, - BindAddr: "192.168.0.1", - EnableDebug: true, - Ports: &Ports{ - HTTP: 1234, - RPC: 2345, - Serf: 3456, - }, - Addresses: &Addresses{ - HTTP: "127.0.0.1", - RPC: "127.0.0.2", - Serf: "127.0.0.3", - }, - AdvertiseAddrs: &AdvertiseAddrs{ - RPC: "127.0.0.3", - Serf: "127.0.0.4", - }, - Client: &ClientConfig{ - Enabled: true, - StateDir: "/tmp/client-state", - AllocDir: "/tmp/alloc", - Servers: []string{"a.b.c:80", "127.0.0.1:1234"}, - NodeClass: "linux-medium-64bit", - ServerJoin: &ServerJoin{ - RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, - RetryInterval: time.Duration(15) * time.Second, - RetryMaxAttempts: 3, - }, - Meta: map[string]string{ - "foo": "bar", - "baz": "zip", - }, - Options: map[string]string{ - "foo": "bar", - "baz": "zip", - }, - ChrootEnv: map[string]string{ - "/opt/myapp/etc": "/etc", - "/opt/myapp/bin": "/bin", - }, - NetworkInterface: "eth0", - NetworkSpeed: 100, - CpuCompute: 4444, - MemoryMB: 0, - MaxKillTimeout: "10s", - ClientMinPort: 1000, - ClientMaxPort: 2000, - Reserved: &Resources{ - CPU: 10, - MemoryMB: 10, - DiskMB: 10, - ReservedPorts: "1,100,10-12", - }, - GCInterval: 6 * time.Second, - GCParallelDestroys: 6, - GCDiskUsageThreshold: 82, - GCInodeUsageThreshold: 91, - GCMaxAllocs: 50, - NoHostUUID: helper.BoolToPtr(false), - }, - Server: &ServerConfig{ - Enabled: true, - AuthoritativeRegion: "foobar", - BootstrapExpect: 5, - DataDir: "/tmp/data", - ProtocolVersion: 3, - RaftProtocol: 3, - NumSchedulers: helper.IntToPtr(2), - EnabledSchedulers: []string{"test"}, - NodeGCThreshold: "12h", - EvalGCThreshold: "12h", - JobGCThreshold: "12h", - DeploymentGCThreshold: "12h", - HeartbeatGrace: 30 * time.Second, - MinHeartbeatTTL: 33 * time.Second, - MaxHeartbeatsPerSecond: 11.0, - RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, - StartJoin: []string{"1.1.1.1", "2.2.2.2"}, - RetryInterval: 15 * time.Second, - RejoinAfterLeave: true, - RetryMaxAttempts: 3, - NonVotingServer: true, - RedundancyZone: "foo", - UpgradeVersion: "0.8.0", - EncryptKey: "abc", - ServerJoin: &ServerJoin{ - RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, - RetryInterval: time.Duration(15) * time.Second, - RetryMaxAttempts: 3, - }, - }, - ACL: &ACLConfig{ - Enabled: true, - TokenTTL: 60 * time.Second, - PolicyTTL: 60 * time.Second, - ReplicationToken: "foobar", - }, - Telemetry: &Telemetry{ - StatsiteAddr: "127.0.0.1:1234", - StatsdAddr: "127.0.0.1:2345", - PrometheusMetrics: true, - DisableHostname: true, - UseNodeName: false, - CollectionInterval: "3s", - collectionInterval: 3 * time.Second, - PublishAllocationMetrics: true, - PublishNodeMetrics: true, - DisableTaggedMetrics: true, - BackwardsCompatibleMetrics: true, - }, - LeaveOnInt: true, - LeaveOnTerm: true, - EnableSyslog: true, - SyslogFacility: "LOCAL1", - DisableUpdateCheck: helper.BoolToPtr(true), - DisableAnonymousSignature: true, - Consul: &config.ConsulConfig{ - ServerServiceName: "nomad", - ServerHTTPCheckName: "nomad-server-http-health-check", - ServerSerfCheckName: "nomad-server-serf-health-check", - ServerRPCCheckName: "nomad-server-rpc-health-check", - ClientServiceName: "nomad-client", - ClientHTTPCheckName: "nomad-client-http-health-check", - Addr: "127.0.0.1:9500", - Token: "token1", - Auth: "username:pass", - EnableSSL: &trueValue, - VerifySSL: &trueValue, - CAFile: "/path/to/ca/file", - CertFile: "/path/to/cert/file", - KeyFile: "/path/to/key/file", - ServerAutoJoin: &trueValue, - ClientAutoJoin: &trueValue, - AutoAdvertise: &trueValue, - ChecksUseAdvertise: &trueValue, - }, - Vault: &config.VaultConfig{ - Addr: "127.0.0.1:9500", - AllowUnauthenticated: &trueValue, - Enabled: &falseValue, - Role: "test_role", - TLSCaFile: "/path/to/ca/file", - TLSCaPath: "/path/to/ca", - TLSCertFile: "/path/to/cert/file", - TLSKeyFile: "/path/to/key/file", - TLSServerName: "foobar", - TLSSkipVerify: &trueValue, - TaskTokenTTL: "1s", - Token: "12345", - }, - TLSConfig: &config.TLSConfig{ - EnableHTTP: true, - EnableRPC: true, - VerifyServerHostname: true, - CAFile: "foo", - CertFile: "bar", - KeyFile: "pipe", - RPCUpgradeMode: true, - VerifyHTTPSClient: true, - TLSPreferServerCipherSuites: true, - TLSCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - TLSMinVersion: "tls12", - }, - HTTPAPIResponseHeaders: map[string]string{ - "Access-Control-Allow-Origin": "*", - }, - Sentinel: &config.SentinelConfig{ - Imports: []*config.SentinelImport{ - { - Name: "foo", - Path: "foo", - Args: []string{"a", "b", "c"}, - }, - { - Name: "bar", - Path: "bar", - Args: []string{"x", "y", "z"}, - }, - }, - }, - Autopilot: &config.AutopilotConfig{ - CleanupDeadServers: &trueValue, - ServerStabilizationTime: 23057 * time.Second, - LastContactThreshold: 12705 * time.Second, - MaxTrailingLogs: 17849, - EnableRedundancyZones: &trueValue, - DisableUpgradeMigration: &trueValue, - EnableCustomUpgrades: &trueValue, - }, - Plugins: []*config.PluginConfig{ - { - Name: "docker", - Args: []string{"foo", "bar"}, - Config: map[string]interface{}{ - "foo": "bar", - "nested": []map[string]interface{}{ - { - "bam": 2, - }, - }, - }, - }, - { - Name: "exec", - Config: map[string]interface{}{ - "foo": true, - }, - }, - }, - }, + basicConfig, false, }, { "basic.json", - &Config{ - Region: "foobar", - Datacenter: "dc2", - NodeName: "my-web", - DataDir: "/tmp/nomad", - PluginDir: "/tmp/nomad-plugins", - LogLevel: "ERR", - LogJson: true, - BindAddr: "192.168.0.1", - EnableDebug: true, - Ports: &Ports{ - HTTP: 1234, - RPC: 2345, - Serf: 3456, - }, - Addresses: &Addresses{ - HTTP: "127.0.0.1", - RPC: "127.0.0.2", - Serf: "127.0.0.3", - }, - AdvertiseAddrs: &AdvertiseAddrs{ - RPC: "127.0.0.3", - Serf: "127.0.0.4", - }, - Client: &ClientConfig{ - Enabled: true, - StateDir: "/tmp/client-state", - AllocDir: "/tmp/alloc", - Servers: []string{"a.b.c:80", "127.0.0.1:1234"}, - NodeClass: "linux-medium-64bit", - ServerJoin: &ServerJoin{ - RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, - RetryInterval: time.Duration(15) * time.Second, - RetryMaxAttempts: 3, - }, - Meta: map[string]string{ - "foo": "bar", - "baz": "zip", - }, - Options: map[string]string{ - "foo": "bar", - "baz": "zip", - }, - ChrootEnv: map[string]string{ - "/opt/myapp/etc": "/etc", - "/opt/myapp/bin": "/bin", - }, - NetworkInterface: "eth0", - NetworkSpeed: 100, - CpuCompute: 4444, - MemoryMB: 0, - MaxKillTimeout: "10s", - ClientMinPort: 1000, - ClientMaxPort: 2000, - Reserved: &Resources{ - CPU: 10, - MemoryMB: 10, - DiskMB: 10, - ReservedPorts: "1,100,10-12", - }, - GCInterval: 6 * time.Second, - GCParallelDestroys: 6, - GCDiskUsageThreshold: 82, - GCInodeUsageThreshold: 91, - GCMaxAllocs: 50, - NoHostUUID: helper.BoolToPtr(false), - }, - Server: &ServerConfig{ - Enabled: true, - AuthoritativeRegion: "foobar", - BootstrapExpect: 5, - DataDir: "/tmp/data", - ProtocolVersion: 3, - RaftProtocol: 3, - NumSchedulers: helper.IntToPtr(2), - EnabledSchedulers: []string{"test"}, - NodeGCThreshold: "12h", - EvalGCThreshold: "12h", - JobGCThreshold: "12h", - DeploymentGCThreshold: "12h", - HeartbeatGrace: 30 * time.Second, - MinHeartbeatTTL: 33 * time.Second, - MaxHeartbeatsPerSecond: 11.0, - RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, - StartJoin: []string{"1.1.1.1", "2.2.2.2"}, - RetryInterval: 15 * time.Second, - RejoinAfterLeave: true, - RetryMaxAttempts: 3, - NonVotingServer: true, - RedundancyZone: "foo", - UpgradeVersion: "0.8.0", - EncryptKey: "abc", - ServerJoin: &ServerJoin{ - RetryJoin: []string{"1.1.1.1", "2.2.2.2"}, - RetryInterval: time.Duration(15) * time.Second, - RetryMaxAttempts: 3, - }, - }, - ACL: &ACLConfig{ - Enabled: true, - TokenTTL: 60 * time.Second, - PolicyTTL: 60 * time.Second, - ReplicationToken: "foobar", - }, - Telemetry: &Telemetry{ - StatsiteAddr: "127.0.0.1:1234", - StatsdAddr: "127.0.0.1:2345", - PrometheusMetrics: true, - DisableHostname: true, - UseNodeName: false, - CollectionInterval: "3s", - collectionInterval: 3 * time.Second, - PublishAllocationMetrics: true, - PublishNodeMetrics: true, - DisableTaggedMetrics: true, - BackwardsCompatibleMetrics: true, - }, - LeaveOnInt: true, - LeaveOnTerm: true, - EnableSyslog: true, - SyslogFacility: "LOCAL1", - DisableUpdateCheck: helper.BoolToPtr(true), - DisableAnonymousSignature: true, - Consul: &config.ConsulConfig{ - ServerServiceName: "nomad", - ServerHTTPCheckName: "nomad-server-http-health-check", - ServerSerfCheckName: "nomad-server-serf-health-check", - ServerRPCCheckName: "nomad-server-rpc-health-check", - ClientServiceName: "nomad-client", - ClientHTTPCheckName: "nomad-client-http-health-check", - Addr: "127.0.0.1:9500", - Token: "token1", - Auth: "username:pass", - EnableSSL: &trueValue, - VerifySSL: &trueValue, - CAFile: "/path/to/ca/file", - CertFile: "/path/to/cert/file", - KeyFile: "/path/to/key/file", - ServerAutoJoin: &trueValue, - ClientAutoJoin: &trueValue, - AutoAdvertise: &trueValue, - ChecksUseAdvertise: &trueValue, - }, - Vault: &config.VaultConfig{ - Addr: "127.0.0.1:9500", - AllowUnauthenticated: &trueValue, - Enabled: &falseValue, - Role: "test_role", - TLSCaFile: "/path/to/ca/file", - TLSCaPath: "/path/to/ca", - TLSCertFile: "/path/to/cert/file", - TLSKeyFile: "/path/to/key/file", - TLSServerName: "foobar", - TLSSkipVerify: &trueValue, - TaskTokenTTL: "1s", - Token: "12345", - }, - TLSConfig: &config.TLSConfig{ - EnableHTTP: true, - EnableRPC: true, - VerifyServerHostname: true, - CAFile: "foo", - CertFile: "bar", - KeyFile: "pipe", - RPCUpgradeMode: true, - VerifyHTTPSClient: true, - TLSPreferServerCipherSuites: true, - TLSCipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - TLSMinVersion: "tls12", - }, - HTTPAPIResponseHeaders: map[string]string{ - "Access-Control-Allow-Origin": "*", - }, - Sentinel: &config.SentinelConfig{ - Imports: []*config.SentinelImport{ - { - Name: "foo", - Path: "foo", - Args: []string{"a", "b", "c"}, - }, - { - Name: "bar", - Path: "bar", - Args: []string{"x", "y", "z"}, - }, - }, - }, - Autopilot: &config.AutopilotConfig{ - CleanupDeadServers: &trueValue, - ServerStabilizationTime: 23057 * time.Second, - LastContactThreshold: 12705 * time.Second, - MaxTrailingLogs: 17849, - EnableRedundancyZones: &trueValue, - DisableUpgradeMigration: &trueValue, - EnableCustomUpgrades: &trueValue, - }, - Plugins: []*config.PluginConfig{ - { - Name: "docker", - Args: []string{"foo", "bar"}, - Config: map[string]interface{}{ - "foo": "bar", - "nested": []map[string]interface{}{ - { - "bam": 2, - }, - }, - }, - }, - { - Name: "exec", - Config: map[string]interface{}{ - "foo": true, - }, - }, - }, - }, + basicConfig, false, }, { "plugin.hcl", - &Config{ - Region: "", - Datacenter: "", - NodeName: "", - DataDir: "", - PluginDir: "", - LogLevel: "", - BindAddr: "", - EnableDebug: false, - Ports: nil, - Addresses: nil, - AdvertiseAddrs: nil, - Client: &ClientConfig{ - Enabled: false, - StateDir: "", - AllocDir: "", - Servers: nil, - NodeClass: "", - Meta: nil, - Options: nil, - ChrootEnv: nil, - NetworkInterface: "", - NetworkSpeed: 0, - CpuCompute: 0, - MemoryMB: 5555, - MaxKillTimeout: "", - ClientMinPort: 0, - ClientMaxPort: 0, - Reserved: nil, - GCInterval: 0, - GCParallelDestroys: 0, - GCDiskUsageThreshold: 0, - GCInodeUsageThreshold: 0, - GCMaxAllocs: 0, - NoHostUUID: nil, - }, - Server: nil, - ACL: nil, - Telemetry: nil, - LeaveOnInt: false, - LeaveOnTerm: false, - EnableSyslog: false, - SyslogFacility: "", - DisableUpdateCheck: nil, - DisableAnonymousSignature: false, - Consul: nil, - Vault: nil, - TLSConfig: nil, - HTTPAPIResponseHeaders: nil, - Sentinel: nil, - Plugins: []*config.PluginConfig{ - { - Name: "docker", - Config: map[string]interface{}{ - "allow_privileged": true, - }, - }, - { - Name: "raw_exec", - Config: map[string]interface{}{ - "enabled": true, - }, - }, - }, - }, + pluginConfig, false, }, { "plugin.json", - &Config{ - Region: "", - Datacenter: "", - NodeName: "", - DataDir: "", - PluginDir: "", - LogLevel: "", - BindAddr: "", - EnableDebug: false, - Ports: nil, - Addresses: nil, - AdvertiseAddrs: nil, - Client: &ClientConfig{ - Enabled: false, - StateDir: "", - AllocDir: "", - Servers: nil, - NodeClass: "", - Meta: nil, - Options: nil, - ChrootEnv: nil, - NetworkInterface: "", - NetworkSpeed: 0, - CpuCompute: 0, - MemoryMB: 5555, - MaxKillTimeout: "", - ClientMinPort: 0, - ClientMaxPort: 0, - Reserved: nil, - GCInterval: 0, - GCParallelDestroys: 0, - GCDiskUsageThreshold: 0, - GCInodeUsageThreshold: 0, - GCMaxAllocs: 0, - NoHostUUID: nil, - }, - Server: nil, - ACL: nil, - Telemetry: nil, - LeaveOnInt: false, - LeaveOnTerm: false, - EnableSyslog: false, - SyslogFacility: "", - DisableUpdateCheck: nil, - DisableAnonymousSignature: false, - Consul: nil, - Vault: nil, - TLSConfig: nil, - HTTPAPIResponseHeaders: nil, - Sentinel: nil, - Plugins: []*config.PluginConfig{ - { - Name: "docker", - Config: map[string]interface{}{ - "allow_privileged": true, - }, - }, - { - Name: "raw_exec", - Config: map[string]interface{}{ - "enabled": true, - }, - }, - }, - }, + pluginConfig, false, }, { "non-optional.hcl", - &Config{ - Region: "", - Datacenter: "", - NodeName: "", - DataDir: "", - PluginDir: "", - LogLevel: "", - BindAddr: "", - EnableDebug: false, - Ports: nil, - Addresses: nil, - AdvertiseAddrs: nil, - Client: &ClientConfig{ - Enabled: false, - StateDir: "", - AllocDir: "", - Servers: nil, - NodeClass: "", - Meta: nil, - Options: nil, - ChrootEnv: nil, - NetworkInterface: "", - NetworkSpeed: 0, - CpuCompute: 0, - MemoryMB: 5555, - MaxKillTimeout: "", - ClientMinPort: 0, - ClientMaxPort: 0, - Reserved: nil, - GCInterval: 0, - GCParallelDestroys: 0, - GCDiskUsageThreshold: 0, - GCInodeUsageThreshold: 0, - GCMaxAllocs: 0, - NoHostUUID: nil, - }, - Server: nil, - ACL: nil, - Telemetry: nil, - LeaveOnInt: false, - LeaveOnTerm: false, - EnableSyslog: false, - SyslogFacility: "", - DisableUpdateCheck: nil, - DisableAnonymousSignature: false, - Consul: nil, - Vault: nil, - TLSConfig: nil, - HTTPAPIResponseHeaders: nil, - Sentinel: nil, - }, + nonoptConfig, false, }, } @@ -682,3 +411,137 @@ func removeHelperAttributes(c *Config) *Config { } return c } + +func Test_removeEqualFold(t *testing.T) { + xs := []string{"foo", "bar"} + removeEqualFold(&xs, "foo") + pretty.Log(xs) + removeEqualFold(&xs, "bar") + pretty.Log(xs) +} + +func (c *Config) addDefaults() { + if c.Client.ServerJoin == nil { + c.Client.ServerJoin = &ServerJoin{} + } + if c.ACL == nil { + c.ACL = &ACLConfig{} + } + if c.Consul == nil { + c.Consul = config.DefaultConsulConfig() + } + if c.Autopilot == nil { + c.Autopilot = config.DefaultAutopilotConfig() + } + if c.Vault == nil { + c.Vault = config.DefaultVaultConfig() + } + if c.Telemetry == nil { + c.Telemetry = &Telemetry{} + } + if c.Server == nil { + c.Server = &ServerConfig{} + } + if c.Server.ServerJoin == nil { + c.Server.ServerJoin = &ServerJoin{} + } +} + +func TestParseDirectHCL(t *testing.T) { + t.Parallel() + + // inconsequential changes to parsed data + basicConfig.Telemetry.CollectionInterval = "" // tmp field to hold the string value + pluginConfig.addDefaults() + nonoptConfig.addDefaults() + + cases := []struct { + File string + Result *Config + Err bool + }{ + {"basic.hcl", basicConfig, false}, + {"basic.json", basicConfig, false}, + {"plugin.hcl", pluginConfig, false}, + {"plugin.json", pluginConfig, false}, + {"non-optional.hcl", nonoptConfig, false}, + {"non-optional.json", nonoptConfig, false}, + } + + for _, tc := range cases { + t.Run(tc.File, func(t *testing.T) { + require := require.New(t) + path, err := filepath.Abs(filepath.Join("./testdata", tc.File)) + if err != nil { + t.Fatalf("file: %s\n\n%s", tc.File, err) + } + + actual, err := ParseConfigFileDirectHCL(path) + if (err != nil) != tc.Err { + t.Fatalf("file: %s\n\n%s", tc.File, err) + } + + //panic(fmt.Sprintf("first: %+v \n second: %+v", actual.TLSConfig, tc.Result.TLSConfig)) + require.EqualValues(removeHelperAttributes(actual), tc.Result) + }) + } +} + +// this tests for a panic parsing json with an object of exactly +// length 1 described in +// https://github.com/hashicorp/nomad/issues/1290 +func TestParseDirectHCLPanic(t *testing.T) { + c, err := ParseConfigFileDirectHCL("./testdata/obj-len-one.hcl") + if err != nil { + t.Fatalf("parse error: %s\n", err) + } + + d, err := ParseConfigFileDirectHCL("./testdata/obj-len-one.json") + if err != nil { + t.Fatalf("parse error: %s\n", err) + } + + require.EqualValues(t, c, d) +} + +// this tests for top level keys left by hcl when parsing slices in +// the config structure +func TestParseDirectHCLSliceExtra(t *testing.T) { + c, err := ParseConfigFileDirectHCL("./testdata/config-slices.json") + if err != nil { + t.Fatalf("parse error: %s\n", err) + } + + opt := map[string]string{"o0": "foo", "o1": "bar"} + meta := map[string]string{"m0": "foo", "m1": "bar"} + env := map[string]string{"e0": "baz"} + srv := []string{"foo", "bar"} + + require.EqualValues(t, opt, c.Client.Options) + require.EqualValues(t, meta, c.Client.Meta) + require.EqualValues(t, env, c.Client.ChrootEnv) + require.EqualValues(t, srv, c.Client.Servers) + require.EqualValues(t, srv, c.Server.EnabledSchedulers) + require.EqualValues(t, srv, c.Server.StartJoin) + require.EqualValues(t, srv, c.Server.RetryJoin) + + // the alt format is also accepted by hcl as valid config data + c, err = ParseConfigFileDirectHCL("./testdata/config-slices-alt.json") + if err != nil { + t.Fatalf("parse error: %s\n", err) + } + + require.EqualValues(t, opt, c.Client.Options) + require.EqualValues(t, meta, c.Client.Meta) + require.EqualValues(t, env, c.Client.ChrootEnv) + require.EqualValues(t, srv, c.Client.Servers) + require.EqualValues(t, srv, c.Server.EnabledSchedulers) + require.EqualValues(t, srv, c.Server.StartJoin) + require.EqualValues(t, srv, c.Server.RetryJoin) + + // small files keep more extra keys than large ones + _, err = ParseConfigFileDirectHCL("./testdata/obj-len-one-server.json") + if err != nil { + t.Fatalf("parse error: %s\n", err) + } +} diff --git a/command/agent/testdata/config-slices-alt.json b/command/agent/testdata/config-slices-alt.json new file mode 100644 index 000000000..d259e6209 --- /dev/null +++ b/command/agent/testdata/config-slices-alt.json @@ -0,0 +1,67 @@ +{ + "client": [ + { + "chroot_env": [ + { + "e0": "baz" + } + ], + "meta": [ + { + "m0": "foo", + "m1": "bar" + } + ], + "options": [ + { + "o0": "foo", + "o1": "bar" + } + ], + "server_join": [ + { + "retry_join": [ + "foo", + "bar" + ], + "start_join": [ + "foo", + "bar" + ] + } + ], + "servers": [ + "foo", + "bar" + ] + } + ], + "server": [ + { + "enabled_schedulers": [ + "foo", + "bar" + ], + "retry_join": [ + "foo", + "bar" + ], + "server_join": [ + { + "retry_join": [ + "foo", + "bar" + ], + "start_join": [ + "foo", + "bar" + ] + } + ], + "start_join": [ + "foo", + "bar" + ] + } + ] +} diff --git a/command/agent/testdata/config-slices.hcl b/command/agent/testdata/config-slices.hcl new file mode 100644 index 000000000..98be21cae --- /dev/null +++ b/command/agent/testdata/config-slices.hcl @@ -0,0 +1,13 @@ +client "chroot_env" { + "e0" = "baz" +} + +client "meta" { + "m0" = "foo" + "m1" = "bar" +} + +client "options" { + "o0" = "foo" + "o1" = "bar" +} diff --git a/command/agent/testdata/config-slices.json b/command/agent/testdata/config-slices.json new file mode 100644 index 000000000..4a0e23bfa --- /dev/null +++ b/command/agent/testdata/config-slices.json @@ -0,0 +1,41 @@ +{ + "client": { + "options": { + "o0": "foo", + "o1": "bar" + }, + "meta": { + "m0": "foo", + "m1": "bar" + }, + "chroot_env": { + "e0": "baz" + }, + "servers": [ + "foo", + "bar" + ], + "server_join": { + "start_join": ["foo", "bar"], + "retry_join": ["foo", "bar"] + } + }, + "server": { + "enabled_schedulers": [ + "foo", + "bar" + ], + "start_join": [ + "foo", + "bar" + ], + "retry_join": [ + "foo", + "bar" + ], + "server_join": { + "start_join": ["foo", "bar"], + "retry_join": ["foo", "bar"] + } + } +} diff --git a/command/agent/testdata/non-optional.json b/command/agent/testdata/non-optional.json new file mode 100644 index 000000000..80d65f438 --- /dev/null +++ b/command/agent/testdata/non-optional.json @@ -0,0 +1,7 @@ +{ + "client": [ + { + "memory_total_mb": 5555 + } + ] +} diff --git a/command/agent/testdata/obj-len-one-server.json b/command/agent/testdata/obj-len-one-server.json new file mode 100644 index 000000000..d1d9677b5 --- /dev/null +++ b/command/agent/testdata/obj-len-one-server.json @@ -0,0 +1,7 @@ +{ + "server": { + "server_join": { + "start_join": ["foo", "bar"] + } + }, +} diff --git a/command/agent/testdata/obj-len-one.hcl b/command/agent/testdata/obj-len-one.hcl new file mode 100644 index 000000000..9d154a7b9 --- /dev/null +++ b/command/agent/testdata/obj-len-one.hcl @@ -0,0 +1,5 @@ +client { + options { + driver.whitelist = "docker" + } +} diff --git a/command/agent/testdata/obj-len-one.json b/command/agent/testdata/obj-len-one.json new file mode 100644 index 000000000..a1e46acea --- /dev/null +++ b/command/agent/testdata/obj-len-one.json @@ -0,0 +1,8 @@ +{ + "client": { + "options": { + "driver.whitelist": "docker" + } + }, + "server": {} +}