/* Copyright © 2021 Arsen Musayelyan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package cmd import ( "net" "net/http" "strings" "github.com/abiosoft/ishell" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/vmihailenco/msgpack/v5" "go.arsenm.dev/lasso/internal/types" "github.com/spf13/viper" ) var cfgFile string // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "lassoctl", Short: "Manage devices using IPs retrieved from a lasso server", } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { cobra.CheckErr(rootCmd.Execute()) } func init() { cobra.OnInitialize(initConfig) rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file to use") } // initConfig reads in config file and ENV variables if set. func initConfig() { if cfgFile != "" { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { viper.AddConfigPath("/etc") viper.SetConfigType("toml") viper.SetConfigName("lassoctl") } viper.SetEnvPrefix("lassoctl") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) viper.AutomaticEnv() // read in environment variables that match // If a config file is found, read it in. viper.ReadInConfig() } // getNodeList gets a list of nodes from the lasso server func getNodeList() map[string]types.Node { // Get server address addr := net.JoinHostPort(viper.GetString("server.addr"), viper.GetString("server.port")) // Create base url for HTTPS server baseURL := "https://" + addr // Get node list res, err := http.Get(baseURL + "/node/list") if err != nil { log.Fatal().Err(err).Msg("Error getting node list from server") } var resp types.Response // Decode server response err = msgpack.NewDecoder(res.Body).Decode(&resp) if err != nil { log.Fatal().Err(err).Msg("Error decoding server response") } // If server response is an error if resp.Error { log.Fatal().Str("error", resp.Message).Msg("Server returned error") } var nodes map[string]types.Node // Decode response data as node map err = mapstructure.Decode(resp.Data, &nodes) if err != nil { log.Fatal().Err(err).Msg("Error decoding nodes map") } // Return node map return nodes } // cmdError prints an error while running mssh func cmdError(shell *ishell.Shell, node string, err error) { shell.Printf("%s [error]: %v\n", node, err) } // cmdOut prints output from a command while running mssh func cmdOut(shell *ishell.Shell, node, out string) { shell.Printf("%s [out]: %s\n", node, out) } // cmdSucces prints a success message while running mssh func cmdSuccess(shell *ishell.Shell, node, msg string) { shell.Printf("%s [success]: %s\n", node, msg) }