github.com/hazelops/ize@v1.1.12-0.20230915191306-97d7c0e48f11/internal/requirements/requirements.go (about)

     1  package requirements
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/Masterminds/semver"
     7  	"github.com/pterm/pterm"
     8  	"github.com/sirupsen/logrus"
     9  	"github.com/spf13/viper"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  )
    14  
    15  type requirements struct {
    16  	configFile bool
    17  	ssmplugin  bool
    18  	structure  bool
    19  	nvm        bool
    20  }
    21  
    22  func CheckRequirements(options ...Option) error {
    23  	r := requirements{}
    24  	for _, opt := range options {
    25  		opt(&r)
    26  	}
    27  
    28  	if r.nvm {
    29  		err := checkNVM()
    30  		if err != nil {
    31  			return err
    32  		}
    33  	}
    34  
    35  	if r.structure {
    36  		if !isStructured() {
    37  			pterm.Warning.Println("is not an ize-structured directory. Please run ize init or cd into an ize-structured directory.")
    38  		}
    39  	}
    40  
    41  	if r.ssmplugin {
    42  		if err := checkSessionManagerPlugin(); err != nil {
    43  			return err
    44  		}
    45  	}
    46  
    47  	switch viper.GetString("prefer_runtime") {
    48  	case "native":
    49  		logrus.Debug("use native runtime")
    50  	case "docker":
    51  		if err := checkDocker(); err != nil {
    52  			return err
    53  		}
    54  		logrus.Debug("use docker runtime")
    55  	default:
    56  		return fmt.Errorf("unknown runtime type: %s", viper.GetString("prefer_runtime"))
    57  	}
    58  
    59  	if len(viper.ConfigFileUsed()) == 0 && r.configFile {
    60  		return fmt.Errorf("this command requires a config file. Please add ize.toml to %s", viper.GetString("env_dir"))
    61  	}
    62  
    63  	return nil
    64  }
    65  
    66  type Option func(*requirements)
    67  
    68  func WithIzeStructure() Option {
    69  	return func(r *requirements) {
    70  		r.structure = true
    71  	}
    72  }
    73  
    74  func WithConfigFile() Option {
    75  	return func(r *requirements) {
    76  		r.configFile = true
    77  	}
    78  }
    79  
    80  func WithSSMPlugin() Option {
    81  	return func(r *requirements) {
    82  		r.ssmplugin = true
    83  	}
    84  }
    85  
    86  func WithNVM() Option {
    87  	return func(r *requirements) {
    88  		r.nvm = true
    89  	}
    90  }
    91  
    92  func checkNVM() error {
    93  	if len(os.Getenv("NVM_DIR")) == 0 {
    94  		return errors.New("nvm is not installed (visit https://github.com/nvm-sh/nvm)")
    95  	}
    96  
    97  	return nil
    98  }
    99  
   100  func checkDocker() error {
   101  	exist, _ := CheckCommand("docker", []string{"info"})
   102  	if !exist {
   103  		return errors.New("docker is not running or is not installed (visit https://www.docker.com/get-started)")
   104  	}
   105  
   106  	return nil
   107  }
   108  
   109  func isStructured() bool {
   110  	var isStructured = false
   111  
   112  	cwd, err := os.Getwd()
   113  	if err != nil {
   114  		logrus.Fatalln("can't initialize config: %w", err)
   115  	}
   116  
   117  	_, err = os.Stat(filepath.Join(cwd, ".ize"))
   118  	if !os.IsNotExist(err) {
   119  		isStructured = true
   120  	}
   121  
   122  	_, err = os.Stat(filepath.Join(cwd, ".infra"))
   123  	if !os.IsNotExist(err) {
   124  		isStructured = true
   125  	}
   126  
   127  	return isStructured
   128  }
   129  
   130  func checkSessionManagerPlugin() error {
   131  	exist, _ := CheckCommand("session-manager-plugin", []string{})
   132  	if !exist {
   133  		pterm.Warning.Println("SSM Agent plugin is not installed. Trying to install SSM Agent plugin")
   134  
   135  		var pyVersion string
   136  
   137  		exist, pyVersion := CheckCommand("python3", []string{"--version"})
   138  		if !exist {
   139  			exist, pyVersion = CheckCommand("python", []string{"--version"})
   140  			if !exist {
   141  				return errors.New("python is not installed")
   142  			}
   143  
   144  			c, err := semver.NewConstraint("<= 2.6.5")
   145  			if err != nil {
   146  				return err
   147  			}
   148  
   149  			v, err := semver.NewVersion(strings.TrimSpace(strings.Split(pyVersion, " ")[1]))
   150  			if err != nil {
   151  				return err
   152  			}
   153  
   154  			if c.Check(v) {
   155  				return fmt.Errorf("python version %s below required %s", v.String(), "2.6.5")
   156  			}
   157  			return errors.New("python is not installed")
   158  		}
   159  
   160  		c, err := semver.NewConstraint("<= 3.3.0")
   161  		if err != nil {
   162  			return err
   163  		}
   164  
   165  		v, err := semver.NewVersion(strings.TrimSpace(strings.Split(pyVersion, " ")[1]))
   166  		if err != nil {
   167  			return err
   168  		}
   169  
   170  		if c.Check(v) {
   171  			return fmt.Errorf("python version %s below required %s", v.String(), "3.3.0")
   172  		}
   173  
   174  		pterm.DefaultSection.Println("Installing SSM Agent plugin")
   175  
   176  		err = downloadSSMAgentPlugin()
   177  		if err != nil {
   178  			return fmt.Errorf("download SSM Agent plugin error: %v (visit https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)", err)
   179  		}
   180  
   181  		pterm.Success.Println("Downloading SSM Agent plugin")
   182  
   183  		err = installSSMAgent()
   184  		if err != nil {
   185  			return fmt.Errorf("install SSM Agent plugin error: %v (visit https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)", err)
   186  		}
   187  
   188  		pterm.Success.Println("Installing SSM Agent plugin")
   189  
   190  		err = cleanupSSMAgent()
   191  		if err != nil {
   192  			return fmt.Errorf("cleanup SSM Agent plugin error: %v (visit https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)", err)
   193  		}
   194  
   195  		pterm.Success.Println("Cleanup Session Manager plugin installation package")
   196  
   197  		exist, _ = CheckCommand("session-manager-plugin", []string{})
   198  		if !exist {
   199  			return fmt.Errorf("check SSM Agent plugin error: %v (visit https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)", err)
   200  		}
   201  	}
   202  
   203  	return nil
   204  }