github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/appbuilder/discover/discover.go (about)

     1  // Copyright (c) 2022, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package discover
     6  
     7  import (
     8  	"context"
     9  	"encoding/json"
    10  	"fmt"
    11  
    12  	"github.com/choria-io/appbuilder/builder"
    13  	"github.com/choria-io/fisk"
    14  	"github.com/choria-io/go-choria/choria"
    15  	"github.com/choria-io/go-choria/client/discovery"
    16  	"github.com/choria-io/go-choria/config"
    17  	"github.com/choria-io/go-choria/providers/appbuilder"
    18  	"github.com/sirupsen/logrus"
    19  )
    20  
    21  type Command struct {
    22  	StandardFilter bool                       `json:"std_filters"`
    23  	Filter         *discovery.StandardOptions `json:"filter"`
    24  	builder.GenericCommand
    25  	builder.GenericSubCommands
    26  }
    27  
    28  type Discover struct {
    29  	b         *builder.AppBuilder
    30  	cmd       *fisk.CmdClause
    31  	fo        *discovery.StandardOptions
    32  	def       *Command
    33  	cfg       any
    34  	arguments map[string]any
    35  	flags     map[string]any
    36  	json      bool
    37  	log       builder.Logger
    38  	ctx       context.Context
    39  }
    40  
    41  func NewDiscoverCommand(b *builder.AppBuilder, j json.RawMessage, log builder.Logger) (builder.Command, error) {
    42  	find := &Discover{
    43  		arguments: map[string]any{},
    44  		flags:     map[string]any{},
    45  		def:       &Command{},
    46  		cfg:       b.Configuration(),
    47  		ctx:       b.Context(),
    48  		log:       log,
    49  		b:         b,
    50  	}
    51  
    52  	err := json.Unmarshal(j, find.def)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	return find, nil
    58  }
    59  
    60  func Register() error {
    61  	return builder.RegisterCommand("discover", NewDiscoverCommand)
    62  }
    63  
    64  func MustRegister() {
    65  	builder.MustRegisterCommand("discover", NewDiscoverCommand)
    66  }
    67  
    68  func (r *Discover) Validate(log builder.Logger) error { return nil }
    69  
    70  func (r *Discover) String() string { return fmt.Sprintf("%s (discover)", r.def.Name) }
    71  
    72  func (r *Discover) SubCommands() []json.RawMessage {
    73  	return r.def.Commands
    74  }
    75  
    76  func (r *Discover) CreateCommand(app builder.KingpinCommand) (*fisk.CmdClause, error) {
    77  	r.cmd = builder.CreateGenericCommand(app, &r.def.GenericCommand, r.arguments, r.flags, r.b, r.runCommand)
    78  
    79  	r.fo = discovery.NewStandardOptions()
    80  
    81  	if r.def.StandardFilter {
    82  		r.fo.AddFilterFlags(r.cmd)
    83  		r.fo.AddFlatFileFlags(r.cmd)
    84  		r.fo.AddSelectionFlags(r.cmd)
    85  	}
    86  
    87  	r.cmd.Flag("json", "Produce JSON output").BoolVar(&r.json)
    88  
    89  	return r.cmd, nil
    90  }
    91  
    92  func (r *Discover) runCommand(_ *fisk.ParseContext) error {
    93  	cfg, err := config.NewConfig(choria.UserConfig())
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	logger, ok := any(r.log).(*logrus.Logger)
    99  	if ok {
   100  		cfg.CustomLogger = logger
   101  	}
   102  
   103  	fw, err := choria.NewWithConfig(cfg)
   104  	if err != nil {
   105  		return err
   106  	}
   107  
   108  	log := fw.Logger("find")
   109  
   110  	if r.def.Filter != nil {
   111  		err = appbuilder.ProcessStdDiscoveryOptions(r.def.Filter, r.arguments, r.flags, r.cfg)
   112  		if err != nil {
   113  			return err
   114  		}
   115  
   116  		r.fo.Merge(r.def.Filter)
   117  	}
   118  
   119  	r.fo.SetDefaultsFromChoria(fw)
   120  
   121  	targets, _, err := r.fo.Discover(r.ctx, fw, "discovery", true, false, log)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	if r.json {
   127  		out, err := json.MarshalIndent(targets, "", "  ")
   128  		if err != nil {
   129  			return err
   130  		}
   131  		fmt.Println(string(out))
   132  		return nil
   133  	}
   134  
   135  	for _, t := range targets {
   136  		fmt.Println(t)
   137  	}
   138  
   139  	return nil
   140  }