2014-06-06 23:40:48 +00:00
/ *
Copyright 2014 Google Inc . All rights reserved .
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
2014-06-23 18:32:11 +00:00
2014-06-06 23:40:48 +00:00
package main
import (
"flag"
"fmt"
2014-06-12 20:41:48 +00:00
"io/ioutil"
2014-06-12 01:13:25 +00:00
"net/url"
2014-06-06 23:40:48 +00:00
"os"
"strconv"
2014-06-12 21:13:02 +00:00
"strings"
2014-07-15 04:13:06 +00:00
"text/template"
2014-06-06 23:40:48 +00:00
"time"
kube_client "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
2014-06-26 00:55:43 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubecfg"
2014-06-25 03:51:57 +00:00
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
2014-06-06 23:40:48 +00:00
)
2014-07-08 06:30:18 +00:00
// AppVersion is the current version of kubecfg.
const AppVersion = "0.1"
2014-06-06 23:40:48 +00:00
// The flag package provides a default help printer via -h switch
2014-06-07 21:06:28 +00:00
var (
2014-06-25 05:04:32 +00:00
versionFlag = flag . Bool ( "V" , false , "Print the version number." )
2014-06-07 21:06:28 +00:00
httpServer = flag . String ( "h" , "" , "The host to connect to." )
config = flag . String ( "c" , "" , "Path to the config file." )
2014-06-18 23:47:41 +00:00
selector = flag . String ( "l" , "" , "Selector (label query) to use for listing" )
2014-06-11 06:29:36 +00:00
updatePeriod = flag . Duration ( "u" , 60 * time . Second , "Update interarrival period" )
2014-06-07 21:06:28 +00:00
portSpec = flag . String ( "p" , "" , "The port spec, comma-separated list of <external>:<internal>,..." )
servicePort = flag . Int ( "s" , - 1 , "If positive, create and run a corresponding service on this port, only used with 'run'" )
2014-06-12 01:13:25 +00:00
authConfig = flag . String ( "auth" , os . Getenv ( "HOME" ) + "/.kubernetes_auth" , "Path to the auth info file. If missing, prompt the user. Only used if doing https." )
2014-06-09 03:29:30 +00:00
json = flag . Bool ( "json" , false , "If true, print raw JSON for responses" )
yaml = flag . Bool ( "yaml" , false , "If true, print raw YAML for responses" )
2014-06-16 03:53:21 +00:00
verbose = flag . Bool ( "verbose" , false , "If true, print extra information" )
2014-06-24 02:57:54 +00:00
proxy = flag . Bool ( "proxy" , false , "If true, run a proxy to the api server" )
2014-06-24 05:18:14 +00:00
www = flag . String ( "www" , "" , "If -proxy is true, use this directory to serve static files" )
2014-07-15 04:13:06 +00:00
templateFile = flag . String ( "template" , "" , "If present load this file as a golang template and us it for output printing" )
2014-06-07 21:06:28 +00:00
)
2014-06-06 23:40:48 +00:00
func usage ( ) {
2014-06-26 00:55:43 +00:00
fmt . Fprint ( os . Stderr , ` usage : kubecfg - h [ - c config / file . json ] [ - p : , ... , : ] < method >
2014-06-11 22:08:23 +00:00
Kubernetes REST API :
2014-06-26 00:55:43 +00:00
kubecfg [ OPTIONS ] get | list | create | delete | update < url >
2014-06-11 22:08:23 +00:00
Manage replication controllers :
2014-06-26 00:55:43 +00:00
kubecfg [ OPTIONS ] stop | rm | rollingupdate < controller >
kubecfg [ OPTIONS ] run < image > < replicas > < controller >
kubecfg [ OPTIONS ] resize < controller > < replicas >
2014-06-11 22:08:23 +00:00
Options :
` )
flag . PrintDefaults ( )
2014-06-06 23:40:48 +00:00
}
2014-06-25 03:51:57 +00:00
// Reads & parses config file. On error, calls glog.Fatal().
2014-06-12 20:41:48 +00:00
func readConfig ( storage string ) [ ] byte {
if len ( * config ) == 0 {
2014-06-25 03:51:57 +00:00
glog . Fatal ( "Need config file (-c)" )
2014-06-12 20:41:48 +00:00
}
data , err := ioutil . ReadFile ( * config )
if err != nil {
2014-07-01 02:45:00 +00:00
glog . Fatalf ( "Unable to read %v: %v\n" , * config , err )
2014-06-12 20:41:48 +00:00
}
2014-06-26 00:55:43 +00:00
data , err = kubecfg . ToWireFormat ( data , storage )
2014-06-12 20:41:48 +00:00
if err != nil {
2014-07-01 02:45:00 +00:00
glog . Fatalf ( "Error parsing %v as an object for %v: %v\n" , * config , storage , err )
2014-06-12 20:41:48 +00:00
}
2014-06-16 03:53:21 +00:00
if * verbose {
2014-06-25 03:51:57 +00:00
glog . Infof ( "Parsed config file successfully; sending:\n%v\n" , string ( data ) )
2014-06-16 03:53:21 +00:00
}
2014-06-12 20:41:48 +00:00
return data
}
2014-06-06 23:40:48 +00:00
// CloudCfg command line tool.
func main ( ) {
2014-06-11 22:08:23 +00:00
flag . Usage = func ( ) {
usage ( )
}
2014-06-06 23:40:48 +00:00
flag . Parse ( ) // Scan the arguments list
2014-06-25 03:51:57 +00:00
util . InitLogs ( )
defer util . FlushLogs ( )
2014-06-06 23:40:48 +00:00
if * versionFlag {
2014-07-08 06:30:18 +00:00
fmt . Println ( "Version:" , AppVersion )
2014-06-06 23:40:48 +00:00
os . Exit ( 0 )
}
2014-06-12 01:13:25 +00:00
secure := true
2014-06-28 05:48:32 +00:00
var masterServer string
if len ( * httpServer ) > 0 {
masterServer = * httpServer
} else if len ( os . Getenv ( "KUBERNETES_MASTER" ) ) > 0 {
masterServer = os . Getenv ( "KUBERNETES_MASTER" )
} else {
masterServer = "http://localhost:8080"
}
2014-07-08 06:30:18 +00:00
parsedURL , err := url . Parse ( masterServer )
2014-06-12 01:13:25 +00:00
if err != nil {
2014-06-25 03:51:57 +00:00
glog . Fatalf ( "Unable to parse %v as a URL\n" , err )
2014-06-12 01:13:25 +00:00
}
2014-07-08 06:30:18 +00:00
if parsedURL . Scheme != "" && parsedURL . Scheme != "https" {
2014-06-12 01:13:25 +00:00
secure = false
}
2014-06-09 03:29:30 +00:00
2014-06-12 05:25:50 +00:00
var auth * kube_client . AuthInfo
2014-06-12 01:13:25 +00:00
if secure {
2014-06-26 00:55:43 +00:00
auth , err = kubecfg . LoadAuthInfo ( * authConfig )
2014-06-12 01:13:25 +00:00
if err != nil {
2014-07-01 02:45:00 +00:00
glog . Fatalf ( "Error loading auth: %v" , err )
2014-06-12 01:13:25 +00:00
}
2014-06-06 23:40:48 +00:00
}
2014-06-24 02:57:54 +00:00
if * proxy {
2014-06-25 03:51:57 +00:00
glog . Info ( "Starting to serve on localhost:8001" )
2014-06-28 05:48:32 +00:00
server := kubecfg . NewProxyServer ( * www , masterServer , auth )
2014-06-25 03:51:57 +00:00
glog . Fatal ( server . Serve ( ) )
2014-06-24 02:57:54 +00:00
}
2014-06-24 05:18:14 +00:00
if len ( flag . Args ( ) ) < 1 {
usage ( )
os . Exit ( 1 )
}
method := flag . Arg ( 0 )
2014-06-28 05:48:32 +00:00
client := kube_client . New ( masterServer , auth )
matchFound := executeAPIRequest ( method , client ) || executeControllerRequest ( method , client )
2014-06-11 22:08:23 +00:00
if matchFound == false {
2014-06-25 03:51:57 +00:00
glog . Fatalf ( "Unknown command %s" , method )
2014-06-11 22:08:23 +00:00
}
}
// Attempts to execute an API request
2014-06-28 05:48:32 +00:00
func executeAPIRequest ( method string , s * kube_client . Client ) bool {
2014-06-11 22:08:23 +00:00
parseStorage := func ( ) string {
if len ( flag . Args ( ) ) != 2 {
2014-06-26 00:55:43 +00:00
glog . Fatal ( "usage: kubecfg [OPTIONS] get|list|create|update|delete <url>" )
2014-06-11 22:08:23 +00:00
}
return strings . Trim ( flag . Arg ( 1 ) , "/" )
}
2014-06-21 21:23:14 +00:00
verb := ""
2014-06-10 21:42:59 +00:00
switch method {
case "get" , "list" :
2014-06-21 21:23:14 +00:00
verb = "GET"
2014-06-10 21:42:59 +00:00
case "delete" :
2014-06-21 21:23:14 +00:00
verb = "DELETE"
2014-06-10 21:42:59 +00:00
case "create" :
2014-06-21 21:23:14 +00:00
verb = "POST"
2014-06-10 21:42:59 +00:00
case "update" :
2014-06-21 21:23:14 +00:00
verb = "PUT"
2014-06-11 22:08:23 +00:00
default :
return false
}
2014-06-21 21:23:14 +00:00
r := s . Verb ( verb ) .
Path ( parseStorage ( ) ) .
2014-06-23 00:02:48 +00:00
ParseSelector ( * selector )
2014-06-21 21:23:14 +00:00
if method == "create" || method == "update" {
r . Body ( readConfig ( parseStorage ( ) ) )
}
2014-07-01 02:45:00 +00:00
result := r . Do ( )
obj , err := result . Get ( )
2014-06-21 21:23:14 +00:00
if err != nil {
2014-06-25 03:51:57 +00:00
glog . Fatalf ( "Got request error: %v\n" , err )
2014-06-21 21:23:14 +00:00
return false
}
2014-06-26 00:55:43 +00:00
var printer kubecfg . ResourcePrinter
2014-06-11 22:08:23 +00:00
if * json {
2014-06-26 00:55:43 +00:00
printer = & kubecfg . IdentityPrinter { }
2014-06-11 22:08:23 +00:00
} else if * yaml {
2014-06-26 00:55:43 +00:00
printer = & kubecfg . YAMLPrinter { }
2014-07-15 04:13:06 +00:00
} else if len ( * templateFile ) > 0 {
data , err := ioutil . ReadFile ( * templateFile )
if err != nil {
glog . Fatalf ( "Error reading template %s, %v\n" , * templateFile , err )
return false
}
tmpl , err := template . New ( "output" ) . Parse ( string ( data ) )
if err != nil {
glog . Fatalf ( "Error parsing template %s, %v\n" , string ( data ) , err )
return false
}
printer = & kubecfg . TemplatePrinter {
Template : tmpl ,
}
2014-06-11 22:08:23 +00:00
} else {
2014-06-26 00:55:43 +00:00
printer = & kubecfg . HumanReadablePrinter { }
2014-06-11 22:08:23 +00:00
}
2014-06-21 21:23:14 +00:00
if err = printer . PrintObj ( obj , os . Stdout ) ; err != nil {
2014-07-01 02:45:00 +00:00
body , _ := result . Raw ( )
glog . Fatalf ( "Failed to print: %v\nRaw received object:\n%#v\n\nBody received: %v" , err , obj , string ( body ) )
2014-06-11 22:08:23 +00:00
}
2014-06-21 21:23:14 +00:00
fmt . Print ( "\n" )
2014-06-11 22:08:23 +00:00
return true
}
// Attempts to execute a replicationController request
2014-06-28 05:48:32 +00:00
func executeControllerRequest ( method string , c * kube_client . Client ) bool {
2014-06-11 22:08:23 +00:00
parseController := func ( ) string {
if len ( flag . Args ( ) ) != 2 {
2014-06-26 00:55:43 +00:00
glog . Fatal ( "usage: kubecfg [OPTIONS] stop|rm|rollingupdate <controller>" )
2014-06-11 22:08:23 +00:00
}
return flag . Arg ( 1 )
}
var err error
switch method {
case "stop" :
2014-06-26 00:55:43 +00:00
err = kubecfg . StopController ( parseController ( ) , c )
2014-06-11 22:08:23 +00:00
case "rm" :
2014-06-26 00:55:43 +00:00
err = kubecfg . DeleteController ( parseController ( ) , c )
2014-06-10 21:42:59 +00:00
case "rollingupdate" :
2014-06-26 00:55:43 +00:00
err = kubecfg . Update ( parseController ( ) , c , * updatePeriod )
2014-06-10 21:42:59 +00:00
case "run" :
2014-06-11 22:08:23 +00:00
if len ( flag . Args ( ) ) != 4 {
2014-06-26 00:55:43 +00:00
glog . Fatal ( "usage: kubecfg [OPTIONS] run <image> <replicas> <controller>" )
2014-06-06 23:40:48 +00:00
}
2014-06-11 22:08:23 +00:00
image := flag . Arg ( 1 )
replicas , err := strconv . Atoi ( flag . Arg ( 2 ) )
name := flag . Arg ( 3 )
2014-06-06 23:40:48 +00:00
if err != nil {
2014-07-01 02:45:00 +00:00
glog . Fatalf ( "Error parsing replicas: %v" , err )
2014-06-06 23:40:48 +00:00
}
2014-06-26 00:55:43 +00:00
err = kubecfg . RunController ( image , name , replicas , c , * portSpec , * servicePort )
2014-06-12 17:03:17 +00:00
case "resize" :
args := flag . Args ( )
if len ( args ) < 3 {
2014-06-26 00:55:43 +00:00
glog . Fatal ( "usage: kubecfg resize <controller> <replicas>" )
2014-06-12 17:03:17 +00:00
}
name := args [ 1 ]
replicas , err := strconv . Atoi ( args [ 2 ] )
if err != nil {
2014-07-01 02:45:00 +00:00
glog . Fatalf ( "Error parsing replicas: %v" , err )
2014-06-12 17:03:17 +00:00
}
2014-06-26 00:55:43 +00:00
err = kubecfg . ResizeController ( name , replicas , c )
2014-06-10 21:42:59 +00:00
default :
2014-06-11 22:08:23 +00:00
return false
2014-06-06 23:40:48 +00:00
}
if err != nil {
2014-07-01 02:45:00 +00:00
glog . Fatalf ( "Error: %v" , err )
2014-06-06 23:40:48 +00:00
}
2014-06-11 22:08:23 +00:00
return true
2014-06-06 23:40:48 +00:00
}