cmd: Unify the push coding style

- Use 'flags' for the subcommand FlagSet
- Use %v to print errors
- Use 'path' for the path
- Fix cases where the 'path' refers to a different directory
- Don't use CamelCase for command line options

Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
This commit is contained in:
Rolf Neugebauer 2017-06-15 16:35:56 -07:00
parent 684b77d62b
commit 2f212e6c74
6 changed files with 68 additions and 67 deletions

View File

@ -34,7 +34,7 @@ This will output a `azure.vhd` image.
To deploy the `azure.vhd` image on Azure, invoke the following command: To deploy the `azure.vhd` image on Azure, invoke the following command:
``` ```
linuxkit run azure --resourceGroupName <resource-goup-name> --accountName <storageaccountname> --location westeurope <path-to-your-azure.vhd> linuxkit run azure --resource-group <resource-group-name> --storage-account <storage-account-name> --location westeurope <path-to-your-azure.vhd>
``` ```
Sample output of the command: Sample output of the command:

View File

@ -38,11 +38,11 @@ func push(args []string) {
pushAzure(args[1:]) pushAzure(args[1:])
case "gcp": case "gcp":
pushGcp(args[1:]) pushGcp(args[1:])
case "vcenter":
pushVCenter(args[1:])
case "help", "-h", "-help", "--help": case "help", "-h", "-help", "--help":
pushUsage() pushUsage()
os.Exit(0) os.Exit(0)
case "vcenter":
pushVCenter(args[1:])
default: default:
log.Errorf("No 'push' backend specified.") log.Errorf("No 'push' backend specified.")
} }

View File

@ -20,29 +20,29 @@ import (
const timeoutVar = "LINUXKIT_UPLOAD_TIMEOUT" const timeoutVar = "LINUXKIT_UPLOAD_TIMEOUT"
func pushAWS(args []string) { func pushAWS(args []string) {
awsCmd := flag.NewFlagSet("aws", flag.ExitOnError) flags := flag.NewFlagSet("aws", flag.ExitOnError)
invoked := filepath.Base(os.Args[0]) invoked := filepath.Base(os.Args[0])
awsCmd.Usage = func() { flags.Usage = func() {
fmt.Printf("USAGE: %s push aws [options] [name]\n\n", invoked) fmt.Printf("USAGE: %s push aws [options] path\n\n", invoked)
fmt.Printf("'name' specifies the full path of an image file which will be uploaded\n") fmt.Printf("'path' specifies the full path of an AWS image. It will be uploaded to S3 and an AMI will be created from it.\n")
fmt.Printf("Options:\n\n") fmt.Printf("Options:\n\n")
awsCmd.PrintDefaults() flags.PrintDefaults()
} }
timeoutFlag := awsCmd.Int("timeout", 0, "Upload timeout in seconds") timeoutFlag := flags.Int("timeout", 0, "Upload timeout in seconds")
bucketFlag := awsCmd.String("bucket", "", "S3 Bucket to upload to. *Required*") bucketFlag := flags.String("bucket", "", "S3 Bucket to upload to. *Required*")
nameFlag := awsCmd.String("img-name", "", "Overrides the Name used to identify the file in Amazon S3 and Image. Defaults to [name] with the file extension removed.") nameFlag := flags.String("img-name", "", "Overrides the name used to identify the file in Amazon S3 and the VM image. Defaults to the base of 'path' with the file extension removed.")
if err := awsCmd.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args") log.Fatal("Unable to parse args")
} }
remArgs := awsCmd.Args() remArgs := flags.Args()
if len(remArgs) == 0 { if len(remArgs) == 0 {
fmt.Printf("Please specify the path to the image to push\n") fmt.Printf("Please specify the path to the image to push\n")
awsCmd.Usage() flags.Usage()
os.Exit(1) os.Exit(1)
} }
src := remArgs[0] path := remArgs[0]
timeout := getIntValue(timeoutVar, *timeoutFlag, 600) timeout := getIntValue(timeoutVar, *timeoutFlag, 600)
bucket := getStringValue(bucketVar, *bucketFlag, "") bucket := getStringValue(bucketVar, *bucketFlag, "")
@ -55,25 +55,26 @@ func pushAWS(args []string) {
defer cancelFn() defer cancelFn()
if bucket == "" { if bucket == "" {
log.Fatalf("No bucket specified. Please provide one using the -bucket flag") log.Fatalf("Please provide the bucket to use")
} }
f, err := os.Open(src) f, err := os.Open(path)
if err != nil { if err != nil {
log.Fatalf("Error opening file: %s", err) log.Fatalf("Error opening file: %v", err)
} }
defer f.Close() defer f.Close()
if name == "" { if name == "" {
name = strings.TrimSuffix(src, filepath.Ext(src)) name = strings.TrimSuffix(path, filepath.Ext(path))
name = filepath.Base(name)
} }
content, err := ioutil.ReadAll(f) content, err := ioutil.ReadAll(f)
if err != nil { if err != nil {
log.Fatalf("error reading file: %s", err) log.Fatalf("Error reading file: %v", err)
} }
dst := name + filepath.Ext(src) dst := name + filepath.Ext(path)
putParams := &s3.PutObjectInput{ putParams := &s3.PutObjectInput{
Bucket: aws.String(bucket), Bucket: aws.String(bucket),
Key: aws.String(dst), Key: aws.String(dst),
@ -85,7 +86,7 @@ func pushAWS(args []string) {
_, err = storage.PutObjectWithContext(ctx, putParams) _, err = storage.PutObjectWithContext(ctx, putParams)
if err != nil { if err != nil {
log.Fatalf("Error uploading to S3: %s", err) log.Fatalf("Error uploading to S3: %v", err)
} }
compute := ec2.New(sess) compute := ec2.New(sess)
@ -105,7 +106,7 @@ func pushAWS(args []string) {
resp, err := compute.ImportSnapshot(importParams) resp, err := compute.ImportSnapshot(importParams)
if err != nil { if err != nil {
log.Fatalf("Error importing snapshot: %s", err) log.Fatalf("Error importing snapshot: %v", err)
} }
var snapshotID *string var snapshotID *string
@ -118,7 +119,7 @@ func pushAWS(args []string) {
log.Debugf("DescribeImportSnapshotTask:\n%v", describeParams) log.Debugf("DescribeImportSnapshotTask:\n%v", describeParams)
status, err := compute.DescribeImportSnapshotTasks(describeParams) status, err := compute.DescribeImportSnapshotTasks(describeParams)
if err != nil { if err != nil {
log.Fatalf("Error getting import snapshot status: %s", err) log.Fatalf("Error getting import snapshot status: %v", err)
} }
if len(status.ImportSnapshotTasks) == 0 { if len(status.ImportSnapshotTasks) == 0 {
log.Fatalf("Unable to get import snapshot task status") log.Fatalf("Unable to get import snapshot task status")
@ -162,7 +163,7 @@ func pushAWS(args []string) {
log.Debugf("RegisterImage:\n%v", regParams) log.Debugf("RegisterImage:\n%v", regParams)
regResp, err := compute.RegisterImage(regParams) regResp, err := compute.RegisterImage(regParams)
if err != nil { if err != nil {
log.Fatalf("Error registering the image: %s; %s", name, err) log.Fatalf("Error registering the image: %s; %v", name, err)
} }
log.Infof("Created AMI: %s", *regResp.ImageId) log.Infof("Created AMI: %s", *regResp.ImageId)
} }

View File

@ -13,15 +13,15 @@ func pushAzure(args []string) {
flags := flag.NewFlagSet("azure", flag.ExitOnError) flags := flag.NewFlagSet("azure", flag.ExitOnError)
invoked := filepath.Base(os.Args[0]) invoked := filepath.Base(os.Args[0])
flags.Usage = func() { flags.Usage = func() {
fmt.Printf("USAGE: %s push azure [options] name\n\n", invoked) fmt.Printf("USAGE: %s push azure [options] path\n\n", invoked)
fmt.Printf("'imagePath' specifies the path (absolute or relative) of a\n") fmt.Printf("Push a disk image to Azure\n")
fmt.Printf("VHD image be uploaded to an Azure Storage Account\n") fmt.Printf("'path' specifies the path to a VHD. It will be uploaded to an Azure Storage Account.\n")
fmt.Printf("Options:\n\n") fmt.Printf("Options:\n\n")
flags.PrintDefaults() flags.PrintDefaults()
} }
resourceGroupName := flags.String("resourceGroupName", "", "Name of resource group to be used for VM") resourceGroup := flags.String("resource-group", "", "Name of resource group to be used for VM")
accountName := flags.String("accountName", "", "Name of the storage account") accountName := flags.String("storage-account", "", "Name of the storage account")
if err := flags.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args") log.Fatal("Unable to parse args")
@ -29,11 +29,11 @@ func pushAzure(args []string) {
remArgs := flags.Args() remArgs := flags.Args()
if len(remArgs) == 0 { if len(remArgs) == 0 {
fmt.Printf("Please specify the image to push\n") fmt.Printf("Please specify the path to the image to push\n")
flags.Usage() flags.Usage()
os.Exit(1) os.Exit(1)
} }
imagePath := remArgs[0] path := remArgs[0]
subscriptionID := getEnvVarOrExit("AZURE_SUBSCRIPTION_ID") subscriptionID := getEnvVarOrExit("AZURE_SUBSCRIPTION_ID")
tenantID := getEnvVarOrExit("AZURE_TENANT_ID") tenantID := getEnvVarOrExit("AZURE_TENANT_ID")
@ -43,5 +43,5 @@ func pushAzure(args []string) {
initializeAzureClients(subscriptionID, tenantID, clientID, clientSecret) initializeAzureClients(subscriptionID, tenantID, clientID, clientSecret)
uploadVMImage(*resourceGroupName, *accountName, imagePath) uploadVMImage(*resourceGroup, *accountName, path)
} }

View File

@ -5,39 +5,38 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
) )
// Process the run arguments and execute run
func pushGcp(args []string) { func pushGcp(args []string) {
gcpCmd := flag.NewFlagSet("gcp", flag.ExitOnError) flags := flag.NewFlagSet("gcp", flag.ExitOnError)
invoked := filepath.Base(os.Args[0]) invoked := filepath.Base(os.Args[0])
gcpCmd.Usage = func() { flags.Usage = func() {
fmt.Printf("USAGE: %s push gcp [options] [name]\n\n", invoked) fmt.Printf("USAGE: %s push gcp [options] path\n\n", invoked)
fmt.Printf("'name' specifies the full path of an image file which will be uploaded\n") fmt.Printf("'path' is the full path to a GCP image. It will be uploaded to GCS and GCP VM image will be created from it.\n")
fmt.Printf("Options:\n\n") fmt.Printf("Options:\n\n")
gcpCmd.PrintDefaults() flags.PrintDefaults()
} }
keysFlag := gcpCmd.String("keys", "", "Path to Service Account JSON key file") keysFlag := flags.String("keys", "", "Path to Service Account JSON key file")
projectFlag := gcpCmd.String("project", "", "GCP Project Name") projectFlag := flags.String("project", "", "GCP Project Name")
bucketFlag := gcpCmd.String("bucket", "", "GS Bucket to upload to. *Required*") bucketFlag := flags.String("bucket", "", "GCS Bucket to upload to. *Required*")
publicFlag := gcpCmd.Bool("public", false, "Select if file on GS should be public. *Optional*") publicFlag := flags.Bool("public", false, "Select if file on GCS should be public. *Optional*")
familyFlag := gcpCmd.String("family", "", "GCP Image Family. A group of images where the family name points to the most recent image. *Optional*") familyFlag := flags.String("family", "", "GCP Image Family. A group of images where the family name points to the most recent image. *Optional*")
nameFlag := gcpCmd.String("img-name", "", "Overrides the Name used to identify the file in Google Storage and Image. Defaults to [name] with the '.img.tar.gz' suffix removed") nameFlag := flags.String("img-name", "", "Overrides the name used to identify the file in Google Storage and the VM image. Defaults to the base of 'path' with the '.img.tar.gz' suffix removed")
if err := gcpCmd.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args") log.Fatal("Unable to parse args")
} }
remArgs := gcpCmd.Args() remArgs := flags.Args()
if len(remArgs) == 0 { if len(remArgs) == 0 {
fmt.Printf("Please specify the prefix to the image to push\n") fmt.Printf("Please specify the path to the image to push\n")
gcpCmd.Usage() flags.Usage()
os.Exit(1) os.Exit(1)
} }
src := remArgs[0] path := remArgs[0]
suffix := ".img.tar.gz"
keys := getStringValue(keysVar, *keysFlag, "") keys := getStringValue(keysVar, *keysFlag, "")
project := getStringValue(projectVar, *projectFlag, "") project := getStringValue(projectVar, *projectFlag, "")
@ -46,20 +45,22 @@ func pushGcp(args []string) {
family := getStringValue(familyVar, *familyFlag, "") family := getStringValue(familyVar, *familyFlag, "")
name := getStringValue(nameVar, *nameFlag, "") name := getStringValue(nameVar, *nameFlag, "")
client, err := NewGCPClient(keys, project) const suffix = ".img.tar.gz"
if err != nil {
log.Fatalf("Unable to connect to GCP")
}
if name == "" { if name == "" {
name = src[:len(src)-len(suffix)] name = strings.TrimSuffix(path, suffix)
name = filepath.Base(name)
} }
if bucket == "" { if bucket == "" {
log.Fatalf("No bucket specified. Please provide one using the -bucket flag") log.Fatalf("Please specify the bucket to use")
} }
err = client.UploadFile(src, name+suffix, bucket, public) client, err := NewGCPClient(keys, project)
if err != nil {
log.Fatalf("Unable to connect to GCP: %v", err)
}
err = client.UploadFile(path, name+suffix, bucket, public)
if err != nil { if err != nil {
log.Fatalf("Error copying to Google Storage: %v", err) log.Fatalf("Error copying to Google Storage: %v", err)
} }

View File

@ -21,6 +21,12 @@ func pushVCenter(args []string) {
flags := flag.NewFlagSet("vCenter", flag.ExitOnError) flags := flag.NewFlagSet("vCenter", flag.ExitOnError)
invoked := filepath.Base(os.Args[0]) invoked := filepath.Base(os.Args[0])
flags.Usage = func() {
fmt.Printf("USAGE: %s push vcenter [options] path \n\n", invoked)
fmt.Printf("'path' specifies the full path of an ISO image. It will be pushed to a vCenter cluster.\n")
fmt.Printf("Options:\n\n")
flags.PrintDefaults()
}
newVM.vCenterURL = flags.String("url", os.Getenv("VCURL"), "URL of VMware vCenter in the format of https://username:password@VCaddress/sdk") newVM.vCenterURL = flags.String("url", os.Getenv("VCURL"), "URL of VMware vCenter in the format of https://username:password@VCaddress/sdk")
newVM.dsName = flags.String("datastore", os.Getenv("VCDATASTORE"), "The name of the DataStore to host the image") newVM.dsName = flags.String("datastore", os.Getenv("VCDATASTORE"), "The name of the DataStore to host the image")
@ -30,13 +36,6 @@ func pushVCenter(args []string) {
newVM.vmFolder = flags.String("folder", "", "A folder on the datastore to push the image too") newVM.vmFolder = flags.String("folder", "", "A folder on the datastore to push the image too")
flags.Usage = func() {
fmt.Printf("USAGE: %s push vcenter [options] path \n\n", invoked)
fmt.Printf("'path' specifies the full path of an image that will be pushed\n")
fmt.Printf("Options:\n\n")
flags.PrintDefaults()
}
if err := flags.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
log.Fatalln("Unable to parse args") log.Fatalln("Unable to parse args")
} }
@ -51,7 +50,7 @@ func pushVCenter(args []string) {
// Ensure an iso has been passed to the vCenter push Command // Ensure an iso has been passed to the vCenter push Command
if !strings.HasSuffix(*newVM.path, ".iso") { if !strings.HasSuffix(*newVM.path, ".iso") {
log.Fatalln("Please pass an \".iso\" file as the path") log.Fatalln("Please specify an '.iso' file")
} }
// Test any passed in files before uploading image // Test any passed in files before uploading image