package main
import (
"bufio"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"sync"
)
const (
workers = 10
bufferSize = 20
)
func cleanTerraformDirs(listFile string) error {
file, err := os.Open(listFile)
if err != nil {
return fmt.Errorf("open paths file: %w", err)
}
defer file.Close()
jobs := make(chan string, bufferSize)
var wg sync.WaitGroup
// Workers
for i := 0; i < workers; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
for basePath := range jobs {
if err := cleanTerraformDir(basePath); err != nil {
log.Printf(
"[worker %d] %s: %v",
id,
basePath,
err,
)
}
}
}(i)
}
// Lecture streaming des paths
scanner := bufio.NewScanner(file)
for scanner.Scan() {
basePath := scanner.Text()
if basePath == "" {
continue
}
jobs <- basePath
}
close(jobs)
wg.Wait()
return scanner.Err()
}
func cleanTerraformDir(basePath string) error {
terraformDir := filepath.Join(basePath, ".terraform")
info, err := os.Lstat(terraformDir)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
}
return err
}
if !info.IsDir() {
return fmt.Errorf("%s existe mais n'est pas un directory", terraformDir)
}
return os.RemoveAll(terraformDir)
}
func main() {
if err := cleanTerraformDirs("paths.txt"); err != nil {
log.Fatal(err)
}
}- list l'ensemble des workspaces avec un list.go
- remove all
.terraformdirectory - retourne la list des workspace actif
- run cmd
string[]{"init", "-upgrade"}uniquement sur la list de workspaces actif
Si tu veux retrouver le fichier terraform.tfstate dans un répertoire, tu as plusieurs possibilités selon ton besoin.
Si le fichier est toujours directement dans le dossier :
/project/
├── terraform.tfstate
└── .terraform/
Tu peux simplement faire :
func FindTerraformState(root string) (string, bool, error) {
path := filepath.Join(root, "terraform.tfstate")
info, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return "", false, nil
}
return "", false, err
}
if info.IsDir() {
return "", false, nil
}
return path, true, nil
}Utilisation :
path, found, err := FindTerraformState("/my/project")
if err != nil {
return err
}
if found {
fmt.Println(path)
}Si le fichier peut être n'importe où :
/projects/
├── app1/
│ └── terraform.tfstate
├── app2/
│ └── envs/
│ └── prod/
│ └── terraform.tfstate
Utilise filepath.WalkDir :
func FindTerraformState(root string) ([]string, error) {
var states []string
err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && d.Name() == "terraform.tfstate" {
states = append(states, path)
}
return nil
})
if err != nil {
return nil, err
}
return states, nil
}Exemple :
states, err := FindTerraformState("/projects")
if err != nil {
return err
}
for _, state := range states {
fmt.Println(state)
}Si tu parcours plus de 100 000 répertoires, éviter :
var states []stringet préférer un callback :
func FindTerraformState(root string, fn func(string) error) error {
return filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && d.Name() == "terraform.tfstate" {
return fn(path)
}
return nil
})
}Utilisation :
err := FindTerraformState("/projects", func(path string) error {
fmt.Println(path)
// Lire, déplacer ou supprimer ici
return nil
})Cela garde une consommation mémoire constante.
Pour Terraform, le cas le plus fréquent est :
/my-project/
├── terraform.tfstate
├── terraform.tfstate.backup
└── .terraform/
Donc la version simple avec :
filepath.Join(projectPath, "terraform.tfstate")est souvent suffisante et beaucoup plus rapide qu'un WalkDir.