2016-02-04 22:12:05 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2016 The Kubernetes Authors .
2016-02-04 22:12:05 +00:00
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 .
* /
package cmd
import (
"fmt"
"io"
"os"
"path"
"github.com/spf13/cobra"
2017-01-22 03:36:02 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2016-02-04 22:12:05 +00:00
"k8s.io/kubernetes/pkg/api"
2016-10-07 22:24:42 +00:00
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
2016-02-04 22:12:05 +00:00
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
2017-07-07 04:04:11 +00:00
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
2017-02-19 22:56:11 +00:00
"k8s.io/kubernetes/pkg/printers"
2016-02-04 22:12:05 +00:00
)
// NewCmdCreateSecret groups subcommands to create various types of secrets
2016-10-13 00:18:39 +00:00
func NewCmdClusterInfoDump ( f cmdutil . Factory , cmdOut io . Writer ) * cobra . Command {
2016-02-04 22:12:05 +00:00
cmd := & cobra . Command {
2016-05-16 23:50:13 +00:00
Use : "dump" ,
2017-01-25 01:00:32 +00:00
Short : i18n . T ( "Dump lots of relevant info for debugging and diagnosis" ) ,
2016-05-16 23:50:13 +00:00
Long : dumpLong ,
Example : dumpExample ,
2016-02-04 22:12:05 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2017-03-17 13:55:46 +00:00
cmdutil . CheckErr ( dumpClusterInfo ( f , cmd , cmdOut ) )
2016-02-04 22:12:05 +00:00
} ,
}
2017-02-07 06:26:44 +00:00
cmd . Flags ( ) . String ( "output-directory" , "" , i18n . T ( "Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory" ) )
2016-02-04 22:12:05 +00:00
cmd . Flags ( ) . StringSlice ( "namespaces" , [ ] string { } , "A comma separated list of namespaces to dump." )
cmd . Flags ( ) . Bool ( "all-namespaces" , false , "If true, dump all namespaces. If true, --namespaces is ignored." )
2017-02-21 16:19:13 +00:00
cmdutil . AddPodRunningTimeoutFlag ( cmd , defaultPodLogsTimeout )
2016-02-04 22:12:05 +00:00
return cmd
}
2016-10-07 22:24:42 +00:00
var (
2017-03-15 03:49:10 +00:00
dumpLong = templates . LongDesc ( i18n . T ( `
2016-10-07 22:24:42 +00:00
Dumps cluster info out suitable for debugging and diagnosing cluster problems . By default , dumps everything to
stdout . You can optionally specify a directory with -- output - directory . If you specify a directory , kubernetes will
build a set of files in that directory . By default only dumps things in the ' kube - system ' namespace , but you can
switch to a different namespace with the -- namespaces flag , or specify -- all - namespaces to dump all namespaces .
2016-05-11 18:17:26 +00:00
2016-10-07 22:24:42 +00:00
The command also dumps the logs of all of the pods in the cluster , these logs are dumped into different directories
2017-03-15 03:49:10 +00:00
based on namespace and pod name . ` ) )
2016-02-04 22:12:05 +00:00
2017-03-15 03:49:10 +00:00
dumpExample = templates . Examples ( i18n . T ( `
2016-10-07 22:24:42 +00:00
# Dump current cluster state to stdout
kubectl cluster - info dump
2016-06-01 12:50:29 +00:00
2016-10-07 22:24:42 +00:00
# Dump current cluster state to / path / to / cluster - state
kubectl cluster - info dump -- output - directory = / path / to / cluster - state
2016-06-01 12:50:29 +00:00
2016-10-07 22:24:42 +00:00
# Dump all namespaces to stdout
kubectl cluster - info dump -- all - namespaces
2016-06-01 12:50:29 +00:00
2016-10-07 22:24:42 +00:00
# Dump a set of namespaces to / path / to / cluster - state
2017-03-15 03:49:10 +00:00
kubectl cluster - info dump -- namespaces default , kube - system -- output - directory = / path / to / cluster - state ` ) )
2016-02-04 22:12:05 +00:00
)
2016-05-11 18:17:26 +00:00
func setupOutputWriter ( cmd * cobra . Command , defaultWriter io . Writer , filename string ) io . Writer {
2016-02-04 22:12:05 +00:00
dir := cmdutil . GetFlagString ( cmd , "output-directory" )
if len ( dir ) == 0 || dir == "-" {
2016-03-25 16:25:24 +00:00
return defaultWriter
2016-02-04 22:12:05 +00:00
}
fullFile := path . Join ( dir , filename )
parent := path . Dir ( fullFile )
cmdutil . CheckErr ( os . MkdirAll ( parent , 0755 ) )
file , err := os . Create ( path . Join ( dir , filename ) )
cmdutil . CheckErr ( err )
return file
}
2017-03-17 13:55:46 +00:00
func dumpClusterInfo ( f cmdutil . Factory , cmd * cobra . Command , out io . Writer ) error {
2017-02-21 16:19:13 +00:00
timeout , err := cmdutil . GetPodRunningTimeoutFlag ( cmd )
if err != nil {
2017-06-14 21:14:42 +00:00
return cmdutil . UsageErrorf ( cmd , err . Error ( ) )
2017-02-21 16:19:13 +00:00
}
2016-09-07 20:29:57 +00:00
clientset , err := f . ClientSet ( )
if err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2016-09-07 20:29:57 +00:00
2017-02-19 22:56:11 +00:00
printer := & printers . JSONPrinter { }
2016-02-04 22:12:05 +00:00
2017-01-22 03:36:02 +00:00
nodes , err := clientset . Core ( ) . Nodes ( ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( nodes , setupOutputWriter ( cmd , out , "nodes.json" ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
var namespaces [ ] string
if cmdutil . GetFlagBool ( cmd , "all-namespaces" ) {
2017-01-22 03:36:02 +00:00
namespaceList , err := clientset . Core ( ) . Namespaces ( ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
for ix := range namespaceList . Items {
namespaces = append ( namespaces , namespaceList . Items [ ix ] . Name )
}
} else {
namespaces = cmdutil . GetFlagStringSlice ( cmd , "namespaces" )
if len ( namespaces ) == 0 {
cmdNamespace , _ , err := f . DefaultNamespace ( )
if err != nil {
return err
}
namespaces = [ ] string {
2017-01-22 03:36:02 +00:00
metav1 . NamespaceSystem ,
2016-02-04 22:12:05 +00:00
cmdNamespace ,
}
}
}
for _ , namespace := range namespaces {
// TODO: this is repetitive in the extreme. Use reflection or
// something to make this a for loop.
2017-01-22 03:36:02 +00:00
events , err := clientset . Core ( ) . Events ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( events , setupOutputWriter ( cmd , out , path . Join ( namespace , "events.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-01-22 03:36:02 +00:00
rcs , err := clientset . Core ( ) . ReplicationControllers ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( rcs , setupOutputWriter ( cmd , out , path . Join ( namespace , "replication-controllers.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-01-22 03:36:02 +00:00
svcs , err := clientset . Core ( ) . Services ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( svcs , setupOutputWriter ( cmd , out , path . Join ( namespace , "services.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-01-22 03:36:02 +00:00
sets , err := clientset . Extensions ( ) . DaemonSets ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( sets , setupOutputWriter ( cmd , out , path . Join ( namespace , "daemonsets.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-01-22 03:36:02 +00:00
deps , err := clientset . Extensions ( ) . Deployments ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( deps , setupOutputWriter ( cmd , out , path . Join ( namespace , "deployments.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-01-22 03:36:02 +00:00
rps , err := clientset . Extensions ( ) . ReplicaSets ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( rps , setupOutputWriter ( cmd , out , path . Join ( namespace , "replicasets.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-01-22 03:36:02 +00:00
pods , err := clientset . Core ( ) . Pods ( namespace ) . List ( metav1 . ListOptions { } )
2016-02-04 22:12:05 +00:00
if err != nil {
return err
}
2016-05-11 18:17:26 +00:00
if err := printer . PrintObj ( pods , setupOutputWriter ( cmd , out , path . Join ( namespace , "pods.json" ) ) ) ; err != nil {
2016-02-04 22:12:05 +00:00
return err
}
2017-04-05 08:37:35 +00:00
printContainer := func ( writer io . Writer , container api . Container , pod * api . Pod ) {
writer . Write ( [ ] byte ( fmt . Sprintf ( "==== START logs for container %s of pod %s/%s ====\n" , container . Name , pod . Namespace , pod . Name ) ) )
defer writer . Write ( [ ] byte ( fmt . Sprintf ( "==== END logs for container %s of pod %s/%s ====\n" , container . Name , pod . Namespace , pod . Name ) ) )
request , err := f . LogsForObject ( pod , & api . PodLogOptions { Container : container . Name } , timeout )
2016-02-04 22:12:05 +00:00
if err != nil {
2017-04-05 08:37:35 +00:00
// Print error and return.
writer . Write ( [ ] byte ( fmt . Sprintf ( "Create log request error: %s\n" , err . Error ( ) ) ) )
return
2016-02-04 22:12:05 +00:00
}
data , err := request . DoRaw ( )
if err != nil {
2017-04-05 08:37:35 +00:00
// Print error and return.
writer . Write ( [ ] byte ( fmt . Sprintf ( "Request log error: %s\n" , err . Error ( ) ) ) )
return
2016-02-04 22:12:05 +00:00
}
writer . Write ( data )
2017-04-05 08:37:35 +00:00
}
for ix := range pods . Items {
pod := & pods . Items [ ix ]
containers := pod . Spec . Containers
writer := setupOutputWriter ( cmd , out , path . Join ( namespace , pod . Name , "logs.txt" ) )
for i := range containers {
printContainer ( writer , containers [ i ] , pod )
}
2016-02-04 22:12:05 +00:00
}
}
2016-05-11 18:17:26 +00:00
dir := cmdutil . GetFlagString ( cmd , "output-directory" )
if len ( dir ) == 0 {
2017-03-14 07:14:59 +00:00
dir = "standard output"
2016-05-11 18:17:26 +00:00
}
if dir != "-" {
2017-03-14 07:14:59 +00:00
fmt . Fprintf ( out , "Cluster info dumped to %s\n" , dir )
2016-05-11 18:17:26 +00:00
}
2016-02-04 22:12:05 +00:00
return nil
}