github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/cli/openapi.go (about)

     1  package cli
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"net/http"
     7  	"time"
     8  
     9  	"github.com/spf13/cobra"
    10  	"k8s.io/cli-runtime/pkg/genericclioptions"
    11  	"k8s.io/client-go/rest"
    12  	"k8s.io/client-go/transport"
    13  
    14  	"github.com/tilt-dev/tilt-apiserver/pkg/server/apiserver"
    15  	"github.com/tilt-dev/tilt/internal/analytics"
    16  	engineanalytics "github.com/tilt-dev/tilt/internal/engine/analytics"
    17  	"github.com/tilt-dev/tilt/internal/hud/server"
    18  	"github.com/tilt-dev/tilt/internal/store"
    19  	"github.com/tilt-dev/tilt/internal/xdg"
    20  	"github.com/tilt-dev/tilt/pkg/assets"
    21  	"github.com/tilt-dev/tilt/pkg/model"
    22  )
    23  
    24  type openapiCmd struct {
    25  	streams genericclioptions.IOStreams
    26  }
    27  
    28  var _ tiltCmd = &openapiCmd{}
    29  
    30  func newOpenapiCmd(streams genericclioptions.IOStreams) *openapiCmd {
    31  	return &openapiCmd{streams: streams}
    32  }
    33  
    34  func (c *openapiCmd) name() model.TiltSubcommand { return "openapi" }
    35  
    36  func (c *openapiCmd) register() *cobra.Command {
    37  	cmd := &cobra.Command{
    38  		Use:     "openapi",
    39  		Short:   "Print the openapi spec of the current tilt binary",
    40  		Example: "tilt dump openapi > swagger.json",
    41  	}
    42  
    43  	return cmd
    44  }
    45  
    46  func (c *openapiCmd) run(ctx context.Context, args []string) error {
    47  	a := analytics.Get(ctx)
    48  
    49  	cmdTags := engineanalytics.CmdTags(map[string]string{})
    50  	a.Incr("cmd.openapi", cmdTags.AsMap())
    51  	defer a.Flush(time.Second)
    52  
    53  	hs, err := newHeadlessServer(ctx)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	defer hs.tearDown(ctx)
    58  
    59  	restConfig := hs.loopbackClientConfig
    60  	trConfig, err := restConfig.TransportConfig()
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	tr, err := transport.New(trConfig)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	httpClient := http.Client{Transport: tr}
    71  	resp, err := httpClient.Get(restConfig.Host + "/openapi/v2")
    72  	if err != nil {
    73  		return err
    74  	}
    75  	defer resp.Body.Close()
    76  
    77  	var msg json.RawMessage
    78  	err = json.NewDecoder(resp.Body).Decode(&msg)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	encoder := json.NewEncoder(c.streams.Out)
    84  	encoder.SetIndent("", "  ")
    85  	return encoder.Encode(msg)
    86  }
    87  
    88  type headlessServer struct {
    89  	memconn              apiserver.ConnProvider
    90  	hudsc                *server.HeadsUpServerController
    91  	loopbackClientConfig *rest.Config
    92  }
    93  
    94  func newHeadlessServer(ctx context.Context) (*headlessServer, error) {
    95  	memconn := server.ProvideMemConn()
    96  	genCert, err := server.ProvideKeyCert("headless", "localhost", 0, xdg.NewTiltDevBase())
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	serverOptions, err := server.ProvideTiltServerOptionsForHeadless(ctx, genCert, memconn, tiltInfo())
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	webListener, err := server.ProvideWebListener("localhost", 0)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	hudsc := server.ProvideHeadsUpServerController(
   109  		nil, "tilt-headless", webListener, serverOptions,
   110  		&server.HeadsUpServer{}, assets.NewFakeServer(), model.WebURL{})
   111  	st := store.NewTestingStore()
   112  	err = hudsc.SetUp(ctx, st)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	return &headlessServer{
   117  		memconn:              memconn,
   118  		hudsc:                hudsc,
   119  		loopbackClientConfig: serverOptions.GenericConfig.LoopbackClientConfig,
   120  	}, nil
   121  }
   122  
   123  func (hs *headlessServer) tearDown(ctx context.Context) {
   124  	hs.hudsc.TearDown(ctx)
   125  }