Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: disambiguate abs/rel paths with types. #1894

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 82 additions & 78 deletions cmd/terramate/cli/cli.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cmd/terramate/cli/cliconfig/cliconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func TestLoad(t *testing.T) {
homeEntry := s.DirEntry("home")
file := homeEntry.CreateFile(cliconfig.Filename, tc.cfg)

cfg, err := cliconfig.LoadFrom(file.HostPath())
cfg, err := cliconfig.LoadFrom(file.Path())
errtest.Assert(t, err, tc.want.err)
if err != nil {
return
Expand Down
17 changes: 9 additions & 8 deletions cmd/terramate/cli/cloud_sync_terraform_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"bytes"
"context"
"encoding/json"
"os"
stdos "os"
"os/exec"
"path/filepath"
"time"
Expand All @@ -17,6 +17,7 @@ import (
"github.com/terramate-io/terramate/cloud"
"github.com/terramate-io/terramate/cmd/terramate/cli/clitest"
"github.com/terramate-io/terramate/errors"
"github.com/terramate-io/terramate/os"
"github.com/terramate-io/tfjson"
"github.com/terramate-io/tfjson/sanitize"
)
Expand Down Expand Up @@ -45,11 +46,11 @@ func (c *cli) getTerraformChangeset(run stackCloudRun) (*cloud.ChangesetDetails,
return nil, errors.E(clitest.ErrCloudInvalidTerraformPlanFilePath, "path must be relative to the running stack")
}

absPlanFilePath := filepath.Join(run.Stack.HostDir(c.cfg()), planfile)
absPlanFilePath := run.Stack.HostDir(c.cfg()).Join(planfile)

// Terragrunt writes the plan to a temporary directory, so we cannot check for its existence.
if !run.Task.UseTerragrunt {
_, err := os.Lstat(absPlanFilePath)
_, err := stdos.Lstat(absPlanFilePath.String())
if err != nil {
return nil, errors.E(err, "checking plan file")
}
Expand Down Expand Up @@ -137,7 +138,7 @@ func (c *cli) runTerraformShow(run stackCloudRun, flags ...string) (string, erro
defer cancel()

cmd := exec.CommandContext(ctx, cmdName, args...)
cmd.Dir = run.Stack.Dir.HostPath(c.rootdir())
cmd.Dir = run.Stack.Dir.HostPath(c.rootdir()).String()
cmd.Stdout = &stdout
cmd.Stderr = &stderr
cmd.Env = run.Env
Expand All @@ -162,15 +163,15 @@ func (c *cli) runTerraformShow(run stackCloudRun, flags ...string) (string, erro
return stdout.String(), nil
}

func extractTFStateSerial(planfile string) (int64, bool) {
func extractTFStateSerial(planfile os.Path) (int64, bool) {
logger := log.With().
Str("action", "extractTFStateSerial").
Str("planfile", planfile).
Stringer("planfile", planfile).
Logger()

planReader, err := zip.OpenReader(planfile)
planReader, err := zip.OpenReader(planfile.String())
if err != nil {
if b, err := os.ReadFile(planfile); err == nil {
if b, err := stdos.ReadFile(planfile.String()); err == nil {
if bytes.HasPrefix(b, []byte("tfplan")) {
logger.Debug().Msg("plan serial extraction failed: plan file was created with a pre 1.22 version of terraform")
} else {
Expand Down
5 changes: 2 additions & 3 deletions cmd/terramate/cli/github/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package github_test

import (
"os"
"path/filepath"
"testing"

"github.com/madlambda/spells/assert"
Expand All @@ -29,7 +28,7 @@ func TestGetEventPR(t *testing.T) {
draft bool
}

nonExistentEventFile := filepath.Join(test.NonExistingDir(t), "event_pull_request.json")
nonExistentEventFile := test.NonExistingDir(t).Join("event_pull_request.json")

type testcase struct {
name string
Expand All @@ -56,7 +55,7 @@ func TestGetEventPR(t *testing.T) {
{
name: "non existent path",
env: map[string]string{
"GITHUB_EVENT_PATH": nonExistentEventFile,
"GITHUB_EVENT_PATH": nonExistentEventFile.String(),
},
want: want{
err: os.ErrNotExist,
Expand Down
8 changes: 5 additions & 3 deletions cmd/terramate/cli/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package cli
import (
"fmt"

"github.com/terramate-io/terramate/os"

"github.com/rs/zerolog/log"
"github.com/terramate-io/terramate/config"
"github.com/terramate-io/terramate/errors"
Expand All @@ -16,8 +18,8 @@ import (
)

type project struct {
rootdir string
wd string
rootdir os.Path
wd os.Path
isRepo bool
root config.Root
baseRef string
Expand Down Expand Up @@ -178,7 +180,7 @@ func (p project) defaultBranchRef() string {
func (p *project) setDefaults() error {
logger := log.With().
Str("action", "setDefaults()").
Str("workingDir", p.wd).
Stringer("workingDir", p.wd).
Logger()

logger.Debug().Msg("Set defaults.")
Expand Down
4 changes: 2 additions & 2 deletions cmd/terramate/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ func (c *cli) runAll(
cmd := exec.Command(backend.Command[0], backend.Command[1:]...)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
cmd.Dir = otherStack.HostDir(c.cfg())
cmd.Dir = otherStack.HostDir(c.cfg()).String()
var inputVal cty.Value
err := cmd.Run()
if err != nil {
Expand Down Expand Up @@ -579,7 +579,7 @@ func (c *cli) runAll(
}

cmd := exec.Command(cmdPath, task.Cmd[1:]...)
cmd.Dir = run.Stack.HostDir(c.cfg())
cmd.Dir = run.Stack.HostDir(c.cfg()).String()
cmd.Env = environ

stdout := c.stdout
Expand Down
16 changes: 10 additions & 6 deletions cmd/tgdeps/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
"encoding/json"
"flag"
"fmt"
"os"
stdos "os"

"github.com/rs/zerolog"
"github.com/terramate-io/terramate/os"
"github.com/terramate-io/terramate/project"
"github.com/terramate-io/terramate/tg"
)
Expand All @@ -25,12 +26,15 @@ func main() {
if *trace {
zerolog.SetGlobalLevel(zerolog.TraceLevel)
}
rootdir, err := os.Getwd()
rootdirStr, err := stdos.Getwd()
abortOnErr(err)

var dir string
// assume current dir is project root dir.
rootdir := os.NewHostPath(rootdirStr)

var dir os.Path
if len(flag.Args()) == 2 {
dir = flag.Arg(1)
dir = rootdir.Join(flag.Arg(1))
} else {
dir = rootdir
}
Expand All @@ -56,7 +60,7 @@ func main() {

func abortOnErr(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "error: %s\n", err)
os.Exit(1)
fmt.Fprintf(stdos.Stderr, "error: %s\n", err)
stdos.Exit(1)
}
}
59 changes: 30 additions & 29 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"bytes"
"fmt"
"io/fs"
"os"
stdos "os"
"path"
"path/filepath"
"sort"
Expand All @@ -25,6 +25,7 @@ import (
"github.com/terramate-io/terramate/hcl"
"github.com/terramate-io/terramate/hcl/ast"
"github.com/terramate-io/terramate/hcl/info"
"github.com/terramate-io/terramate/os"
"github.com/terramate-io/terramate/printer"
"github.com/terramate-io/terramate/project"
"github.com/zclconf/go-cty/cty"
Expand Down Expand Up @@ -72,7 +73,7 @@ type Tree struct {
root *Root
stack *Stack

dir string
dir os.Path
}

// DirElem represents a node which is represented by a directory.
Expand All @@ -89,7 +90,7 @@ type List[T DirElem] []T
// the config in fromdir and all parent directories until / is reached.
// If the configuration is found, it returns the whole configuration tree,
// configpath != "" and found as true.
func TryLoadConfig(fromdir string) (tree *Root, configpath string, found bool, err error) {
func TryLoadConfig(fromdir os.Path) (tree *Root, configpath os.Path, found bool, err error) {
for {
ok, err := hcl.IsRootConfig(fromdir)
if err != nil {
Expand Down Expand Up @@ -130,7 +131,7 @@ func NewRoot(tree *Tree) *Root {
}

// LoadRoot loads the root configuration tree.
func LoadRoot(rootdir string) (*Root, error) {
func LoadRoot(rootdir os.Path) (*Root, error) {
rootcfg, err := hcl.ParseDir(rootdir, rootdir)
if err != nil {
return nil, err
Expand All @@ -148,7 +149,7 @@ func LoadRoot(rootdir string) (*Root, error) {
func (root *Root) Tree() *Tree { return &root.tree }

// HostDir returns the root directory.
func (root *Root) HostDir() string { return root.tree.RootDir() }
func (root *Root) Path() os.Path { return root.tree.Path() }

// Lookup a node from the root using a filesystem query path.
func (root *Root) Lookup(path project.Path) (*Tree, bool) {
Expand Down Expand Up @@ -229,20 +230,20 @@ func (root *Root) LoadSubTree(cfgdir project.Path) error {
parentNode = root.Tree()
}

rootdir := root.HostDir()
rootdir := root.Path()

relpath := strings.TrimPrefix(cfgdir.String(), parent.String())
relpath = strings.TrimPrefix(relpath, "/")
components := strings.Split(relpath, "/")
nextComponent := components[0]
subtreeDir := filepath.Join(rootdir, parent.String(), nextComponent)
subtreeDir := rootdir.Join(parent.String(), nextComponent)

node, err := loadTree(root.Tree(), subtreeDir, nil)
if err != nil {
return errors.E(err, "failed to load config from %s", subtreeDir)
}

if node.HostDir() == rootdir {
if node.Path() == rootdir {
// root configuration reloaded
*root = *NewRoot(node)
} else {
Expand All @@ -269,8 +270,8 @@ func (root *Root) Runtime() project.Runtime {

func (root *Root) initRuntime() {
rootfs := cty.ObjectVal(map[string]cty.Value{
"absolute": cty.StringVal(root.HostDir()),
"basename": cty.StringVal(filepath.ToSlash(filepath.Base(root.HostDir()))),
"absolute": cty.StringVal(root.Path().String()),
"basename": cty.StringVal(filepath.ToSlash(filepath.Base(root.Path().String()))),
})
rootpath := cty.ObjectVal(map[string]cty.Value{
"fs": rootfs,
Expand All @@ -288,8 +289,8 @@ func (root *Root) initRuntime() {
}
}

// HostDir is the node absolute directory in the host.
func (tree *Tree) HostDir() string {
// Path is the node absolute directory in the host.
func (tree *Tree) Path() os.Path {
return tree.dir
}

Expand All @@ -299,7 +300,7 @@ func (tree *Tree) Dir() project.Path {
}

// RootDir returns the tree root directory..
func (tree *Tree) RootDir() string {
func (tree *Tree) RootDir() os.Path {
if tree.Parent != nil {
return tree.Parent.RootDir()
}
Expand Down Expand Up @@ -422,13 +423,13 @@ func (l List[T]) Len() int { return len(l) }
func (l List[T]) Less(i, j int) bool { return l[i].Dir().String() < l[j].Dir().String() }
func (l List[T]) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

func loadTree(parentTree *Tree, cfgdir string, rootcfg *hcl.Config) (_ *Tree, err error) {
func loadTree(parentTree *Tree, cfgdir os.Path, rootcfg *hcl.Config) (_ *Tree, err error) {
logger := log.With().
Str("action", "config.loadTree()").
Str("dir", cfgdir).
Stringer("dir", cfgdir).
Logger()

f, err := os.Open(cfgdir)
f, err := stdos.Open(cfgdir.String())
if err != nil {
return nil, errors.E(err, "failed to open cfg directory")
}
Expand Down Expand Up @@ -469,7 +470,7 @@ func loadTree(parentTree *Tree, cfgdir string, rootcfg *hcl.Config) (_ *Tree, er

tree.Node = cfg
tree.Parent = parentTree
parentTree.Children[filepath.Base(cfgdir)] = tree
parentTree.Children[cfgdir.Base()] = tree

parentTree = tree
}
Expand All @@ -485,7 +486,7 @@ func loadTree(parentTree *Tree, cfgdir string, rootcfg *hcl.Config) (_ *Tree, er
continue
}

dir := filepath.Join(cfgdir, fname)
dir := cfgdir.Join(fname)
node, err := loadTree(parentTree, dir, rootcfg)
if err != nil {
return nil, errors.E(err, "loading from %s", dir)
Expand All @@ -497,7 +498,7 @@ func loadTree(parentTree *Tree, cfgdir string, rootcfg *hcl.Config) (_ *Tree, er
return parentTree, nil
}

func processTmGenFiles(rootTree *Tree, cfg *hcl.Config, cfgdir string, dirEntries []fs.DirEntry) error {
func processTmGenFiles(rootTree *Tree, cfg *hcl.Config, cfgdir os.Path, dirEntries []fs.DirEntry) error {
const tmgenSuffix = ".tmgen"

tmgenEnabled := rootTree.hasExperiment("tmgen")
Expand All @@ -509,7 +510,7 @@ func processTmGenFiles(rootTree *Tree, cfg *hcl.Config, cfgdir string, dirEntrie
continue
}

absFname := filepath.Join(cfgdir, fname)
absFname := cfgdir.Join(fname)

if !tmgenEnabled {
printer.Stderr.Warn(
Expand All @@ -520,7 +521,7 @@ func processTmGenFiles(rootTree *Tree, cfg *hcl.Config, cfgdir string, dirEntrie
continue
}

content, err := os.ReadFile(absFname)
content, err := stdos.ReadFile(absFname.String())
if err != nil {
return errors.E(err, "failed to read .tmgen file")
}
Expand Down Expand Up @@ -559,10 +560,10 @@ func processTmGenFiles(rootTree *Tree, cfg *hcl.Config, cfgdir string, dirEntrie

implicitGenBlock := hcl.GenHCLBlock{
IsImplicitBlock: true,
Dir: project.PrjAbsPath(rootTree.HostDir(), cfgdir),
Dir: project.PrjAbsPath(rootTree.Path(), cfgdir),
Inherit: inheritAttr,
Range: info.NewRange(rootTree.HostDir(), hhcl.Range{
Filename: absFname,
Range: info.NewRange(rootTree.Path(), hhcl.Range{
Filename: absFname.String(),
Start: hhcl.InitialPos,
End: hhcl.Pos{
Line: nLines,
Expand Down Expand Up @@ -596,13 +597,13 @@ func (tree *Tree) NonEmptyGlobalsParent() *Tree {
}

// IsStack returns true if the given directory is a stack, false otherwise.
func IsStack(root *Root, dir string) bool {
node, ok := root.Lookup(project.PrjAbsPath(root.HostDir(), dir))
func IsStack(root *Root, dir os.Path) bool {
node, ok := root.Lookup(project.PrjAbsPath(root.Path(), dir))
return ok && node.IsStack()
}

// NewTree creates a new tree node.
func NewTree(cfgdir string) *Tree {
func NewTree(cfgdir os.Path) *Tree {
return &Tree{
dir: cfgdir,
Children: make(map[string]*Tree),
Expand Down Expand Up @@ -677,8 +678,8 @@ func Skip(name string) bool {
return name[0] == '.'
}

func parentDir(dir string) (string, bool) {
parent := filepath.Dir(dir)
func parentDir(dir os.Path) (os.Path, bool) {
parent := dir.Dir()
return parent, parent != dir
}

Expand Down
Loading
Loading