99 "context"
1010 "crypto/x509"
1111 "encoding/base64"
12+ "encoding/json"
1213 "encoding/pem"
1314 "errors"
1415 "fmt"
@@ -24,6 +25,7 @@ import (
2425 "github.com/siderolabs/gen/maps"
2526 "github.com/spf13/cobra"
2627 "google.golang.org/protobuf/types/known/durationpb"
28+ "gopkg.in/yaml.v3"
2729
2830 "github.com/siderolabs/talos/cmd/talosctl/pkg/talos/helpers"
2931 machineapi "github.com/siderolabs/talos/pkg/machinery/api/machine"
@@ -444,47 +446,58 @@ var configNewCmd = &cobra.Command{
444446}
445447
446448// configNewCmd represents the `config info` command output template.
447- var configInfoCmdTemplate = template .Must (template .New ("configInfoCmdTemplate" ).Option ("missingkey=error" ).Parse (strings .TrimSpace (`
449+ var configInfoCmdTemplate = template .Must (template .New ("configInfoCmdTemplate" ).
450+ Funcs (template.FuncMap {"join" : strings .Join }).
451+ Option ("missingkey=error" ).
452+ Parse (strings .TrimSpace (`
448453Current context: {{ .Context }}
449- Nodes: {{ .Nodes }}
450- Endpoints: {{ .Endpoints }}
454+ Nodes: {{ if .Nodes }}{{ join .Nodes ", " }}{{ else }}not defined{{ end }}
455+ Endpoints: {{ if .Endpoints }}{{ join .Endpoints ", " }}{{ else }}not defined{{ end }}
451456{{- if .Roles }}
452- Roles: {{ .Roles }}{{ end }}
457+ Roles: {{ join .Roles ", " }}{{ end }}
453458{{- if .CertTTL }}
454459Certificate expires: {{ .CertTTL }} ({{ .CertNotAfter }}){{ end }}
455460` )))
456461
457- // configInfoCommand implements `config info` command logic.
458- func configInfoCommand (config * clientconfig.Config , now time.Time ) (string , error ) {
462+ type talosconfigInfo struct {
463+ Context string `json:"context" yaml:"context"`
464+ Nodes []string `json:"nodes" yaml:"nodes"`
465+ Endpoints []string `json:"endpoints" yaml:"endpoints"`
466+ Roles []string `json:"roles" yaml:"roles"`
467+ CertTTL string `json:"certTTL" yaml:"certTTL"`
468+ CertNotAfter string `json:"certNotAfter" yaml:"certNotAfter"`
469+ }
470+
471+ // configInfo returns talosct config info.
472+ func configInfo (config * clientconfig.Config , now time.Time ) (talosconfigInfo , error ) {
459473 cfgContext , err := getContextData (config )
460474 if err != nil {
461- return "" , err
475+ return talosconfigInfo {} , err
462476 }
463477
464478 var (
465479 certTTL , certNotAfter string
466480 roles role.Set
467- rolesS string
468481 )
469482
470483 if cfgContext .Crt != "" {
471484 var b []byte
472485
473486 b , err = base64 .StdEncoding .DecodeString (cfgContext .Crt )
474487 if err != nil {
475- return "" , err
488+ return talosconfigInfo {} , err
476489 }
477490
478491 block , _ := pem .Decode (b )
479492 if block == nil {
480- return "" , fmt .Errorf ("error decoding PEM" )
493+ return talosconfigInfo {} , fmt .Errorf ("error decoding PEM" )
481494 }
482495
483496 var crt * x509.Certificate
484497
485498 crt , err = x509 .ParseCertificate (block .Bytes )
486499 if err != nil {
487- return "" , err
500+ return talosconfigInfo {} , err
488501 }
489502
490503 roles , _ = role .Parse (crt .Subject .Organization )
@@ -493,33 +506,33 @@ func configInfoCommand(config *clientconfig.Config, now time.Time) (string, erro
493506 certNotAfter = crt .NotAfter .UTC ().Format ("2006-01-02" )
494507 }
495508
496- nodesS := "not defined"
497- if len ( cfgContext . Nodes ) > 0 {
498- nodesS = strings . Join ( cfgContext .Nodes , ", " )
499- }
500-
501- endpointsS := "not defined"
502- if len ( cfgContext . Endpoints ) > 0 {
503- endpointsS = strings . Join ( cfgContext . Endpoints , ", " )
504- }
509+ return talosconfigInfo {
510+ Context : config . Context ,
511+ Nodes : cfgContext .Nodes ,
512+ Endpoints : cfgContext . Endpoints ,
513+ Roles : roles . Strings (),
514+ CertTTL : certTTL ,
515+ CertNotAfter : certNotAfter ,
516+ }, nil
517+ }
505518
506- if s := roles .Strings (); len (s ) > 0 {
507- rolesS = strings .Join (s , ", " )
519+ // configInfoCommand implements `config info` command logic.
520+ func configInfoCommand (config * clientconfig.Config , now time.Time ) (string , error ) {
521+ info , err := configInfo (config , now )
522+ if err != nil {
523+ return "" , err
508524 }
509525
510526 var res bytes.Buffer
511- err = configInfoCmdTemplate .Execute (& res , map [string ]string {
512- "Context" : config .Context ,
513- "Nodes" : nodesS ,
514- "Endpoints" : endpointsS ,
515- "Roles" : rolesS ,
516- "CertTTL" : certTTL ,
517- "CertNotAfter" : certNotAfter ,
518- })
527+ err = configInfoCmdTemplate .Execute (& res , info )
519528
520529 return res .String () + "\n " , err
521530}
522531
532+ var configInfoCmdFlags struct {
533+ output string
534+ }
535+
523536// configInfoCmd represents the `config info` command.
524537var configInfoCmd = & cobra.Command {
525538 Use : "info" ,
@@ -531,14 +544,36 @@ var configInfoCmd = &cobra.Command{
531544 return err
532545 }
533546
534- res , err := configInfoCommand (c , time .Now ())
535- if err != nil {
536- return err
537- }
547+ switch configInfoCmdFlags .output {
548+ case "text" :
549+ res , err := configInfoCommand (c , time .Now ())
550+ if err != nil {
551+ return err
552+ }
538553
539- fmt .Print (res )
554+ fmt .Print (res )
540555
541- return nil
556+ return nil
557+ case "json" :
558+ info , err := configInfo (c , time .Now ())
559+ if err != nil {
560+ return err
561+ }
562+
563+ enc := json .NewEncoder (os .Stdout )
564+ enc .SetIndent ("" , " " )
565+
566+ return enc .Encode (& info )
567+ case "yaml" :
568+ info , err := configInfo (c , time .Now ())
569+ if err != nil {
570+ return err
571+ }
572+
573+ return yaml .NewEncoder (os .Stdout ).Encode (& info )
574+ default :
575+ return fmt .Errorf ("unknown output format: %q" , configInfoCmdFlags .output )
576+ }
542577 },
543578}
544579
@@ -584,6 +619,8 @@ func init() {
584619 configNewCmd .Flags ().StringSliceVar (& configNewCmdFlags .roles , "roles" , role .MakeSet (role .Admin ).Strings (), "roles" )
585620 configNewCmd .Flags ().DurationVar (& configNewCmdFlags .crtTTL , "crt-ttl" , 87600 * time .Hour , "certificate TTL" )
586621
622+ configInfoCmd .Flags ().StringVarP (& configInfoCmdFlags .output , "output" , "o" , "text" , "output format (json|yaml|text). Default text." )
623+
587624 addCommand (configCmd )
588625}
589626
0 commit comments