From 773ae3b46715520c166dac6a381330c352f2d2f2 Mon Sep 17 00:00:00 2001 From: Bryce Palmer Date: Mon, 24 May 2021 09:15:42 -0400 Subject: [PATCH] upgrade command and config file --- config.hcl | 3 + subcommands/install_sc.go | 9 +- subcommands/subcommand.go | 8 +- subcommands/upgrade_sc.go | 264 ++++++++++++++++++++++++++++++++++++++ utils/hcl_parse.go | 66 +++++++--- 5 files changed, 333 insertions(+), 17 deletions(-) create mode 100644 config.hcl create mode 100644 subcommands/upgrade_sc.go diff --git a/config.hcl b/config.hcl new file mode 100644 index 0000000..bdd6237 --- /dev/null +++ b/config.hcl @@ -0,0 +1,3 @@ +base_dir="./" +start_port=3000 +port_increment=1 diff --git a/subcommands/install_sc.go b/subcommands/install_sc.go index c113bee..1ad3c8f 100644 --- a/subcommands/install_sc.go +++ b/subcommands/install_sc.go @@ -35,6 +35,11 @@ func (ic *InstallCommand) Name() string { //Init - Parses and Populates values of the Install subcommand func (ic *InstallCommand) Init(args []string) error { + + if len(args) <= 0 { + return errors.New("No package name was found. You must include the name of the package you wish to install.") + } + ic.name = args[0] return nil } @@ -49,7 +54,9 @@ func (ic *InstallCommand) Run() error { packageList := "./package_list.hcl" //Parse the package list - packages, err := utils.Parse(packageList) + parseOut, err := utils.Parse(packageList, utils.PackageHCLUtil{}) + + packages := parseOut.(utils.PackageHCLUtil) //Check for errors if err != nil { diff --git a/subcommands/subcommand.go b/subcommands/subcommand.go index d44b579..6855e80 100644 --- a/subcommands/subcommand.go +++ b/subcommands/subcommand.go @@ -21,13 +21,19 @@ func SubCommand(args []string) error { cmds := []Runner{ NewInstallCommand(), + NewUpgradeCommand(), } subcommand := os.Args[1] for _, cmd := range cmds { if cmd.Name() == subcommand { - cmd.Init(os.Args[2:]) + err := cmd.Init(os.Args[2:]) + + if err != nil { + return err + } + return cmd.Run() } } diff --git a/subcommands/upgrade_sc.go b/subcommands/upgrade_sc.go new file mode 100644 index 0000000..838a7a0 --- /dev/null +++ b/subcommands/upgrade_sc.go @@ -0,0 +1,264 @@ +package subcommands + +import ( + "errors" + "flag" + "fmt" + "os" + + "github.com/everettraven/packageless/utils" +) + +//Install Sub-Command Object +type UpgradeCommand struct { + //FlagSet so that we can create a custom flag + fs *flag.FlagSet + + //String for the name of the package to install + name string +} + +//Instantiation method for a new InstallCommand +func NewUpgradeCommand() *UpgradeCommand { + //Create a new InstallCommand and set the FlagSet + ic := &UpgradeCommand{ + fs: flag.NewFlagSet("upgrade", flag.ContinueOnError), + } + + return ic +} + +//Name - Gets the name of the Sub-Command +func (ic *UpgradeCommand) Name() string { + return ic.fs.Name() +} + +//Init - Parses and Populates values of the Install subcommand +func (ic *UpgradeCommand) Init(args []string) error { + if len(args) <= 0 { + fmt.Println("No package specified, upgrading all currently installed packages.") + } else { + ic.name = args[0] + fmt.Println("Upgrading", ic.name) + } + return nil +} + +//Run - Runs the install subcommand +func (ic *UpgradeCommand) Run() error { + //Create variables to use later + var found bool + var pack utils.Package + + //Default location of the package list + packageList := "./package_list.hcl" + + //Parse the package list + parseOut, err := utils.Parse(packageList, utils.PackageHCLUtil{}) + + packages := parseOut.(utils.PackageHCLUtil) + + //Check for errors + if err != nil { + return err + } + + if ic.name != "" { + //Look for the package we want in the package list + for _, packs := range packages.Packages { + //If we find it, set some variables and break + if packs.Name == ic.name { + found = true + pack = packs + break + } + } + + //Make sure we have found the package in the package list + if !found { + return errors.New("Could not find package " + ic.name + " in the package list") + } + + //Check if the corresponding package image is already installed + imgExist, err := utils.ImageExists(pack.Image) + + //Check for errors + if err != nil { + return err + } + + //If the image exists the package is already installed + if !imgExist { + return errors.New("Package: " + pack.Name + " is not installed. It must be installed before it can be upgraded.") + } + + fmt.Println("Upgrading", pack.Name) + //Pull the image down from Docker Hub + err = utils.PullImage(pack.Image) + + if err != nil { + return err + } + + fmt.Println("Updating package directories") + + //Check the volumes and create the directories for them if they don't already exist + for _, vol := range pack.Volumes { + //Make sure that a path is given. If not we already assume that the working directory will be mounted + if vol.Path != "" { + if _, err := os.Stat(vol.Path); err != nil { + if os.IsNotExist(err) { + err = os.MkdirAll(vol.Path, 0755) + + if err != nil { + return err + } + } else { + return err + } + } else { + //Remove the directory if it already exists + err = os.RemoveAll(vol.Path) + + if err != nil { + return err + } + + //Recreate the directory + err = os.MkdirAll(vol.Path, 0755) + + if err != nil { + return err + } + } + } + } + + //Check and see if any files need to be copied from the container to one of the volumes on the host. + if len(pack.Copies) > 0 { + + fmt.Println("Copying necessary files 1/3") + //Create the container so that we can copy the files over to the right places + containerID, err := utils.CreateContainer(pack.Image) + + if err != nil { + return err + } + + fmt.Println("Copying necessary files 2/3") + //Copy the files from the container to the locations + for _, copy := range pack.Copies { + err = utils.CopyFromContainer(copy.Source, copy.Dest, containerID) + + if err != nil { + return err + } + } + + fmt.Println("Copying necessary files 3/3") + //Remove the Container + err = utils.RemoveContainer(containerID) + + if err != nil { + return err + } + + fmt.Println(pack.Name, "successfully upgraded") + + } + } else { + //Loop through the packages in the package list + for _, pack := range packages.Packages { + //Check if the corresponding package image is already installed + imgExist, err := utils.ImageExists(pack.Image) + + //Check for errors + if err != nil { + return err + } + + //If the image exists the package is already installed + if !imgExist { + continue + } + + fmt.Println("Upgrading", pack.Name) + //Pull the image down from Docker Hub + err = utils.PullImage(pack.Image) + + if err != nil { + return err + } + + fmt.Println("Updating package directories") + + //Check the volumes and create the directories for them if they don't already exist + for _, vol := range pack.Volumes { + //Make sure that a path is given. If not we already assume that the working directory will be mounted + if vol.Path != "" { + if _, err := os.Stat(vol.Path); err != nil { + if os.IsNotExist(err) { + err = os.MkdirAll(vol.Path, 0755) + + if err != nil { + return err + } + } else { + return err + } + } else { + //Remove the directory if it already exists + err = os.RemoveAll(vol.Path) + + if err != nil { + return err + } + + //Recreate the directory + err = os.MkdirAll(vol.Path, 0755) + + if err != nil { + return err + } + } + } + } + + //Check and see if any files need to be copied from the container to one of the volumes on the host. + if len(pack.Copies) > 0 { + + fmt.Println("Copying necessary files 1/3") + //Create the container so that we can copy the files over to the right places + containerID, err := utils.CreateContainer(pack.Image) + + if err != nil { + return err + } + + fmt.Println("Copying necessary files 2/3") + //Copy the files from the container to the locations + for _, copy := range pack.Copies { + err = utils.CopyFromContainer(copy.Source, copy.Dest, containerID) + + if err != nil { + return err + } + } + + fmt.Println("Copying necessary files 3/3") + //Remove the Container + err = utils.RemoveContainer(containerID) + + if err != nil { + return err + } + + fmt.Println(pack.Name, "successfully upgraded") + } + + } + + } + + return nil +} diff --git a/utils/hcl_parse.go b/utils/hcl_parse.go index 21caaa2..f327696 100644 --- a/utils/hcl_parse.go +++ b/utils/hcl_parse.go @@ -32,29 +32,65 @@ type PackageHCLUtil struct { Packages []Package `hcl:"package,block"` } +//Config object to contain the configuration details +type Config struct { + BaseDir string `hcl:"base_dir,attr"` + StartPort int `hcl:"start_port,attr"` + PortInc int `hcl:"port_increment,attr"` +} + //Parse function to parse the HCL file given in the filepath -func Parse(filepath string) (PackageHCLUtil, error) { +func Parse(filepath string, out interface{}) (interface{}, error) { //Create a parser parser := hclparse.NewParser() - //Create the object to be decoded to - var packages PackageHCLUtil + switch out.(type) { + default: + return nil, errors.New("Unexpected type passed into the HCL parse function") - //Parse the data - parseData, parseDiags := parser.ParseHCLFile(filepath) + case PackageHCLUtil: + //Create the object to be decoded to + var packages PackageHCLUtil - //Check for errors - if parseDiags.HasErrors() { - return packages, errors.New("ParseDiags: " + parseDiags.Error()) - } + //Parse the data + parseData, parseDiags := parser.ParseHCLFile(filepath) + + //Check for errors + if parseDiags.HasErrors() { + return packages, errors.New("ParseDiags: " + parseDiags.Error()) + } + + //Decode the parsed HCL to the Object + decodeDiags := gohcl.DecodeBody(parseData.Body, nil, &packages) + + //Check for errors + if decodeDiags.HasErrors() { + return packages, errors.New("DecodeDiags: " + decodeDiags.Error()) + } + + return packages, nil + + case Config: + //Create the object to be decoded to + var config Config + + //Parse the data + parseData, parseDiags := parser.ParseHCLFile(filepath) + + //Check for errors + if parseDiags.HasErrors() { + return config, errors.New("ParseDiags: " + parseDiags.Error()) + } + + //Decode the parsed HCL to the Object + decodeDiags := gohcl.DecodeBody(parseData.Body, nil, &config) - //Decode the parsed HCL to the Object - decodeDiags := gohcl.DecodeBody(parseData.Body, nil, &packages) + //Check for errors + if decodeDiags.HasErrors() { + return config, errors.New("DecodeDiags: " + decodeDiags.Error()) + } - //Check for errors - if decodeDiags.HasErrors() { - return packages, errors.New("DecodeDiags: " + decodeDiags.Error()) + return config, nil } - return packages, nil }