Skip to content

Commit

Permalink
Support passing a path for the TF binary
Browse files Browse the repository at this point in the history
Fixes #80
  • Loading branch information
paultyng committed May 21, 2020
1 parent b0f90d0 commit 26be653
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 10 deletions.
28 changes: 28 additions & 0 deletions commands/serve_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"syscall"

Expand All @@ -22,6 +23,7 @@ type ServeCommand struct {
// flags
port int
logFilePath string
tfExecPath string
tfExecLogPath string
}

Expand All @@ -31,6 +33,7 @@ func (c *ServeCommand) flags() *flag.FlagSet {
fs.IntVar(&c.port, "port", 0, "port number to listen on (turns server into TCP mode)")
fs.StringVar(&c.logFilePath, "log-file", "", "path to a file to log into with support "+
"for variables (e.g. Timestamp, Pid, Ppid) via Go template syntax {{.VarName}}")
fs.StringVar(&c.tfExecPath, "tf-exec", "", "path to Terraform binary")
fs.StringVar(&c.tfExecLogPath, "tf-log-file", "", "path to a file for Terraform executions"+
" to be logged into with support for variables (e.g. Timestamp, Pid, Ppid) via Go template"+
" syntax {{.VarName}}")
Expand Down Expand Up @@ -79,6 +82,31 @@ func (c *ServeCommand) Run(args []string) int {
srv := langserver.NewLangServer(ctx, handlers.NewSession)
srv.SetLogger(logger)

if c.tfExecPath != "" {
path := c.tfExecPath

logger.Printf("Setting Terraform exec path to %q", path)

// just some sanity checking here, no need to get too specific otherwise will be complex cross-OS
if !filepath.IsAbs(path) {
c.Ui.Error(fmt.Sprintf("Expected absolute path for Terraform binary, got %q", path))
return 1
}
stat, err := os.Stat(path)
if err != nil {
c.Ui.Error(fmt.Sprintf("Unable to find Terraform binary: %s", err))
return 1
}
if stat.IsDir() {
c.Ui.Error(fmt.Sprintf("Expected a Terraform binary, got a directory: %q", path))
return 1
}

srv.SetDiscoveryFunc(func() (string, error) {
return path, nil
})
}

if c.port != 0 {
err := srv.StartTCP(fmt.Sprintf("localhost:%d", c.port))
if err != nil {
Expand Down
12 changes: 8 additions & 4 deletions langserver/handlers/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type service struct {
sessCtx context.Context
stopSession context.CancelFunc

tfPath discovery.DiscoveryFunc
tfDiscoFunc discovery.DiscoveryFunc
ss *schema.Storage
executorFunc func(ctx context.Context, execPath string) *exec.Executor
}
Expand All @@ -44,7 +44,7 @@ func NewSession(srvCtx context.Context) session.Session {
sessCtx: sessCtx,
stopSession: stopSession,
executorFunc: exec.NewExecutor,
tfPath: d.LookPath,
tfDiscoFunc: d.LookPath,
ss: schema.NewStorage(),
}
}
Expand All @@ -53,6 +53,10 @@ func (svc *service) SetLogger(logger *log.Logger) {
svc.logger = logger
}

func (svc *service) SetDiscoveryFunc(f discovery.DiscoveryFunc) {
svc.tfDiscoFunc = f
}

// Assigner builds out the jrpc2.Map according to the LSP protocol
// and passes related dependencies to handlers via context
func (svc *service) Assigner() (jrpc2.Assigner, error) {
Expand Down Expand Up @@ -81,7 +85,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) {
ctx = lsctx.WithFilesystem(fs, ctx)
ctx = lsctx.WithClientCapabilitiesSetter(cc, ctx)

tfPath, err := svc.tfPath()
tfPath, err := svc.tfDiscoFunc()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -157,7 +161,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) {

ctx = lsctx.WithFilesystem(fs, ctx)

tfPath, err := svc.tfPath()
tfPath, err := svc.tfDiscoFunc()
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions langserver/handlers/service_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func (ms *mockSession) new(srvCtx context.Context) session.Session {
executorFunc: func(context.Context, string) *exec.Executor {
return exec.MockExecutor(ms.mid)
},
tfPath: d.LookPath,
ss: schema.MockStorage(nil),
tfDiscoFunc: d.LookPath,
ss: schema.MockStorage(nil),
}

return svc
Expand Down
18 changes: 14 additions & 4 deletions langserver/langserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ import (
"github.com/creachadair/jrpc2"
"github.com/creachadair/jrpc2/channel"
"github.com/creachadair/jrpc2/server"

"github.com/hashicorp/terraform-ls/internal/terraform/discovery"
"github.com/hashicorp/terraform-ls/langserver/session"
)

type langServer struct {
srvCtx context.Context
logger *log.Logger
srvOptions *jrpc2.ServerOptions
newSession session.SessionFactory
srvCtx context.Context
logger *log.Logger
tfDiscoFunc discovery.DiscoveryFunc
srvOptions *jrpc2.ServerOptions
newSession session.SessionFactory
}

func NewLangServer(srvCtx context.Context, sf session.SessionFactory) *langServer {
Expand All @@ -41,9 +44,16 @@ func (ls *langServer) SetLogger(logger *log.Logger) {
ls.logger = logger
}

func (ls *langServer) SetDiscoveryFunc(f discovery.DiscoveryFunc) {
ls.tfDiscoFunc = f
}

func (ls *langServer) newService() server.Service {
svc := ls.newSession(ls.srvCtx)
svc.SetLogger(ls.logger)
if ls.tfDiscoFunc != nil {
svc.SetDiscoveryFunc(ls.tfDiscoFunc)
}
return svc
}

Expand Down
3 changes: 3 additions & 0 deletions langserver/session/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import (
"log"

"github.com/creachadair/jrpc2"

"github.com/hashicorp/terraform-ls/internal/terraform/discovery"
)

type Session interface {
Assigner() (jrpc2.Assigner, error)
Finish(jrpc2.ServerStatus)
SetLogger(*log.Logger)
SetDiscoveryFunc(discovery.DiscoveryFunc)
}

type SessionFactory func(context.Context) Session

0 comments on commit 26be653

Please sign in to comment.