diff --git a/README.md b/README.md index 1f0d065..f501b99 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Odoo-one-click, help you to setup your odoo instances with just 1 command. - [x] Command init to prepare dependencies and requirement to run odoo - [x] Setup and configure postgresql to run odoo without using root - [x] Add some flags to customize your odoo installation +- [x] Add validation on which OS can run the app - [ ] Add new command `run` to help run existing odoo instances - [ ] Make it available to other OSes (Mac, and other linux distributions) @@ -37,26 +38,26 @@ Odoo-one-click, help you to setup your odoo instances with just 1 command. > NOTE: By default, this command will install odoo 15 community with python3.8.13 - You can also customize your installation by using flags ```sh - odoo-one-click install --odoo-version 13.0 --enterprise --python 3.7.4 + odoo-one-click install --odoo 13.0 --enterprise --python 3.7.4 odoo13 ``` - Command above will install odoo 13 enterprise with python3.7.4 + Command above will install odoo 13 enterprise with python3.7.4, and the instance name will be `odoo13` - For other available flags, you can run `odoo-one-click install --help` ```sh odoo-one-click install --help - ``` - ```sh - Install and configure odoo with demo data + + Install and configure odoo Usage: - odoo-one-click install [flags] + odoo-one-click install [flags] directory_name Flags: - -d, --db-name string Database name to create or use - -e, --enterprise Install odoo enterprise - -h, --help help for install - -o, --odoo-version string Odoo version to install - -p, --python-version string Python version to use + -d, --db-name string Database name to create or use + -e, --enterprise Install odoo enterprise + -h, --help help for install + -o, --odoo string Odoo version to install + -p, --python string Python version to use Global Flags: - -V, --verbose Print logs to stdout - ``` \ No newline at end of file + -v, --verbose Print logs to stdout + ``` + > NOTE: directory_name here is optional, if you have more than 1 instances with the same odoo version, you need to specify the directory name so it won't conflict with the other instance \ No newline at end of file diff --git a/cmd/install.go b/cmd/install.go index bf4dd37..d206e14 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -24,17 +24,26 @@ var ghToken string func init() { installCmd.Flags().BoolVarP(&isEnterprise, "enterprise", "e", false, "Install odoo enterprise") - installCmd.Flags().StringVarP(&odooVer, "odoo-version", "o", "", "Odoo version to install") + installCmd.Flags().StringVarP(&odooVer, "odoo", "o", "", "Odoo version to install") installCmd.Flags().StringVarP(&dbName, "db-name", "d", "", "Database name to create or use") - installCmd.Flags().StringVarP(&pythonVer, "python-version", "p", "", "Python version to use") + installCmd.Flags().StringVarP(&pythonVer, "python", "p", "", "Python version to use") rootCmd.AddCommand(installCmd) } var installCmd = &cobra.Command{ - Use: "install", + Use: "install [flags] directory_name", Short: "Install and configure odoo", - Long: "Install and configure odoo with demo data", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) > 1 { + return fmt.Errorf("too many arguments") + } + if len(args) == 1 && !utils.IsValidDirName(args[0]) { + return fmt.Errorf("invalid directory name") + } + + return nil + }, Run: func(cmd *cobra.Command, args []string) { if !config.Verbose { // TODO: create 1 log file for the project to use; can be extended to log to a file @@ -46,11 +55,11 @@ var installCmd = &cobra.Command{ reader := bufio.NewReader(os.Stdin) fmt.Print("Enter github username: ") ghUsername, _ = reader.ReadString('\n') - ghUsername = strings.Replace(ghUsername, "\n", "", -1) + ghUsername = utils.RemoveNewLine(ghUsername) fmt.Print("Enter github token: ") ghToken, _ = reader.ReadString('\n') - ghToken = strings.Replace(ghToken, "\n", "", -1) + ghToken = utils.RemoveNewLine(ghToken) } if odooVer == "" { @@ -63,8 +72,13 @@ var installCmd = &cobra.Command{ if pythonVer == "" { pythonVer = utils.GetPythonBasedOdooVer(odooVer) } + dirName := utils.DirName(odooVer, isEnterprise) + + if len(args) == 1 { + dirName = args[0] + } - installConf := NewInstallConf(isEnterprise, odooVer, pythonVer, dbName, ghUsername, ghToken) + installConf := NewInstallConf(isEnterprise, odooVer, pythonVer, dbName, ghUsername, ghToken, dirName) installConf.InstallOdoo() }, } @@ -76,9 +90,10 @@ type InstallConf struct { dbName string // Database name for odoo ghUsername string // when is_enterprise is true, need to fill this username ghToken string // when is_enterprise is true, need to fill this token + dirName string // where odoo want to be installed } -func NewInstallConf(isEnterprise bool, odooVer, pythonVer, dbName, ghUser, ghToken string) *InstallConf { +func NewInstallConf(isEnterprise bool, odooVer, pythonVer, dbName, ghUser, ghToken, dirName string) *InstallConf { if isEnterprise && (ghUser == "" || ghToken == "") { log.Fatalln("Please provide github username and token to clone odoo enterprise.") } @@ -89,6 +104,7 @@ func NewInstallConf(isEnterprise bool, odooVer, pythonVer, dbName, ghUser, ghTok dbName: dbName, ghUsername: ghUser, ghToken: ghToken, + dirName: dirName, } } @@ -125,6 +141,9 @@ func (ic InstallConf) InstallOdoo() { if err != nil { log.Println("Create odoo conf: ", err) } + + dirName := utils.DirName(ic.odooVer, ic.isEnterprise) + fmt.Printf("Your odoo %s is ready to use at\n%s\n", dirName, config.OdooDir()+"/"+ic.dirName) } func (ic InstallConf) cloneOdooCommunity() error { @@ -139,16 +158,14 @@ func (ic InstallConf) cloneOdooCommunity() error { return err } - dirName := utils.DirName(ic.odooVer, ic.isEnterprise) - - err = exec.Command("git", "clone", "https://github.com/odoo/odoo", "--branch", ic.odooVer, "--depth", "1", dirName).Run() + err = exec.Command("git", "clone", "https://github.com/odoo/odoo", "--branch", ic.odooVer, "--depth", "1", ic.dirName).Run() if err != nil { if !strings.Contains(err.Error(), "exit status 128") { return err } } - err = os.Chdir(config.OdooDir() + "/" + dirName) + err = os.Chdir(config.OdooDir() + "/" + ic.dirName) if err != nil { return err } @@ -183,21 +200,20 @@ func (ic InstallConf) initPyenv() error { } } - dirName := utils.DirName(ic.odooVer, ic.isEnterprise) - isVenvCreated, err := utils.CheckVenvCreated(dirName) + isVenvCreated, err := utils.CheckVenvCreated(ic.dirName) if err != nil { log.Println(err) } if !isVenvCreated { - err = exec.Command("pyenv", "virtualenv", ic.pythonVer, dirName).Run() + err = exec.Command("pyenv", "virtualenv", ic.pythonVer, ic.dirName).Run() if err != nil { log.Println("Error on create venv: ", err) return err } } - err = exec.Command("pyenv", "local", dirName).Run() + err = exec.Command("pyenv", "local", ic.dirName).Run() if err != nil { return err } @@ -231,12 +247,13 @@ db_port = 5432 db_user = %s db_password = %s db_name = %s -addons_path = ./addons, ./odoo/addons -`, config.DBUsername(), config.DB_PASSWORD, ic.dbName) +addons_path = ./addons, ./odoo/addons`, config.DBUsername(), config.DB_PASSWORD, ic.dbName) if ic.isEnterprise { // When it's enterprise, add enterprise addons path to odoo.conf - confFile = confFile + ", ./enterprise" + confFile = confFile + ", ./enterprise\n" + } else { + confFile = confFile + "\n" } err := ioutil.WriteFile("odoo.conf", []byte(confFile), 0644) diff --git a/cmd/root.go b/cmd/root.go index a78c638..dc91058 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -28,7 +28,7 @@ var rootCmd = &cobra.Command{ } func Execute() { - rootCmd.PersistentFlags().BoolVarP(&config.Verbose, "verbose", "V", false, "Print logs to stdout") + rootCmd.PersistentFlags().BoolVarP(&config.Verbose, "verbose", "v", false, "Print logs to stdout") rootCmd.SetVersionTemplate(fmt.Sprintf("Odoo one-click v%s\n", config.VERSION)) if err := rootCmd.Execute(); err != nil { diff --git a/config/constant.go b/config/constant.go index 11ce529..db3f489 100644 --- a/config/constant.go +++ b/config/constant.go @@ -29,3 +29,15 @@ func OdooDir() string { home, _ := os.UserHomeDir() return home + "/odoo" } + +var allowedOS = map[string]bool{ + "focal": true, + "groovy": true, + "hirsute": true, + "impish": true, + "jammy": true, +} + +func IsAllowedOS(os string) bool { + return allowedOS[os] +} diff --git a/main.go b/main.go index ef4b045..980bb9e 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,42 @@ package main import ( + "fmt" "odoo-one-click/cmd" + "odoo-one-click/config" + "odoo-one-click/utils" + "os" + "os/exec" + "runtime" ) func main() { - // TODO: add validation to check if the OS is ubuntu or derivatives - // on elementary, there is UPSTREAM lsb-release, but it seemms not on all derivatives + // OS Check, for now it's only for ubuntu and derivatives + if runtime.GOOS != "linux" { + fmt.Println("This program only works on Ubuntu or derivatives") + os.Exit(1) + } else { + // Check if UBUNTU_CODENAME is on allowedOS + if err := checkOSVersion(); err != nil { + fmt.Println(err) + os.Exit(1) + } + } + cmd.Execute() } + +func checkOSVersion() error { + out, err := exec.Command("bash", "-c", "source /etc/os-release; echo $UBUNTU_CODENAME").Output() + if err != nil { + return err + } + + // check if UBUNTU_CODENAME on allowedOS + codename := utils.RemoveNewLine(string(out)) + if !config.IsAllowedOS(codename) { + return fmt.Errorf("ubuntu version is not supported") + } + + return nil +} diff --git a/utils/helper.go b/utils/helper.go index d064481..474ce1a 100644 --- a/utils/helper.go +++ b/utils/helper.go @@ -63,3 +63,24 @@ func GetPythonBasedOdooVer(odooVer string) string { return "3.8.13" } + +func RemoveNewLine(data string) string { + return strings.Replace(data, "\n", "", -1) +} + +func IsValidDirName(dirName string) bool { + if dirName == "" { + return false + } + if strings.Contains(dirName, " ") { + return false + } + if strings.Contains(dirName, "/") { + return false + } + if strings.HasPrefix(dirName, ".") { + return false + } + + return true +}