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