2021-12-18 13:13:25 +01:00
package cmd
import (
"os"
"fmt"
2022-04-02 14:18:50 +02:00
"strconv"
2021-12-20 22:10:38 +01:00
"strings"
2022-04-02 14:18:50 +02:00
"encoding/json"
2021-12-18 13:13:25 +01:00
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const (
2022-04-02 15:40:04 +02:00
gVersion = "0.022b"
2021-12-18 13:13:25 +01:00
)
var (
2021-12-19 13:05:30 +01:00
gJails [ ] Jail
2021-12-18 21:34:11 +01:00
2021-12-19 13:05:30 +01:00
gUseSudo bool
gConfigFile string
gDisplayColumns string
2021-12-19 16:49:07 +01:00
gFilterJails string
gSortFields string
2021-12-19 14:31:51 +01:00
gNoLineSep bool
2021-12-18 21:34:11 +01:00
2022-04-02 14:18:50 +02:00
gHostVersion float64
2021-12-18 13:13:25 +01:00
rootCmd = & cobra . Command {
Use : "gocage" ,
Short : "GoCage is a FreeBSD Jail management tool" ,
Long : ` GoCage is a jail management tool . It support VNET , host - only , NAT networks . Provides snapshots and cloning .
It support iocage jails and can coexist with iocage . ` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
fmt . Println ( "Here we are in the Run" )
2022-04-02 14:18:50 +02:00
cleanAfterRun ( )
2021-12-18 13:13:25 +01:00
} ,
}
versionCmd = & cobra . Command {
Use : "version" ,
Short : "Print the version number of GoCage" ,
Long : ` Let this show you how much fail I had to get this *cough* perfect ` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
2022-04-02 14:18:50 +02:00
fmt . Printf ( "GoCage v.%s on FreeBSD %.1f\n" , gVersion , gHostVersion )
cleanAfterRun ( )
2021-12-18 13:13:25 +01:00
} ,
}
listCmd = & cobra . Command {
Use : "list" ,
Short : "Print jails" ,
2021-12-18 21:34:11 +01:00
Long : ` Display jails , their IP and OS .
Jail list can be restricted by adding name on command line
ex : gocage list srv - db srv - web ` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
2021-12-19 12:41:54 +01:00
ListJails ( args , true )
2022-04-02 14:18:50 +02:00
cleanAfterRun ( )
2021-12-18 21:34:11 +01:00
} ,
}
2022-04-02 15:40:04 +02:00
listPropsCmd = & cobra . Command {
Use : "properties" ,
Short : "Print jails properties" ,
Long : "Display jails properties. You can use properties to filter, get or set them." ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
ListJailsProps ( args )
cleanAfterRun ( )
} ,
}
2021-12-18 21:34:11 +01:00
stopCmd = & cobra . Command {
Use : "stop" ,
Short : "stop jail" ,
2022-04-02 15:40:04 +02:00
Long : "shutdown jail" ,
2021-12-18 13:13:25 +01:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2021-12-18 21:34:11 +01:00
// Get the inventory
2021-12-19 12:41:54 +01:00
ListJails ( args , false )
StopJail ( args )
2022-04-02 14:18:50 +02:00
cleanAfterRun ( )
2021-12-18 13:13:25 +01:00
} ,
}
2021-12-21 20:48:15 +01:00
startCmd = & cobra . Command {
Use : "start" ,
Short : "start jail" ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
// Get the inventory
ListJails ( args , false )
StartJail ( args )
2022-04-02 14:18:50 +02:00
cleanAfterRun ( )
2021-12-21 20:48:15 +01:00
} ,
}
2021-12-18 13:13:25 +01:00
)
func init ( ) {
cobra . OnInitialize ( initConfig )
// Global switches
2021-12-18 21:34:11 +01:00
rootCmd . PersistentFlags ( ) . StringVarP ( & gConfigFile , "config" , "c" , "/usr/local/etc/gocage.conf.yml" , "GoCage configuration file" )
2021-12-19 16:49:07 +01:00
rootCmd . PersistentFlags ( ) . BoolVarP ( & gUseSudo , "sudo" , "u" , false , "Use sudo to run commands" )
2021-12-18 13:13:25 +01:00
// Command dependant switches
2021-12-19 13:05:30 +01:00
listCmd . PersistentFlags ( ) . StringVarP ( & gDisplayColumns , "outcol" , "o" , "JID,Name,Config.Release,Config.Ip4_addr,Running" , "Show these columns in output" )
2021-12-19 14:31:51 +01:00
listCmd . PersistentFlags ( ) . BoolVarP ( & gNoLineSep , "nolinesep" , "l" , false , "Do not display line separator between jails" )
2021-12-19 16:49:07 +01:00
listCmd . PersistentFlags ( ) . StringVarP ( & gFilterJails , "filter" , "f" , "none" , "Only display jails with these values. Ex: \"gocage list -f Config.Boot=1\" will only list started on boot jails" )
2021-12-20 22:10:38 +01:00
listCmd . PersistentFlags ( ) . StringVarP ( & gSortFields , "sort" , "s" , "none" , "Display jails sorted by field values. Ex: \"gocage list -s +Name,-Config.Priority\" will sort jails by their decreasing name, then increasing start priority. 3 critera max supported." )
2021-12-18 13:13:25 +01:00
// Now declare commands
rootCmd . AddCommand ( versionCmd )
rootCmd . AddCommand ( listCmd )
2022-04-02 15:40:04 +02:00
listCmd . AddCommand ( listPropsCmd )
2021-12-18 21:34:11 +01:00
rootCmd . AddCommand ( stopCmd )
2021-12-21 20:48:15 +01:00
rootCmd . AddCommand ( startCmd )
2022-04-02 14:18:50 +02:00
// Get FreeBSD version
out , err := executeCommand ( "freebsd-version" )
if err != nil {
fmt . Printf ( "Error running \"freebsd-version\": %s" , err . Error ( ) )
os . Exit ( 1 )
}
gHostVersion , _ = strconv . ParseFloat ( strings . Split ( out , "-" ) [ 0 ] , 32 )
2021-12-18 13:13:25 +01:00
}
func initConfig ( ) {
if gConfigFile == "" {
fmt . Println ( "No config file!" )
2021-12-18 21:34:11 +01:00
os . Exit ( 1 )
2021-12-18 13:13:25 +01:00
}
// fmt.Printf("We are in initConfig(), with config file %s\n", gConfigFile)
viper . SetConfigFile ( gConfigFile )
if err := viper . ReadInConfig ( ) ; err != nil {
fmt . Printf ( "ERROR reading config file %s : %s\n" , gConfigFile , err . Error ( ) )
2021-12-18 21:34:11 +01:00
os . Exit ( 1 )
2021-12-18 13:13:25 +01:00
}
// fmt.Println("Using config file:", viper.ConfigFileUsed())
// fmt.Printf("datastore in config : %s\n", viper.GetStringSlice("datastore"))
// fmt.Printf("datastore.0 in config : %s\n", viper.GetStringSlice("datastore.0"))
2021-12-19 13:05:30 +01:00
// Command line flags have priority on config file
2021-12-19 14:45:12 +01:00
if rootCmd . Flags ( ) . Lookup ( "sudo" ) != nil && false == rootCmd . Flags ( ) . Lookup ( "sudo" ) . Changed {
2021-12-19 13:05:30 +01:00
gUseSudo = viper . GetBool ( "sudo" )
}
2021-12-19 14:45:12 +01:00
if listCmd . Flags ( ) . Lookup ( "outcol" ) != nil && false == listCmd . Flags ( ) . Lookup ( "outcol" ) . Changed {
2021-12-19 13:05:30 +01:00
gDisplayColumns = viper . GetString ( "outcol" )
}
2021-12-19 14:45:12 +01:00
if listCmd . Flags ( ) . Lookup ( "nolinesep" ) != nil && false == listCmd . Flags ( ) . Lookup ( "nolinesep" ) . Changed {
2021-12-19 14:31:51 +01:00
gNoLineSep = viper . GetBool ( "nolinesep" )
}
2021-12-19 16:49:07 +01:00
if listCmd . Flags ( ) . Lookup ( "filter" ) != nil && false == listCmd . Flags ( ) . Lookup ( "filter" ) . Changed {
gFilterJails = viper . GetString ( "filter" )
}
if listCmd . Flags ( ) . Lookup ( "sort" ) != nil && false == listCmd . Flags ( ) . Lookup ( "sort" ) . Changed {
gSortFields = viper . GetString ( "sort" )
}
2021-12-20 22:10:38 +01:00
if len ( strings . Split ( gSortFields , "," ) ) > 3 {
fmt . Printf ( "More than 3 sort criteria, this is not supported!\n" )
os . Exit ( 1 )
}
2021-12-18 13:13:25 +01:00
}
2022-04-02 14:18:50 +02:00
// Called after execution
func cleanAfterRun ( ) {
for _ , j := range gJails {
if j . ConfigUpdated {
// TODO : Marshall to disk
fmt . Printf ( "Config for jail %s will be updated\n" , j . Name )
marshaled , err := json . MarshalIndent ( j . Config , "" , " " )
if err != nil {
fmt . Printf ( "ERROR marshaling config: %s\n" , err . Error ( ) )
}
fmt . Printf ( string ( marshaled ) )
}
}
}
2021-12-18 13:13:25 +01:00
func Execute ( ) {
if err := rootCmd . Execute ( ) ; err != nil {
fmt . Fprintln ( os . Stderr , err )
os . Exit ( 1 )
}
}