17464: Update config variables & docs from feedback
[arvados.git] / sdk / go / arvados / config.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package arvados
6
7 import (
8         "encoding/json"
9         "errors"
10         "fmt"
11         "net/url"
12         "os"
13
14         "git.arvados.org/arvados.git/sdk/go/config"
15 )
16
17 var DefaultConfigFile = func() string {
18         if path := os.Getenv("ARVADOS_CONFIG"); path != "" {
19                 return path
20         }
21         return "/etc/arvados/config.yml"
22 }()
23
24 type Config struct {
25         Clusters         map[string]Cluster
26         AutoReloadConfig bool
27 }
28
29 // GetConfig returns the current system config, loading it from
30 // configFile if needed.
31 func GetConfig(configFile string) (*Config, error) {
32         var cfg Config
33         err := config.LoadFile(&cfg, configFile)
34         return &cfg, err
35 }
36
37 // GetCluster returns the cluster ID and config for the given
38 // cluster, or the default/only configured cluster if clusterID is "".
39 func (sc *Config) GetCluster(clusterID string) (*Cluster, error) {
40         if clusterID == "" {
41                 if len(sc.Clusters) == 0 {
42                         return nil, fmt.Errorf("no clusters configured")
43                 } else if len(sc.Clusters) > 1 {
44                         return nil, fmt.Errorf("multiple clusters configured, cannot choose")
45                 } else {
46                         for id, cc := range sc.Clusters {
47                                 cc.ClusterID = id
48                                 return &cc, nil
49                         }
50                 }
51         }
52         cc, ok := sc.Clusters[clusterID]
53         if !ok {
54                 return nil, fmt.Errorf("cluster %q is not configured", clusterID)
55         }
56         cc.ClusterID = clusterID
57         return &cc, nil
58 }
59
60 type WebDAVCacheConfig struct {
61         TTL                  Duration
62         UUIDTTL              Duration
63         MaxBlockEntries      int
64         MaxCollectionEntries int
65         MaxCollectionBytes   int64
66         MaxPermissionEntries int
67         MaxUUIDEntries       int
68         MaxSessions          int
69 }
70
71 type UploadDownloadPermission struct {
72         Upload   bool
73         Download bool
74 }
75
76 type UploadDownloadRolePermissions struct {
77         User  UploadDownloadPermission
78         Admin UploadDownloadPermission
79 }
80
81 type Cluster struct {
82         ClusterID       string `json:"-"`
83         ManagementToken string
84         SystemRootToken string
85         Services        Services
86         InstanceTypes   InstanceTypeMap
87         Containers      ContainersConfig
88         RemoteClusters  map[string]RemoteCluster
89         PostgreSQL      PostgreSQL
90
91         API struct {
92                 AsyncPermissionsUpdateInterval Duration
93                 DisabledAPIs                   StringSet
94                 MaxIndexDatabaseRead           int
95                 MaxItemsPerResponse            int
96                 MaxConcurrentRequests          int
97                 MaxKeepBlobBuffers             int
98                 MaxRequestAmplification        int
99                 MaxRequestSize                 int
100                 MaxTokenLifetime               Duration
101                 RequestTimeout                 Duration
102                 SendTimeout                    Duration
103                 WebsocketClientEventQueue      int
104                 WebsocketServerEventQueue      int
105                 KeepServiceRequestTimeout      Duration
106         }
107         AuditLogs struct {
108                 MaxAge             Duration
109                 MaxDeleteBatch     int
110                 UnloggedAttributes StringSet
111         }
112         Collections struct {
113                 BlobSigning              bool
114                 BlobSigningKey           string
115                 BlobSigningTTL           Duration
116                 BlobTrash                bool
117                 BlobTrashLifetime        Duration
118                 BlobTrashCheckInterval   Duration
119                 BlobTrashConcurrency     int
120                 BlobDeleteConcurrency    int
121                 BlobReplicateConcurrency int
122                 CollectionVersioning     bool
123                 DefaultTrashLifetime     Duration
124                 DefaultReplication       int
125                 ManagedProperties        map[string]struct {
126                         Value     interface{}
127                         Function  string
128                         Protected bool
129                 }
130                 PreserveVersionIfIdle        Duration
131                 TrashSweepInterval           Duration
132                 TrustAllContent              bool
133                 ForwardSlashNameSubstitution string
134                 S3FolderObjects              bool
135
136                 BlobMissingReport        string
137                 BalancePeriod            Duration
138                 BalanceCollectionBatch   int
139                 BalanceCollectionBuffers int
140                 BalanceTimeout           Duration
141
142                 WebDAVCache WebDAVCacheConfig
143
144                 KeepproxyPermission UploadDownloadRolePermissions
145                 WebDAVPermission    UploadDownloadRolePermissions
146                 WebDAVLogEvents     bool
147         }
148         Git struct {
149                 GitCommand   string
150                 GitoliteHome string
151                 Repositories string
152         }
153         Login struct {
154                 LDAP struct {
155                         Enable             bool
156                         URL                URL
157                         StartTLS           bool
158                         InsecureTLS        bool
159                         StripDomain        string
160                         AppendDomain       string
161                         SearchAttribute    string
162                         SearchBindUser     string
163                         SearchBindPassword string
164                         SearchBase         string
165                         SearchFilters      string
166                         EmailAttribute     string
167                         UsernameAttribute  string
168                 }
169                 Google struct {
170                         Enable                          bool
171                         ClientID                        string
172                         ClientSecret                    string
173                         AlternateEmailAddresses         bool
174                         AuthenticationRequestParameters map[string]string
175                 }
176                 OpenIDConnect struct {
177                         Enable                          bool
178                         Issuer                          string
179                         ClientID                        string
180                         ClientSecret                    string
181                         EmailClaim                      string
182                         EmailVerifiedClaim              string
183                         UsernameClaim                   string
184                         AcceptAccessToken               bool
185                         AcceptAccessTokenScope          string
186                         AuthenticationRequestParameters map[string]string
187                 }
188                 PAM struct {
189                         Enable             bool
190                         Service            string
191                         DefaultEmailDomain string
192                 }
193                 SSO struct {
194                         Enable            bool
195                         ProviderAppID     string
196                         ProviderAppSecret string
197                 }
198                 Test struct {
199                         Enable bool
200                         Users  map[string]TestUser
201                 }
202                 LoginCluster       string
203                 RemoteTokenRefresh Duration
204                 TokenLifetime      Duration
205                 TrustedClients     map[string]struct{}
206                 IssueTrustedTokens bool
207         }
208         Mail struct {
209                 MailchimpAPIKey                string
210                 MailchimpListID                string
211                 SendUserSetupNotificationEmail bool
212                 IssueReporterEmailFrom         string
213                 IssueReporterEmailTo           string
214                 SupportEmailAddress            string
215                 EmailFrom                      string
216         }
217         SystemLogs struct {
218                 LogLevel                string
219                 Format                  string
220                 MaxRequestLogParamsSize int
221         }
222         TLS struct {
223                 Certificate string
224                 Key         string
225                 Insecure    bool
226         }
227         Users struct {
228                 AnonymousUserToken                    string
229                 AdminNotifierEmailFrom                string
230                 AutoAdminFirstUser                    bool
231                 AutoAdminUserWithEmail                string
232                 AutoSetupNewUsers                     bool
233                 AutoSetupNewUsersWithRepository       bool
234                 AutoSetupNewUsersWithVmUUID           string
235                 AutoSetupUsernameBlacklist            StringSet
236                 EmailSubjectPrefix                    string
237                 NewInactiveUserNotificationRecipients StringSet
238                 NewUserNotificationRecipients         StringSet
239                 NewUsersAreActive                     bool
240                 UserNotifierEmailFrom                 string
241                 UserProfileNotificationAddress        string
242                 PreferDomainForUsername               string
243                 UserSetupMailText                     string
244         }
245         Volumes   map[string]Volume
246         Workbench struct {
247                 ActivationContactLink            string
248                 APIClientConnectTimeout          Duration
249                 APIClientReceiveTimeout          Duration
250                 APIResponseCompression           bool
251                 ApplicationMimetypesWithViewIcon StringSet
252                 ArvadosDocsite                   string
253                 ArvadosPublicDataDocURL          string
254                 DefaultOpenIdPrefix              string
255                 EnableGettingStartedPopup        bool
256                 EnablePublicProjectsPage         bool
257                 FileViewersConfigURL             string
258                 LogViewerMaxBytes                ByteSize
259                 MultiSiteSearch                  string
260                 ProfilingEnabled                 bool
261                 Repositories                     bool
262                 RepositoryCache                  string
263                 RunningJobLogRecordsToFetch      int
264                 SecretKeyBase                    string
265                 ShowRecentCollectionsOnDashboard bool
266                 ShowUserAgreementInline          bool
267                 ShowUserNotifications            bool
268                 SiteName                         string
269                 Theme                            string
270                 UserProfileFormFields            map[string]struct {
271                         Type                 string
272                         FormFieldTitle       string
273                         FormFieldDescription string
274                         Required             bool
275                         Position             int
276                         Options              map[string]struct{}
277                 }
278                 UserProfileFormMessage string
279                 VocabularyURL          string
280                 WelcomePageHTML        string
281                 InactivePageHTML       string
282                 SSHHelpPageHTML        string
283                 SSHHelpHostSuffix      string
284                 IdleTimeout            Duration
285         }
286 }
287
288 type Volume struct {
289         AccessViaHosts   map[URL]VolumeAccess
290         ReadOnly         bool
291         Replication      int
292         StorageClasses   map[string]bool
293         Driver           string
294         DriverParameters json.RawMessage
295 }
296
297 type S3VolumeDriverParameters struct {
298         IAMRole            string
299         AccessKeyID        string
300         SecretAccessKey    string
301         Endpoint           string
302         Region             string
303         Bucket             string
304         LocationConstraint bool
305         V2Signature        bool
306         UseAWSS3v2Driver   bool
307         IndexPageSize      int
308         ConnectTimeout     Duration
309         ReadTimeout        Duration
310         RaceWindow         Duration
311         UnsafeDelete       bool
312 }
313
314 type AzureVolumeDriverParameters struct {
315         StorageAccountName   string
316         StorageAccountKey    string
317         StorageBaseURL       string
318         ContainerName        string
319         RequestTimeout       Duration
320         ListBlobsRetryDelay  Duration
321         ListBlobsMaxAttempts int
322 }
323
324 type DirectoryVolumeDriverParameters struct {
325         Root      string
326         Serialize bool
327 }
328
329 type VolumeAccess struct {
330         ReadOnly bool
331 }
332
333 type Services struct {
334         Composer       Service
335         Controller     Service
336         DispatchCloud  Service
337         GitHTTP        Service
338         GitSSH         Service
339         Health         Service
340         Keepbalance    Service
341         Keepproxy      Service
342         Keepstore      Service
343         RailsAPI       Service
344         SSO            Service
345         WebDAVDownload Service
346         WebDAV         Service
347         WebShell       Service
348         Websocket      Service
349         Workbench1     Service
350         Workbench2     Service
351 }
352
353 type Service struct {
354         InternalURLs map[URL]ServiceInstance
355         ExternalURL  URL
356 }
357
358 type TestUser struct {
359         Email    string
360         Password string
361 }
362
363 // URL is a url.URL that is also usable as a JSON key/value.
364 type URL url.URL
365
366 // UnmarshalText implements encoding.TextUnmarshaler so URL can be
367 // used as a JSON key/value.
368 func (su *URL) UnmarshalText(text []byte) error {
369         u, err := url.Parse(string(text))
370         if err == nil {
371                 *su = URL(*u)
372                 if su.Path == "" && su.Host != "" {
373                         // http://example really means http://example/
374                         su.Path = "/"
375                 }
376         }
377         return err
378 }
379
380 func (su URL) MarshalText() ([]byte, error) {
381         return []byte(fmt.Sprintf("%s", (*url.URL)(&su).String())), nil
382 }
383
384 func (su URL) String() string {
385         return (*url.URL)(&su).String()
386 }
387
388 type ServiceInstance struct {
389         Rendezvous string `json:",omitempty"`
390 }
391
392 type PostgreSQL struct {
393         Connection     PostgreSQLConnection
394         ConnectionPool int
395 }
396
397 type PostgreSQLConnection map[string]string
398
399 type RemoteCluster struct {
400         Host          string
401         Proxy         bool
402         Scheme        string
403         Insecure      bool
404         ActivateUsers bool
405 }
406
407 type InstanceType struct {
408         Name            string
409         ProviderType    string
410         VCPUs           int
411         RAM             ByteSize
412         Scratch         ByteSize
413         IncludedScratch ByteSize
414         AddedScratch    ByteSize
415         Price           float64
416         Preemptible     bool
417 }
418
419 type ContainersConfig struct {
420         CloudVMs                    CloudVMsConfig
421         CrunchRunCommand            string
422         CrunchRunArgumentsList      []string
423         DefaultKeepCacheRAM         ByteSize
424         DispatchPrivateKey          string
425         LogReuseDecisions           bool
426         MaxComputeVMs               int
427         MaxDispatchAttempts         int
428         MaxRetryAttempts            int
429         MinRetryPeriod              Duration
430         ReserveExtraRAM             ByteSize
431         StaleLockTimeout            Duration
432         SupportedDockerImageFormats StringSet
433         UsePreemptibleInstances     bool
434         RuntimeEngine               string
435
436         JobsAPI struct {
437                 Enable         string
438                 GitInternalDir string
439         }
440         Logging struct {
441                 MaxAge                       Duration
442                 LogBytesPerEvent             int
443                 LogSecondsBetweenEvents      Duration
444                 LogThrottlePeriod            Duration
445                 LogThrottleBytes             int
446                 LogThrottleLines             int
447                 LimitLogBytesPerJob          int
448                 LogPartialLineThrottlePeriod Duration
449                 LogUpdatePeriod              Duration
450                 LogUpdateSize                ByteSize
451         }
452         ShellAccess struct {
453                 Admin bool
454                 User  bool
455         }
456         SLURM struct {
457                 PrioritySpread             int64
458                 SbatchArgumentsList        []string
459                 SbatchEnvironmentVariables map[string]string
460                 Managed                    struct {
461                         DNSServerConfDir       string
462                         DNSServerConfTemplate  string
463                         DNSServerReloadCommand string
464                         DNSServerUpdateCommand string
465                         ComputeNodeDomain      string
466                         ComputeNodeNameservers StringSet
467                         AssignNodeHostname     string
468                 }
469         }
470 }
471
472 type CloudVMsConfig struct {
473         Enable bool
474
475         BootProbeCommand               string
476         DeployRunnerBinary             string
477         ImageID                        string
478         MaxCloudOpsPerSecond           int
479         MaxProbesPerSecond             int
480         MaxConcurrentInstanceCreateOps int
481         PollInterval                   Duration
482         ProbeInterval                  Duration
483         SSHPort                        string
484         SyncInterval                   Duration
485         TimeoutBooting                 Duration
486         TimeoutIdle                    Duration
487         TimeoutProbe                   Duration
488         TimeoutShutdown                Duration
489         TimeoutSignal                  Duration
490         TimeoutStaleRunLock            Duration
491         TimeoutTERM                    Duration
492         ResourceTags                   map[string]string
493         TagKeyPrefix                   string
494
495         Driver           string
496         DriverParameters json.RawMessage
497 }
498
499 type InstanceTypeMap map[string]InstanceType
500
501 var errDuplicateInstanceTypeName = errors.New("duplicate instance type name")
502
503 // UnmarshalJSON handles old config files that provide an array of
504 // instance types instead of a hash.
505 func (it *InstanceTypeMap) UnmarshalJSON(data []byte) error {
506         fixup := func(t InstanceType) (InstanceType, error) {
507                 if t.ProviderType == "" {
508                         t.ProviderType = t.Name
509                 }
510                 if t.Scratch == 0 {
511                         t.Scratch = t.IncludedScratch + t.AddedScratch
512                 } else if t.AddedScratch == 0 {
513                         t.AddedScratch = t.Scratch - t.IncludedScratch
514                 } else if t.IncludedScratch == 0 {
515                         t.IncludedScratch = t.Scratch - t.AddedScratch
516                 }
517
518                 if t.Scratch != (t.IncludedScratch + t.AddedScratch) {
519                         return t, fmt.Errorf("InstanceType %q: Scratch != (IncludedScratch + AddedScratch)", t.Name)
520                 }
521                 return t, nil
522         }
523
524         if len(data) > 0 && data[0] == '[' {
525                 var arr []InstanceType
526                 err := json.Unmarshal(data, &arr)
527                 if err != nil {
528                         return err
529                 }
530                 if len(arr) == 0 {
531                         *it = nil
532                         return nil
533                 }
534                 *it = make(map[string]InstanceType, len(arr))
535                 for _, t := range arr {
536                         if _, ok := (*it)[t.Name]; ok {
537                                 return errDuplicateInstanceTypeName
538                         }
539                         t, err := fixup(t)
540                         if err != nil {
541                                 return err
542                         }
543                         (*it)[t.Name] = t
544                 }
545                 return nil
546         }
547         var hash map[string]InstanceType
548         err := json.Unmarshal(data, &hash)
549         if err != nil {
550                 return err
551         }
552         // Fill in Name field (and ProviderType field, if not
553         // specified) using hash key.
554         *it = InstanceTypeMap(hash)
555         for name, t := range *it {
556                 t.Name = name
557                 t, err := fixup(t)
558                 if err != nil {
559                         return err
560                 }
561                 (*it)[name] = t
562         }
563         return nil
564 }
565
566 type StringSet map[string]struct{}
567
568 // UnmarshalJSON handles old config files that provide an array of
569 // instance types instead of a hash.
570 func (ss *StringSet) UnmarshalJSON(data []byte) error {
571         if len(data) > 0 && data[0] == '[' {
572                 var arr []string
573                 err := json.Unmarshal(data, &arr)
574                 if err != nil {
575                         return err
576                 }
577                 if len(arr) == 0 {
578                         *ss = nil
579                         return nil
580                 }
581                 *ss = make(map[string]struct{}, len(arr))
582                 for _, t := range arr {
583                         (*ss)[t] = struct{}{}
584                 }
585                 return nil
586         }
587         var hash map[string]struct{}
588         err := json.Unmarshal(data, &hash)
589         if err != nil {
590                 return err
591         }
592         *ss = make(map[string]struct{}, len(hash))
593         for t := range hash {
594                 (*ss)[t] = struct{}{}
595         }
596
597         return nil
598 }
599
600 type ServiceName string
601
602 const (
603         ServiceNameRailsAPI      ServiceName = "arvados-api-server"
604         ServiceNameController    ServiceName = "arvados-controller"
605         ServiceNameDispatchCloud ServiceName = "arvados-dispatch-cloud"
606         ServiceNameHealth        ServiceName = "arvados-health"
607         ServiceNameWorkbench1    ServiceName = "arvados-workbench1"
608         ServiceNameWorkbench2    ServiceName = "arvados-workbench2"
609         ServiceNameWebsocket     ServiceName = "arvados-ws"
610         ServiceNameKeepbalance   ServiceName = "keep-balance"
611         ServiceNameKeepweb       ServiceName = "keep-web"
612         ServiceNameKeepproxy     ServiceName = "keepproxy"
613         ServiceNameKeepstore     ServiceName = "keepstore"
614 )
615
616 // Map returns all services as a map, suitable for iterating over all
617 // services or looking up a service by name.
618 func (svcs Services) Map() map[ServiceName]Service {
619         return map[ServiceName]Service{
620                 ServiceNameRailsAPI:      svcs.RailsAPI,
621                 ServiceNameController:    svcs.Controller,
622                 ServiceNameDispatchCloud: svcs.DispatchCloud,
623                 ServiceNameHealth:        svcs.Health,
624                 ServiceNameWorkbench1:    svcs.Workbench1,
625                 ServiceNameWorkbench2:    svcs.Workbench2,
626                 ServiceNameWebsocket:     svcs.Websocket,
627                 ServiceNameKeepbalance:   svcs.Keepbalance,
628                 ServiceNameKeepweb:       svcs.WebDAV,
629                 ServiceNameKeepproxy:     svcs.Keepproxy,
630                 ServiceNameKeepstore:     svcs.Keepstore,
631         }
632 }