16997: Test map key order in check/dump. Fix duplicate warnings.
[arvados.git] / lib / config / cmd_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package config
6
7 import (
8         "bytes"
9         "io"
10         "io/ioutil"
11         "os"
12
13         "git.arvados.org/arvados.git/lib/cmd"
14         check "gopkg.in/check.v1"
15 )
16
17 var _ = check.Suite(&CommandSuite{})
18
19 var (
20         // Commands must satisfy cmd.Handler interface
21         _ cmd.Handler = dumpCommand{}
22         _ cmd.Handler = checkCommand{}
23 )
24
25 type CommandSuite struct{}
26
27 func (s *CommandSuite) SetUpSuite(c *check.C) {
28         os.Unsetenv("ARVADOS_API_HOST")
29         os.Unsetenv("ARVADOS_API_HOST_INSECURE")
30         os.Unsetenv("ARVADOS_API_TOKEN")
31 }
32
33 func (s *CommandSuite) TestDump_BadArg(c *check.C) {
34         var stderr bytes.Buffer
35         code := DumpCommand.RunCommand("arvados config-dump", []string{"-badarg"}, bytes.NewBuffer(nil), bytes.NewBuffer(nil), &stderr)
36         c.Check(code, check.Equals, 2)
37         c.Check(stderr.String(), check.Matches, `(?ms)flag provided but not defined: -badarg\nUsage:\n.*`)
38 }
39
40 func (s *CommandSuite) TestDump_EmptyInput(c *check.C) {
41         var stdout, stderr bytes.Buffer
42         code := DumpCommand.RunCommand("arvados config-dump", []string{"-config", "-"}, &bytes.Buffer{}, &stdout, &stderr)
43         c.Check(code, check.Equals, 1)
44         c.Check(stderr.String(), check.Matches, `config does not define any clusters\n`)
45 }
46
47 func (s *CommandSuite) TestCheck_NoWarnings(c *check.C) {
48         var stdout, stderr bytes.Buffer
49         in := `
50 Clusters:
51  z1234:
52   ManagementToken: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
53   SystemRootToken: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
54   API:
55     MaxItemsPerResponse: 1234
56   Collections:
57     BlobSigningKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
58   PostgreSQL:
59     Connection:
60       sslmode: require
61   Services:
62     RailsAPI:
63       InternalURLs:
64         "http://0.0.0.0:8000": {}
65   Workbench:
66     UserProfileFormFields:
67       color:
68         Type: select
69         Options:
70           fuchsia: {}
71     ApplicationMimetypesWithViewIcon:
72       whitespace: {}
73 `
74         code := CheckCommand.RunCommand("arvados config-check", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
75         c.Check(code, check.Equals, 0)
76         c.Check(stdout.String(), check.Equals, "")
77         c.Check(stderr.String(), check.Equals, "")
78 }
79
80 func (s *CommandSuite) TestCheck_DeprecatedKeys(c *check.C) {
81         var stdout, stderr bytes.Buffer
82         in := `
83 Clusters:
84  z1234:
85   RequestLimits:
86     MaxItemsPerResponse: 1234
87 `
88         code := CheckCommand.RunCommand("arvados config-check", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
89         c.Check(code, check.Equals, 1)
90         c.Check(stdout.String(), check.Matches, `(?ms).*\n\- +.*MaxItemsPerResponse: 1000\n\+ +MaxItemsPerResponse: 1234\n.*`)
91 }
92
93 func (s *CommandSuite) TestCheck_OldKeepstoreConfigFile(c *check.C) {
94         f, err := ioutil.TempFile("", "")
95         c.Assert(err, check.IsNil)
96         defer os.Remove(f.Name())
97
98         io.WriteString(f, "Listen: :12345\nDebug: true\n")
99
100         var stdout, stderr bytes.Buffer
101         in := `
102 Clusters:
103  z1234:
104   SystemLogs:
105     LogLevel: info
106 `
107         code := CheckCommand.RunCommand("arvados config-check", []string{"-config", "-", "-legacy-keepstore-config", f.Name()}, bytes.NewBufferString(in), &stdout, &stderr)
108         c.Check(code, check.Equals, 1)
109         c.Check(stdout.String(), check.Matches, `(?ms).*\n\- +.*LogLevel: info\n\+ +LogLevel: debug\n.*`)
110         c.Check(stderr.String(), check.Matches, `(?ms).*you should remove the legacy keepstore config file.*\n`)
111 }
112
113 func (s *CommandSuite) TestCheck_UnknownKey(c *check.C) {
114         var stdout, stderr bytes.Buffer
115         in := `
116 Clusters:
117  z1234:
118   Bogus1: foo
119   BogusSection:
120     Bogus2: foo
121   API:
122     Bogus3:
123      Bogus4: true
124   PostgreSQL:
125     ConnectionPool:
126       {Bogus5: true}
127 `
128         code := CheckCommand.RunCommand("arvados config-check", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
129         c.Log(stderr.String())
130         c.Check(code, check.Equals, 1)
131         c.Check(stderr.String(), check.Matches, `(?ms).*deprecated or unknown config entry: Clusters.z1234.Bogus1"\n.*`)
132         c.Check(stderr.String(), check.Matches, `(?ms).*deprecated or unknown config entry: Clusters.z1234.BogusSection"\n.*`)
133         c.Check(stderr.String(), check.Matches, `(?ms).*deprecated or unknown config entry: Clusters.z1234.API.Bogus3"\n.*`)
134         c.Check(stderr.String(), check.Matches, `(?ms).*unexpected object in config entry: Clusters.z1234.PostgreSQL.ConnectionPool"\n.*`)
135 }
136
137 func (s *CommandSuite) TestCheck_DuplicateWarnings(c *check.C) {
138         var stdout, stderr bytes.Buffer
139         in := `
140 Clusters:
141  z1234: {}
142 `
143         code := CheckCommand.RunCommand("arvados config-check", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
144         c.Check(code, check.Equals, 1)
145         c.Check(stderr.String(), check.Matches, `(?ms).*SystemRootToken.*`)
146         c.Check(stderr.String(), check.Not(check.Matches), `(?ms).*SystemRootToken.*SystemRootToken.*`)
147 }
148
149 func (s *CommandSuite) TestDump_Formatting(c *check.C) {
150         var stdout, stderr bytes.Buffer
151         in := `
152 Clusters:
153  z1234:
154   Containers:
155    CloudVMs:
156     TimeoutBooting: 600s
157   Services:
158    Controller:
159     InternalURLs:
160      http://localhost:12345: {}
161 `
162         code := DumpCommand.RunCommand("arvados config-dump", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
163         c.Check(code, check.Equals, 0)
164         c.Check(stdout.String(), check.Matches, `(?ms).*TimeoutBooting: 10m\n.*`)
165         c.Check(stdout.String(), check.Matches, `(?ms).*http://localhost:12345/: {}\n.*`)
166 }
167
168 func (s *CommandSuite) TestDump_UnknownKey(c *check.C) {
169         var stdout, stderr bytes.Buffer
170         in := `
171 Clusters:
172  z1234:
173   UnknownKey: foobar
174   ManagementToken: secret
175 `
176         code := DumpCommand.RunCommand("arvados config-dump", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
177         c.Check(code, check.Equals, 0)
178         c.Check(stderr.String(), check.Matches, `(?ms).*deprecated or unknown config entry: Clusters.z1234.UnknownKey.*`)
179         c.Check(stdout.String(), check.Matches, `(?ms)(.*\n)?Clusters:\n  z1234:\n.*`)
180         c.Check(stdout.String(), check.Matches, `(?ms).*\n *ManagementToken: secret\n.*`)
181         c.Check(stdout.String(), check.Not(check.Matches), `(?ms).*UnknownKey.*`)
182 }
183
184 func (s *CommandSuite) TestDump_KeyOrder(c *check.C) {
185         in := `
186 Clusters:
187  z1234:
188   Login:
189    Test:
190     Users:
191      a: {}
192      d: {}
193      c: {}
194      b: {}
195      e: {}
196 `
197         for trial := 0; trial < 20; trial++ {
198                 var stdout, stderr bytes.Buffer
199                 code := DumpCommand.RunCommand("arvados config-dump", []string{"-config", "-"}, bytes.NewBufferString(in), &stdout, &stderr)
200                 c.Assert(code, check.Equals, 0)
201                 if !c.Check(stdout.String(), check.Matches, `(?ms).*a:.*b:.*c:.*d:.*e:.*`) {
202                         c.Logf("config-dump did not use lexical key order on trial %d", trial)
203                         c.Log("stdout:\n", stdout.String())
204                         c.Log("stderr:\n", stderr.String())
205                         c.FailNow()
206                 }
207         }
208 }
209
210 func (s *CommandSuite) TestCheck_KeyOrder(c *check.C) {
211         in := `
212 Clusters:
213  z1234:
214   ManagementToken: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
215   SystemRootToken: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
216   Collections:
217    BlobSigningKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
218   InstanceTypes:
219    a: {}
220    d: {}
221    c: {}
222    b: {}
223    e: {}
224 `
225         for trial := 0; trial < 20; trial++ {
226                 var stdout, stderr bytes.Buffer
227                 code := CheckCommand.RunCommand("arvados config-check", []string{"-config=-", "-strict=true"}, bytes.NewBufferString(in), &stdout, &stderr)
228                 if !c.Check(code, check.Equals, 0) || stdout.String() != "" || stderr.String() != "" {
229                         c.Logf("config-check returned error or non-empty output on trial %d", trial)
230                         c.Log("stdout:\n", stdout.String())
231                         c.Log("stderr:\n", stderr.String())
232                         c.FailNow()
233                 }
234         }
235 }