yunion.io/x/cloudmux@v0.3.10-0-alpha.1/cmd/googlecli/main.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"fmt"
    19  	"net/http"
    20  	"net/url"
    21  	"os"
    22  
    23  	"golang.org/x/net/http/httpproxy"
    24  
    25  	"yunion.io/x/jsonutils"
    26  	"yunion.io/x/log"
    27  	"yunion.io/x/pkg/errors"
    28  	"yunion.io/x/structarg"
    29  
    30  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    31  	"yunion.io/x/cloudmux/pkg/multicloud/google"
    32  	_ "yunion.io/x/cloudmux/pkg/multicloud/google/shell"
    33  	"yunion.io/x/onecloud/pkg/util/fileutils2"
    34  	"yunion.io/x/onecloud/pkg/util/shellutils"
    35  )
    36  
    37  type BaseOptions struct {
    38  	Debug        bool   `help:"debug mode"`
    39  	AuthFile     string `help:"google cloud auth json file path" default:"$GOOGLE_AUTH_FILE" metavar:"GOOGLE_AUTH_FILE"`
    40  	ClientEmail  string `help:"Client email" default:"$GOOGLE_CLIENT_EMAIL" metavar:"GOOGLE_CLIENT_EMAIL"`
    41  	ProjectID    string `help:"Project ID" default:"$GOOGLE_PROJECT_ID" metavar:"GOOGLE_PROJECT_ID"`
    42  	PrivateKeyID string `help:"Private Key ID" default:"$GOOGLE_PRIVATE_KEY_ID" metavar:"GOOGLE_PRIVATE_KEY_ID"`
    43  	PrivateKey   string `help:"Private Key" default:"$GOOGLE_PRIVATE_KEY" metavar:"GOOGLE_PRIVATE_KEY"`
    44  	RegionID     string `help:"RegionID" default:"$GOOGLE_REGION" metavar:"GOOGLE_REGION"`
    45  	SUBCOMMAND   string `help:"googlecli subcommand" subcommand:"true"`
    46  }
    47  
    48  func getSubcommandParser() (*structarg.ArgumentParser, error) {
    49  	parse, e := structarg.NewArgumentParserWithHelp(&BaseOptions{},
    50  		"googlecli",
    51  		"Command-line interface to google API.",
    52  		`See "googlecli COMMAND --help" for help on a specific command.`)
    53  
    54  	if e != nil {
    55  		return nil, e
    56  	}
    57  
    58  	subcmd := parse.GetSubcommand()
    59  	if subcmd == nil {
    60  		return nil, fmt.Errorf("No subcommand argument.")
    61  	}
    62  	for _, v := range shellutils.CommandTable {
    63  		_, e := subcmd.AddSubParserWithHelp(v.Options, v.Command, v.Desc, v.Callback)
    64  		if e != nil {
    65  			return nil, e
    66  		}
    67  	}
    68  	return parse, nil
    69  }
    70  
    71  func showErrorAndExit(e error) {
    72  	log.Errorf("%s", e)
    73  	os.Exit(1)
    74  }
    75  
    76  func newClient(options *BaseOptions) (*google.SRegion, error) {
    77  	if len(options.AuthFile) > 0 {
    78  		jsonStr, err := fileutils2.FileGetContents(options.AuthFile)
    79  		if err != nil {
    80  			return nil, errors.Wrap(err, "FileGetContents")
    81  		}
    82  		jsonCfg, err := jsonutils.ParseString(jsonStr)
    83  		if err != nil {
    84  			return nil, errors.Wrap(err, "jsonutils.ParseString")
    85  		}
    86  		options.ClientEmail, _ = jsonCfg.GetString("client_email")
    87  		options.PrivateKeyID, _ = jsonCfg.GetString("private_key_id")
    88  		options.PrivateKey, _ = jsonCfg.GetString("private_key")
    89  		options.ProjectID, _ = jsonCfg.GetString("project_id")
    90  	}
    91  	if len(options.ClientEmail) == 0 {
    92  		return nil, fmt.Errorf("Missing ClientEmail")
    93  	}
    94  
    95  	if len(options.PrivateKeyID) == 0 {
    96  		return nil, fmt.Errorf("Missing PrivateKeyID")
    97  	}
    98  
    99  	if len(options.PrivateKey) == 0 {
   100  		return nil, fmt.Errorf("Missing PrivateKey")
   101  	}
   102  
   103  	if len(options.ProjectID) == 0 {
   104  		return nil, fmt.Errorf("Missing ProjectID")
   105  	}
   106  
   107  	cfg := &httpproxy.Config{
   108  		HTTPProxy:  os.Getenv("HTTP_PROXY"),
   109  		HTTPSProxy: os.Getenv("HTTPS_PROXY"),
   110  		NoProxy:    os.Getenv("NO_PROXY"),
   111  	}
   112  	cfgProxyFunc := cfg.ProxyFunc()
   113  	proxyFunc := func(req *http.Request) (*url.URL, error) {
   114  		return cfgProxyFunc(req.URL)
   115  	}
   116  
   117  	cli, err := google.NewGoogleClient(
   118  		google.NewGoogleClientConfig(
   119  			options.ProjectID,
   120  			options.ClientEmail,
   121  			options.PrivateKeyID,
   122  			options.PrivateKey,
   123  		).Debug(options.Debug).
   124  			CloudproviderConfig(
   125  				cloudprovider.ProviderConfig{
   126  					ProxyFunc: proxyFunc,
   127  				},
   128  			),
   129  	)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	region := cli.GetRegion(options.RegionID)
   135  	if region == nil {
   136  		return nil, fmt.Errorf("No such region %s", options.RegionID)
   137  	}
   138  
   139  	return region, nil
   140  }
   141  
   142  func main() {
   143  	parser, e := getSubcommandParser()
   144  	if e != nil {
   145  		showErrorAndExit(e)
   146  	}
   147  	e = parser.ParseArgs(os.Args[1:], false)
   148  	options := parser.Options().(*BaseOptions)
   149  
   150  	if parser.IsHelpSet() {
   151  		fmt.Print(parser.HelpString())
   152  		return
   153  	}
   154  	subcmd := parser.GetSubcommand()
   155  	subparser := subcmd.GetSubParser()
   156  	if e != nil || subparser == nil {
   157  		if subparser != nil {
   158  			fmt.Print(subparser.Usage())
   159  		} else {
   160  			fmt.Print(parser.Usage())
   161  		}
   162  		showErrorAndExit(e)
   163  		return
   164  	}
   165  	suboptions := subparser.Options()
   166  	if subparser.IsHelpSet() {
   167  		fmt.Print(subparser.HelpString())
   168  		return
   169  	}
   170  	var region *google.SRegion
   171  	region, e = newClient(options)
   172  	if e != nil {
   173  		showErrorAndExit(e)
   174  	}
   175  	e = subcmd.Invoke(region, suboptions)
   176  	if e != nil {
   177  		showErrorAndExit(e)
   178  	}
   179  }