Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI support for subnets #275

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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: 0 additions & 1 deletion cmd/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ func init() {
instanceCreateCmd.Flags().StringVarP(&network, "network", "r", "", "the instance's network you can use the Name or the ID")
instanceCreateCmd.Flags().StringVarP(&firewall, "firewall", "l", "", "the instance's firewall you can use the Name or the ID")
instanceCreateCmd.Flags().StringVarP(&tags, "tags", "g", "", "the instance's tags")
instanceCreateCmd.Flags().StringVarP(&tags, "region", "e", "", "the region code identifier to have your instance built in")
instanceCreateCmd.Flags().StringVar(&script, "script", "", "path to a script that will be uploaded to /usr/local/bin/civo-user-init-script on your instance, read/write/executable only by root and then will be executed at the end of the cloud initialization")
instanceCreateCmd.Flags().BoolVar(&skipShebangCheck, "skip-shebang-check", false, "skip the shebang line check when passing a user init script")

Expand Down
13 changes: 5 additions & 8 deletions cmd/instance/instance_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,26 @@ If you wish to use a custom format, the available fields are:
for _, instance := range instances {
ow.StartLine()

ow.AppendDataWithLabel("id", instance.ID, "ID")
ow.AppendDataWithLabel("id", utility.TruncateID(instance.ID), "ID")
ow.AppendDataWithLabel("hostname", instance.Hostname, "Hostname")
ow.AppendDataWithLabel("region", client.Region, "Region")
ow.AppendDataWithLabel("size", instance.Size, "Size")
ow.AppendDataWithLabel("cpu_cores", strconv.Itoa(instance.CPUCores), "Cpu Cores")
ow.AppendDataWithLabel("ram_mb", strconv.Itoa(instance.RAMMegabytes), "Ram")
ow.AppendDataWithLabel("disk_gb", strconv.Itoa(instance.DiskGigabytes), "SSD disk")
ow.AppendDataWithLabel("public_ip", instance.PublicIP, "Public IP")
ow.AppendDataWithLabel("private_ip", instance.PrivateIP, "Private IP")
ow.AppendDataWithLabel("ipv6", instance.IPv6, "IPv6")
ow.AppendDataWithLabel("status", utility.ColorStatus(instance.Status), "Status")

if common.OutputFormat == "json" || common.OutputFormat == "custom" {
ow.AppendDataWithLabel("network_id", instance.NetworkID, "Network ID")
// ow.AppendDataWithLabel("PrivateIP", instance.PrivateIP, "")
// ow.AppendDataWithLabel("PublicIP", instance.PublicIP, "")
ow.AppendDataWithLabel("cpu_cores", strconv.Itoa(instance.CPUCores), "Cpu Cores")
ow.AppendDataWithLabel("ram_mb", strconv.Itoa(instance.RAMMegabytes), "Ram")
ow.AppendDataWithLabel("disk_gb", strconv.Itoa(instance.DiskGigabytes), "SSD disk")
ow.AppendDataWithLabel("diskimage_id", instance.SourceID, "Disk image ID")
ow.AppendDataWithLabel("initial_user", instance.InitialUser, "Initial User")
ow.AppendDataWithLabel("ssh_key", instance.SSHKey, "SSH Key")
ow.AppendDataWithLabel("notes", instance.Notes, "Notes")
ow.AppendDataWithLabel("firewall_id", instance.FirewallID, "Firewall ID")
ow.AppendDataWithLabel("tags", strings.Join(instance.Tags, " "), "Tags")
// ow.AppendDataWithLabel("CivostatsdToken", instance.CivostatsdToken, "")
// ow.AppendDataWithLabel("CivostatsdStats", instance.CivostatsdStats, "")
ow.AppendDataWithLabel("script", instance.Script, "Script")
ow.AppendDataWithLabel("created_at", instance.CreatedAt.Format(time.RFC1123), "Created At")
ow.AppendDataWithLabel("status", instance.Status, "Status")
Expand Down
38 changes: 38 additions & 0 deletions cmd/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"github.com/spf13/cobra"
)

var v4enabled, v6enabled bool
var cidrv4 string

// NetworkCmd manages Civo networks
var NetworkCmd = &cobra.Command{
Use: "network",
Expand All @@ -20,9 +23,44 @@ var NetworkCmd = &cobra.Command{
},
}

var networkSubnetCmd = &cobra.Command{
Use: "subnet",
Aliases: []string{"subnets"},
Short: "Details of Civo network subnets",
RunE: func(cmd *cobra.Command, args []string) error {
err := cmd.Help()
if err != nil {
return err
}
return errors.New("a valid subcommand is required")
},
}

func init() {
NetworkCmd.AddCommand(networkListCmd)
NetworkCmd.AddCommand(networkCreateCmd)
NetworkCmd.AddCommand(networkUpdateCmd)
NetworkCmd.AddCommand(networkRemoveCmd)
NetworkCmd.AddCommand(networkSubnetCmd)

networkCreateCmd.Flags().BoolVarP(&v4enabled, "v4", "", true, "Enable IPv4 on the network")
networkCreateCmd.Flags().BoolVarP(&v6enabled, "v6", "", false, "Enable IPv6 on the network")
networkCreateCmd.Flags().StringVarP(&cidrv4, "cidr-v4", "c", "", "The CIDR for the IPv4 network")

networkSubnetCmd.AddCommand(networkSubnetListCmd)
networkSubnetCmd.AddCommand(networkSubnetCreateCmd)
networkSubnetCmd.AddCommand(networkSubnetShowCmd)
networkSubnetCmd.AddCommand(networkSubnetRemoveCmd)
networkSubnetCmd.AddCommand(networkSubnetAttachCmd)
networkSubnetCmd.AddCommand(networkSubnetDetachCmd)

networkSubnetAttachCmd.Flags().StringVarP(&subnetID, "subnet", "", "", "the id of subnet you want to attach to the instance")
networkSubnetAttachCmd.Flags().StringVarP(&instanceID, "instance", "", "", "the id of instance you want to attach your subnet to")
networkSubnetAttachCmd.MarkFlagRequired("subnet")
networkSubnetAttachCmd.MarkFlagRequired("instance")

networkSubnetDetachCmd.Flags().StringVarP(&subnetID, "subnet", "", "", "the id of subnet you want to attach to the instance")
networkSubnetDetachCmd.Flags().StringVarP(&instanceID, "instance", "", "", "the id of instance you want to attach your subnet to")
networkSubnetDetachCmd.MarkFlagRequired("subnet")
networkSubnetDetachCmd.MarkFlagRequired("instance")
}
18 changes: 16 additions & 2 deletions cmd/network/network_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"

"github.com/civo/civogo"
"github.com/civo/cli/common"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
Expand All @@ -28,9 +29,22 @@ var networkCreateCmd = &cobra.Command{
os.Exit(1)
}

network, err := client.NewNetwork(args[0])
var network *civogo.NetworkResult

nc := civogo.NetworkConfig{
Label: args[0],
Region: client.Region,
IPv4Enabled: &v4enabled,
IPv6Enabled: &v6enabled,
}

if cidrv4 != "" {
nc.CIDRv4 = cidrv4
}

network, err = client.CreateNetwork(nc)
if err != nil {
utility.Error("%s", err)
utility.Error("Error creating the network: %s", err)
os.Exit(1)
}

Expand Down
2 changes: 2 additions & 0 deletions cmd/network/network_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ If you wish to use a custom format, the available fields are:
ow.AppendDataWithLabel("id", network.ID, "ID")
ow.AppendDataWithLabel("label", network.Label, "Label")
ow.AppendDataWithLabel("region", client.Region, "Region")
ow.AppendDataWithLabel("ipv4_enabled", strconv.FormatBool(network.IPv4Enabled), "IPv4 Enabled")
ow.AppendDataWithLabel("ipv6_enabled", strconv.FormatBool(network.IPv6Enabled), "IPv6 Enabled")
ow.AppendDataWithLabel("default", strconv.FormatBool(network.Default), "Default")
ow.AppendDataWithLabel("status", network.Status, "Status")
}
Expand Down
88 changes: 88 additions & 0 deletions cmd/network/network_subnet_attach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package network

import (
"fmt"
"os"
"time"

"github.com/briandowns/spinner"
"github.com/civo/civogo"
"github.com/civo/cli/common"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
"github.com/spf13/cobra"
)

var instanceID, subnetID string
var waitSubnetAttach bool

var networkSubnetAttachCmd = &cobra.Command{
Use: "attach",
Short: "Attach a subnet to a resource",
Example: "civo network subnet attach --instance INSTANCE-ID --subnet SUBNET-ID",
Run: func(cmd *cobra.Command, args []string) {
utility.EnsureCurrentRegion()

client, err := config.CivoAPIClient()
if common.RegionSet != "" {
client.Region = common.RegionSet
}
if err != nil {
utility.Error("Creating the connection to Civo's API failed with %s", err)
os.Exit(1)
}

instance, err := client.FindInstance(instanceID)
if err != nil {
utility.Error("Instance %s", err)
os.Exit(1)
}

subnet, err := client.FindSubnet(subnetID, instance.NetworkID)
if err != nil {
utility.Error("Subnet %s", err)
os.Exit(1)
}

_, err = client.AttachSubnetToInstance(instance.NetworkID, subnet.ID, &civogo.CreateRoute{
ResourceID: instance.ID,
ResourceType: "instance",
})
if err != nil {
utility.Error("error attaching the subnet: %s", err)
os.Exit(1)
}

if waitSubnetAttach {
stillAttaching := true
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
s.Prefix = "Attaching subnet to the instance... "
s.Start()

for stillAttaching {
subnetCheck, err := client.FindSubnet(subnet.ID, instance.NetworkID)
if err != nil {
utility.Error("Finding the subnet failed with %s", err)
os.Exit(1)
}
if subnetCheck.Status == "attached" {
stillAttaching = false
s.Stop()
} else {
time.Sleep(2 * time.Second)
}
}
}

ow := utility.NewOutputWriterWithMap(map[string]string{"id": subnet.ID, "name": subnet.Name})

switch common.OutputFormat {
case "json":
ow.WriteSingleObjectJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
fmt.Printf("The subnet (%s) was attached to the instance with ID (%s)\n", utility.Green(subnet.Name), utility.Green(instance.ID))
}
},
}
59 changes: 59 additions & 0 deletions cmd/network/network_subnet_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package network

import (
"fmt"
"os"

"github.com/civo/civogo"
"github.com/civo/cli/common"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
"github.com/spf13/cobra"
)

var networkSubnetCreateCmd = &cobra.Command{
Use: "create",
Aliases: []string{"create", "add"},
Short: "Create a new subnet",
Example: "civo network subnet create <SUBNET-NAME> <NETWORK-ID>",
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
utility.EnsureCurrentRegion()

client, err := config.CivoAPIClient()
if common.RegionSet != "" {
client.Region = common.RegionSet
}
if err != nil {
utility.Error("Creating the connection to Civo's API failed with %s", err)
os.Exit(1)
}

network, err := client.FindNetwork(args[1])
if err != nil {
utility.Error("Network %s", err)
os.Exit(1)
}

subnetConfig := civogo.SubnetConfig{
Name: args[0],
}

subnet, err := client.CreateSubnet(network.ID, subnetConfig)
if err != nil {
utility.Error("Subnet %s", err)
os.Exit(1)
}

ow := utility.NewOutputWriterWithMap(map[string]string{"id": subnet.ID, "name": subnet.Name})

switch common.OutputFormat {
case "json":
ow.WriteSingleObjectJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
fmt.Printf("The subnet (%s) was created in network with ID (%s)\n", utility.Green(subnet.Name), utility.Green(network.ID))
}
},
}
83 changes: 83 additions & 0 deletions cmd/network/network_subnet_detach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package network

import (
"fmt"
"os"
"time"

"github.com/briandowns/spinner"
"github.com/civo/cli/common"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
"github.com/spf13/cobra"
)

var waitSubnetDetach bool

var networkSubnetDetachCmd = &cobra.Command{
Use: "detach",
Short: "Detach a subnet from a resource",
Example: "civo network subnet detach --instance INSTANCE-ID --subnet SUBNET-ID",
Run: func(cmd *cobra.Command, args []string) {
utility.EnsureCurrentRegion()

client, err := config.CivoAPIClient()
if common.RegionSet != "" {
client.Region = common.RegionSet
}
if err != nil {
utility.Error("Creating the connection to Civo's API failed with %s", err)
os.Exit(1)
}

instance, err := client.FindInstance(instanceID)
if err != nil {
utility.Error("Instance %s", err)
os.Exit(1)
}

subnet, err := client.FindSubnet(subnetID, instance.NetworkID)
if err != nil {
utility.Error("Subnet %s", err)
os.Exit(1)
}

_, err = client.DetachSubnetFromInstance(instance.NetworkID, subnet.ID)
if err != nil {
utility.Error("error detaching the subnet: %s", err)
os.Exit(1)
}

if waitSubnetDetach {
stillDetaching := true
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
s.Prefix = "Detaching the subnet... "
s.Start()

for stillDetaching {
subnetCheck, err := client.FindSubnet(subnet.ID, instance.NetworkID)
if err != nil {
utility.Error("%s", err)
os.Exit(1)
}
if subnetCheck.Status == "available" {
stillDetaching = false
s.Stop()
} else {
time.Sleep(2 * time.Second)
}
}
}

ow := utility.NewOutputWriterWithMap(map[string]string{"id": subnet.ID, "name": subnet.Name})

switch common.OutputFormat {
case "json":
ow.WriteSingleObjectJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
fmt.Printf("The subnet (%s) was detached from instance with ID (%s)\n", utility.Green(subnet.Name), utility.Green(instance.ID))
}
},
}
Loading