mirror of https://github.com/coder/coder.git
113 lines
2.8 KiB
Go
113 lines
2.8 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/xerrors"
|
|
|
|
"cdr.dev/slog"
|
|
"cdr.dev/slog/sloggers/sloghuman"
|
|
"github.com/coder/coder/coderd"
|
|
"github.com/coder/coder/codersdk"
|
|
"github.com/coder/coder/database"
|
|
"github.com/coder/coder/database/databasefake"
|
|
"github.com/coder/coder/provisioner/terraform"
|
|
"github.com/coder/coder/provisionerd"
|
|
"github.com/coder/coder/provisionersdk"
|
|
"github.com/coder/coder/provisionersdk/proto"
|
|
)
|
|
|
|
func daemon() *cobra.Command {
|
|
var (
|
|
address string
|
|
)
|
|
root := &cobra.Command{
|
|
Use: "daemon",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
logger := slog.Make(sloghuman.Sink(os.Stderr))
|
|
accessURL := &url.URL{
|
|
Scheme: "http",
|
|
Host: address,
|
|
}
|
|
handler, closeCoderd := coderd.New(&coderd.Options{
|
|
AccessURL: accessURL,
|
|
Logger: logger,
|
|
Database: databasefake.New(),
|
|
Pubsub: database.NewPubsubInMemory(),
|
|
})
|
|
|
|
listener, err := net.Listen("tcp", address)
|
|
if err != nil {
|
|
return xerrors.Errorf("listen %q: %w", address, err)
|
|
}
|
|
defer listener.Close()
|
|
|
|
logger.Info(cmd.Context(), "daemon started", slog.F("url", accessURL.String()))
|
|
|
|
client := codersdk.New(accessURL)
|
|
daemonClose, err := newProvisionerDaemon(cmd.Context(), client, logger)
|
|
if err != nil {
|
|
return xerrors.Errorf("create provisioner daemon: %w", err)
|
|
}
|
|
defer daemonClose.Close()
|
|
|
|
errCh := make(chan error)
|
|
go func() {
|
|
defer close(errCh)
|
|
errCh <- http.Serve(listener, handler)
|
|
}()
|
|
|
|
closeCoderd()
|
|
select {
|
|
case <-cmd.Context().Done():
|
|
return cmd.Context().Err()
|
|
case err := <-errCh:
|
|
return err
|
|
}
|
|
},
|
|
}
|
|
defaultAddress, ok := os.LookupEnv("ADDRESS")
|
|
if !ok {
|
|
defaultAddress = "127.0.0.1:3000"
|
|
}
|
|
root.Flags().StringVarP(&address, "address", "a", defaultAddress, "The address to serve the API and dashboard.")
|
|
|
|
return root
|
|
}
|
|
|
|
func newProvisionerDaemon(ctx context.Context, client *codersdk.Client, logger slog.Logger) (io.Closer, error) {
|
|
terraformClient, terraformServer := provisionersdk.TransportPipe()
|
|
go func() {
|
|
err := terraform.Serve(ctx, &terraform.ServeOptions{
|
|
ServeOptions: &provisionersdk.ServeOptions{
|
|
Listener: terraformServer,
|
|
},
|
|
Logger: logger,
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
tempDir, err := ioutil.TempDir("", "provisionerd")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return provisionerd.New(client.ListenProvisionerDaemon, &provisionerd.Options{
|
|
Logger: logger,
|
|
PollInterval: 50 * time.Millisecond,
|
|
UpdateInterval: 50 * time.Millisecond,
|
|
Provisioners: provisionerd.Provisioners{
|
|
string(database.ProvisionerTypeTerraform): proto.NewDRPCProvisionerClient(provisionersdk.Conn(terraformClient)),
|
|
},
|
|
WorkDirectory: tempDir,
|
|
}), nil
|
|
}
|