Last active
May 8, 2019 21:10
-
-
Save bart0sh/9d16471ac1e20f7c81a996bb68afbcb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type OutputType string | |
const ( | |
Text OutputType = "text" | |
YAML = "yaml" | |
JSON = "json" | |
) | |
type Output interface { | |
Out(name string, data interface{}) | |
Flush() error | |
} | |
// Marshal returns data representation in the specified output format | |
func Marshal(data interface{}, outputFormat OutputType) (string, error) { | |
if outputFormat == JSON || outputFormat == YAML { | |
bytes, err := json.MarshalIndent(data, "", " ") | |
if err != nil { | |
return "", err | |
} | |
if outputFormat == YAML { | |
bytes, err = yaml.JSONToYAML(bytes) | |
if err != nil { | |
return "", errors.Wrap(err, "failed to convert JSON output to YAML") | |
} | |
} | |
return string(bytes), nil | |
} | |
return "", errors.Errorf("invalid output format: %s. It should be either YAML or JSON.", outputFormat) | |
} | |
// BootstrapTokenList represents information for JSON and YAML output produced by 'kubeadm token list' | |
type BootstrapTokenList struct { | |
PublicKeyPins []string `json:"publicKeyPins"` | |
ControlPlaneHostPort string `json:"controlPlaneHostPort"` | |
Tokens []*kubeadmapiv1beta1.BootstrapToken `json:"tokens"` | |
} | |
type OutputItem struct { | |
name string | |
data interface{} | |
} | |
type tokenOutput struct { | |
outWriter io.Writer | |
errWriter io.Writer | |
tabWriter io.Writer | |
outputFormat OutputType | |
outputItems []*OutputItem | |
} | |
func (to *tokenOutput) Out(name string, data interface{}) { | |
if to.outputFormat == Text { | |
if to.tabWriter == nil { | |
var out bytes.Buffer | |
to.tabWriter = tabwriter.NewWriter(to.outWriter, 10, 4, 3, ' ', 0) | |
fmt.Fprintln(to.tabWriter, "TOKEN\tDESCRIPTION\tEXPIRES\tTTL") | |
} | |
if name == "token" { | |
token := *kubeadmapiv1beta1.BootstrapToken(data) | |
// Get the human-friendly string representation for the token | |
humanFriendlyTokenOutput := humanReadableBootstrapToken(token) | |
fmt.Fprintln(to.tabWriter, humanFriendlyTokenOutput) | |
} | |
} else if to.outputFormat == YAML || to.outputFormat == JSON { | |
to.outputItems = append(to.outputItems, &OutputItem{name, data}) | |
} | |
} | |
func (to *tokenOutput) Flush() error { | |
if to.outputFormat == YAML || to.outputFormat == JSON { | |
tList := BootstrapTokenList{} | |
for _, item := range to.outputItems { | |
switch item.name { | |
case "token": | |
tList.Tokens = append(tList.Tokens, item.data) | |
case "publicKeyPins": | |
tList.PublicKeyPins = item.data | |
case "controlPlaneHostPort": | |
tList.ControlPlaneHostPort = item.data | |
} | |
} | |
formatted, err := utils.Marshal(tList, to.outputFormat) | |
if err != nil { | |
return err | |
} | |
fmt.Printf(to.outWriter, formatted) | |
} | |
return nil | |
} | |
// RunListTokens lists details on all existing bootstrap tokens on the server. | |
func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface, kubeConfigFile, outputFormat OutputType) error { | |
// First, build our selector for bootstrap tokens only | |
klog.V(1).Infoln("[token] preparing selector for bootstrap token") | |
tokenSelector := fields.SelectorFromSet( | |
map[string]string{ | |
// TODO: We hard-code "type" here until `field_constants.go` that is | |
// currently in `pkg/apis/core/` exists in the external API, i.e. | |
// k8s.io/api/v1. Should be v1.SecretTypeField | |
"type": string(bootstrapapi.SecretTypeBootstrapToken), | |
}, | |
) | |
listOptions := metav1.ListOptions{ | |
FieldSelector: tokenSelector.String(), | |
} | |
klog.V(1).Infoln("[token] retrieving list of bootstrap tokens") | |
secrets, err := client.CoreV1().Secrets(metav1.NamespaceSystem).List(listOptions) | |
if err != nil { | |
return errors.Wrap(err, "failed to list bootstrap tokens") | |
} | |
output := tokenOutput{outWriter: out, errWriter: errW, outputFormat: outputFormat} | |
for _, secret := range secrets.Items { | |
// Get the BootstrapToken struct representation from the Secret object | |
token, err := kubeadmapi.BootstrapTokenFromSecret(&secret) | |
if err != nil { | |
fmt.Fprintf(errW, "%v", err) | |
continue | |
} | |
output.Out("token", token) | |
} | |
clusterConfig, err := cmdutil.GetClusterConfig(kubeConfigFile) | |
if err != nil { | |
return errors.Wrapf(err, "failed to load cluster config from %s", kubeConfigFile) | |
} | |
publicKeyPins, err := cmdutil.GetCAPubKeyPins(clusterConfig) | |
if err != nil { | |
return errors.Wrapf(err, "failed to get CA certs hashes from cluster config") | |
} | |
output.Out("publicKeyPins", publicKeyPins) | |
output.Out("controlPlaneHostPort", strings.Replace(clusterConfig.Server, "https://", "", -1)) | |
return output.Flush() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment