Skip to content
This repository has been archived by the owner on Mar 17, 2023. It is now read-only.

install subcommand #1

Merged
merged 1 commit into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
17 changes: 17 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module github.com/everettraven/packageless

go 1.16

require (
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/containerd/containerd v1.5.1 // indirect
github.com/docker/docker v20.10.6+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
google.golang.org/grpc v1.37.1 // indirect
)
947 changes: 947 additions & 0 deletions go.sum

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"fmt"
"os"

"github.com/everettraven/packageless/utils"
)

func main() {
if err := utils.SubCommand(os.Args[1:]); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
16 changes: 16 additions & 0 deletions package_list.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package "python" {
image="packageless/python"
volume {
path="./python/packages/"
mount="/usr/local/lib/python3.9/site-packages/"
}

volume {
mount="/run/"
}

copy {
source="/usr/local/lib/python3.9/site-packages/"
dest="./python/packages/"
}
}
177 changes: 177 additions & 0 deletions utils/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package utils

import (
"archive/tar"
"context"
"io"
"os"
"path/filepath"
"strings"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)

//PullImage - This function pulls a Docker Image from the packageless organization in Docker Hub
func PullImage(name string) error {
//Set up a Docker API client
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

//Check for errors
if err != nil {
return err
}

//Set the context
ctx := context.Background()

//Begin pulling the image
out, err := cli.ImagePull(ctx, name, types.ImagePullOptions{})

//Check for errors
if err != nil {
return err
}

//Close the output buffer after the function exits
defer out.Close()

//Copy the output to the screen
io.Copy(os.Stdout, out)

//No errors
return nil
}

//CreateContainer - Create a Docker Container from a Docker Image. Returns the containerID and any errors
func CreateContainer(image string) (string, error) {
//Create the client
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

//Check for errors
if err != nil {
return "", err
}

//Create the context and create the container
ctx := context.Background()
container, err := cli.ContainerCreate(ctx, &container.Config{Image: image, Cmd: []string{"bash"}}, nil, nil, nil, "")

//Check for errors
if err != nil {
return "", err
}

//No errors
return container.ID, err
}

//CopyFromContainer will copy files from within a Docker Container to the source location on the host
func CopyFromContainer(source string, dest string, containerID string) error {
//Create the Docker client
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

//Check for errors
if err != nil {
return err
}

//Set the context and begin copying from the container
ctx := context.Background()
reader, _, err := cli.CopyFromContainer(ctx, containerID, source)

//Check for errors
if err != nil {
return err
}

//Close the reader after the function ends
defer reader.Close()

//Create a tar Reader
tarReader := tar.NewReader(reader)

//Skip the first header as it is the source folder name
tarReader.Next()

//Loop through the reader and write the files
for {
//Get the tar header
header, err := tarReader.Next()
//Make sure we havent reached the end of the tar
if err == io.EOF {
break
} else if err != nil {
return err
}

newHeaderPath := strings.Split(header.Name, "/")[1:]
joinPath := strings.Join(newHeaderPath[:], "/")

//Create the destination file path on the host
path := filepath.Join(dest, joinPath)
//Get the file info from the header
info := header.FileInfo()

//Check if the current file is a directory
if info.IsDir() {

//Check if the directory exists
if _, err = os.Stat(path); err != nil {
if os.IsNotExist(err) {
//Make the directory
err = os.MkdirAll(path, info.Mode())
} else {
return err
}
}

} else {
//Create the file and open it in the destination path on the host
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())

//Check for errors
if err != nil {
return err
}

//Copy the contents of the tar reader to the file
_, err = io.Copy(file, tarReader)

//Check for errors
if err != nil {
return err
}

//Close the file when all the writing is finished
file.Close()
}

}

return nil
}

//RemoveContainer is used to remove a container Docker given the container ID
func RemoveContainer(containerID string) error {
//Create the Docker API client
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

//Check for errors
if err != nil {
return err
}

//Create the context and remove the container
ctx := context.Background()
err = cli.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{Force: true})

//Check for errors
if err != nil {
return err
}

//No Errors
return nil
}
60 changes: 60 additions & 0 deletions utils/hcl_parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package utils

import (
"errors"

"github.com/hashicorp/hcl2/gohcl"
"github.com/hashicorp/hcl2/hclparse"
)

//Copy object to parse the copy block in the package list
type Copy struct {
Source string `hcl:"source,attr"`
Dest string `hcl:"dest,attr"`
}

//Volume object to parse the volume block in the package list
type Volume struct {
Path string `hcl:"path,optional"`
Mount string `hcl:"mount,attr"`
}

//Package object to parse the package block in the package list
type Package struct {
Name string `hcl:"name,label"`
Image string `hcl:"image,attr"`
Volumes []Volume `hcl:"volume,block"`
Copies []Copy `hcl:"copy,block"`
}

//PackageHCLUtil object to contain a list of packages and all their attributes after the parsing of the package list
type PackageHCLUtil struct {
Packages []Package `hcl:"package,block"`
}

//Parse function to parse the HCL file given in the filepath
func Parse(filepath string) (PackageHCLUtil, error) {
//Create a parser
parser := hclparse.NewParser()

//Create the object to be decoded to
var packages PackageHCLUtil

//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
}
Loading