github.com/MichaelDarr/ahab@v0.0.0-20200528062404-c74c5106e605/internal/config.go (about) 1 package internal 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "path/filepath" 8 ) 9 10 // ConfigFileName holds the name of the config file 11 const ConfigFileName = "ahab.json" 12 13 // UserConfigFilePath holds the path of the user's config file, relative to their home dir 14 const UserConfigFilePath = ".config/ahab/config.json" 15 16 // Version holds the build-time ahab version 17 var Version string 18 19 // Configuration contains docker config fields 20 type Configuration struct { 21 AhabVersion string `json:"ahab"` 22 BuildContext string `json:"buildContext"` 23 Command string `json:"command"` 24 Dockerfile string `json:"dockerfile"` 25 Entrypoint string `json:"entrypoint"` 26 Environment []string `json:"environment"` 27 Hostname string `json:"hostname"` 28 ImageURI string `json:"image"` 29 Init []string `json:"init"` 30 Name string `json:"name"` 31 Options []string `json:"options"` 32 Permissions PermConfiguration `json:"permissions"` 33 RestartAfterSetup bool `json:"restartAfterSetup"` 34 ShareDisplay bool `json:"shareDisplay"` 35 User string `json:"user"` 36 Volumes []string `json:"volumes"` 37 Workdir string `json:"workdir"` 38 } 39 40 // UserConfiguration contains global user config fields 41 type UserConfiguration struct { 42 Environment []string `json:"environment"` 43 Options []string `json:"options"` 44 HideCommands bool `json:"hideCommands"` 45 Volumes []string `json:"volumes"` 46 } 47 48 // PermConfiguration contains information regarding container user permissions setup 49 type PermConfiguration struct { 50 CmdSet string `json:"cmdSet"` 51 Disable bool `json:"disable"` 52 Groups []string `json:"groups"` 53 } 54 55 // UserConfig finds and parses the user's docker config file 56 // If the user's config is not found, an empty userConfig is returned 57 func UserConfig() (userConfig *UserConfiguration, err error) { 58 homeDir, err := os.UserHomeDir() 59 if err != nil { 60 err = fmt.Errorf("Failed to get user home directory: %s", err) 61 return 62 } 63 64 configPath := filepath.Join(homeDir, UserConfigFilePath) 65 configFile, err := os.Open(configPath) 66 if err != nil && os.IsNotExist(err) { 67 var blankConfig UserConfiguration 68 return &blankConfig, nil 69 } 70 defer configFile.Close() 71 72 decoder := json.NewDecoder(configFile) 73 if err = decoder.Decode(&userConfig); err != nil { 74 err = fmt.Errorf("Failed to parse user config file: %s", err) 75 } 76 return 77 } 78 79 // checkConfigVersion returns a non-nil err if the passed version is newer the active dcfg version 80 func checkConfigVersion(configVersion string) error { 81 configVersionOrd, err := versionOrdinal(configVersion) 82 if err != nil { 83 return err 84 } 85 selfVersionOrd, err := versionOrdinal(Version) 86 if err != nil { 87 return err 88 } 89 90 if configVersionOrd > selfVersionOrd { 91 return fmt.Errorf("Config file requires ahab >= %s (your version: %s)", configVersion, Version) 92 } 93 return nil 94 } 95 96 // findConfigPath recursively searches for a config file starting at topDir, ending at fs root 97 func findConfigPath(topDir string) (configPath string, err error) { 98 configTestPath := filepath.Join(topDir, ConfigFileName) 99 _, err = os.Stat(configTestPath) 100 if err != nil && os.IsNotExist(err) && filepath.Clean(topDir) != "/" { 101 configPath, err = findConfigPath(filepath.Join(topDir, "..")) 102 } else if err != nil && os.IsNotExist(err) { 103 err = fmt.Errorf("No config file '%s' found in current or parent directories", ConfigFileName) 104 } else if err != nil { 105 err = fmt.Errorf("Failed to find config file '%s': %s", ConfigFileName, err) 106 } else { 107 configPath = configTestPath 108 } 109 return 110 } 111 112 // return a non-nil error if config is invalid 113 func (config *Configuration) validateConfig() (err error) { 114 if config.AhabVersion == "" { 115 err = fmt.Errorf("Missing required version field 'ahab'") 116 } else if config.ImageURI == "" && config.Dockerfile == "" { 117 err = fmt.Errorf("Either 'image' or 'dockerfile' must be present") 118 } else if config.ImageURI != "" && config.Dockerfile != "" { 119 err = fmt.Errorf("'image' and `dockerfile' cannot both be present") 120 } 121 return 122 }