Skip to content

Commit 7986dcf

Browse files
committed
added quick start with init command
1 parent f8ad7ac commit 7986dcf

3 files changed

Lines changed: 207 additions & 0 deletions

File tree

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@
77
- After the temporary folder is ready, it executes `terraform` or `tofu` with specified parameters
88
- Maintains separate state files for each environment/layer, automatically providing configuration for remote state management (different path on the storage regarding configured layers/dimensions). So the deployed set (configuration + terraform) is stored in different `tfstate` files in remote storage (S3, GCS)
99

10+
## Quick start with demo configuration
11+
12+
1. [Download release](https://github.com/alt-dima/tofugu/releases) version >= 0.5.0
13+
2. Install [OpenTofu](https://opentofu.org/docs/intro/install/)
14+
3. Execute to generate simpe demo configuration with connection to demo account in [Infrastructure layers Configuration Management Database (CMDB). (Toaster-ToasterDB)](#infrastructure-layers-configuration-management-database-cmdb-toaster-toasterdb):
15+
```bash
16+
tofugu init
17+
```
18+
To generate with [file based inventory](#infrastructure-layersdimensions-configurations-storage):
19+
```bash
20+
tofugu init --toaster=false
21+
```
22+
4. Follow on-screen instructions
23+
1024
## Quick start with AI Coding Assistants
1125

1226
Getting started with `tofugu` is even easier using AI coding assistants:

cmd/inittofu.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"path/filepath"
8+
9+
"github.com/alt-dima/tofugu/utils"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
// initCmd represents the init command
14+
var initCmd = &cobra.Command{
15+
Use: "init",
16+
Short: "Initialize a new tofugu working directory",
17+
Long: `Create a new tofugu working directory with default structure and .tofugu config file`,
18+
Run: func(cmd *cobra.Command, args []string) {
19+
// Get target directory, default to current directory
20+
targetDir, _ := cmd.Flags().GetString("target-dir")
21+
if targetDir == "" {
22+
var err error
23+
targetDir, err = os.Getwd()
24+
if err != nil {
25+
log.Fatalf("Failed to get current directory: %v", err)
26+
}
27+
}
28+
29+
tofuguConfigPath := filepath.Join(targetDir, ".tofugu")
30+
if _, err := os.Stat(tofuguConfigPath); err == nil {
31+
// File exists
32+
overwrite, _ := cmd.Flags().GetBool("force")
33+
if !overwrite {
34+
log.Fatalf(".tofugu file already exists. Use --force to overwrite")
35+
}
36+
log.Printf("Overwriting existing .tofugu file")
37+
}
38+
39+
utils.CreateExampleTofuguConfigFile(tofuguConfigPath)
40+
41+
// Create example organization structure if requested
42+
createExample, _ := cmd.Flags().GetBool("with-example")
43+
useToasterDB, _ := cmd.Flags().GetBool("toaster")
44+
var exampleCmd string
45+
if createExample {
46+
exampleCmd = utils.CreateExampleStructure(targetDir, useToasterDB)
47+
}
48+
49+
fmt.Println("\nTofugu workspace initialized successfully!")
50+
fmt.Println("\nTo use this workspace:")
51+
fmt.Println("1. Make sure you have OpenTofu installed: https://opentofu.org/docs/intro/install/")
52+
fmt.Printf("2. Navigate to: %s\n", targetDir)
53+
fmt.Println("3. Run a command like:")
54+
if createExample {
55+
fmt.Print(exampleCmd)
56+
} else {
57+
fmt.Println(" tofugu cook -o your-org -d dimension:value -t tofi -- init")
58+
fmt.Println(" tofugu cook -o your-org -d dimension:value -t tofi -- plan")
59+
fmt.Println(" tofugu cook -o your-org -d dimension:value -t tofi -- apply")
60+
}
61+
fmt.Println("\nYou can customize the .tofugu file for your specific needs. Add S3 backend configuration if required.")
62+
fmt.Println("Do not to forget to try Infrastructure layers/dimensions configurations Storage: https://toaster.altuhov.su/")
63+
},
64+
}
65+
66+
func init() {
67+
rootCmd.AddCommand(initCmd)
68+
69+
// Define flags for the init command
70+
initCmd.Flags().StringP("target-dir", "d", "", "Target directory for the new tofugu workspace (defaults to current directory)")
71+
initCmd.Flags().BoolP("toaster", "t", true, "Use ToasterDB toaster.altuhov.su for inventory data")
72+
initCmd.Flags().BoolP("force", "f", false, "Force overwrite of existing .tofugu file")
73+
initCmd.Flags().BoolP("with-example", "e", true, "Create an example organization structure with sample files")
74+
}

utils/init_examples.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"path/filepath"
8+
)
9+
10+
const exampleOrg = "example-org"
11+
12+
// writeExampleFile is a helper function to write a file with given content and log the result
13+
func writeExampleFile(targetPath, content, fileType string) {
14+
// Create parent directories if they don't exist
15+
if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil {
16+
log.Fatalf("Failed to create directory for %s: %v", fileType, err)
17+
}
18+
19+
// Write the file
20+
if err := os.WriteFile(targetPath, []byte(content), 0644); err != nil {
21+
log.Fatalf("Failed to create %s file: %v", fileType, err)
22+
}
23+
24+
fmt.Printf("Created %s file: %s\n", fileType, targetPath)
25+
}
26+
27+
// CreateExampleStructure creates an example organization structure with sample configuration files
28+
func CreateExampleStructure(targetDir string, useToasterDB bool) string {
29+
var exampleCmd string
30+
31+
// Create simple manifest file for demo tofi
32+
manifestContent := `{
33+
"dimensions": ["account", "datacenter"]
34+
}`
35+
manifestPath := filepath.Join(targetDir, "examples", "tofies", exampleOrg, "demo", "tofi_manifest.json")
36+
writeExampleFile(manifestPath, manifestContent, "example tofi manifest")
37+
38+
// Create output.tf file
39+
outputContent := `output "account_region_from_inv" {
40+
value = var.tofugu_account_data.region
41+
}
42+
43+
output "account_id_from_inv" {
44+
value = var.tofugu_account_data.account_id
45+
}
46+
47+
output "datacenter_name_from_inv" {
48+
value = var.tofugu_datacenter_name
49+
}
50+
51+
output "datacenter_vpc_cidr_from_inv" {
52+
value = var.tofugu_datacenter_data.vpc_cidr
53+
}
54+
55+
output "datacenter_az_count_from_inv" {
56+
value = var.tofugu_datacenter_data.az_count
57+
}`
58+
outputPath := filepath.Join(targetDir, "examples", "tofies", exampleOrg, "demo", "output.tf")
59+
writeExampleFile(outputPath, outputContent, "example output.tf")
60+
61+
if !useToasterDB {
62+
63+
// Create a simple example account.json file
64+
exampleAccountContent := `{
65+
"account_id": "123456789012",
66+
"region": "us-east-1"
67+
}`
68+
accountPath := filepath.Join(targetDir, "examples", "inventory", exampleOrg, "account", "dev.json")
69+
writeExampleFile(accountPath, exampleAccountContent, "example account")
70+
71+
// Create example datacenter.json file
72+
exampleDevDatacenterContent := `{
73+
"vpc_cidr": "10.0.0.0/16",
74+
"az_count": 1
75+
}`
76+
datacenterDevPath := filepath.Join(targetDir, "examples", "inventory", exampleOrg, "datacenter", "dev.json")
77+
writeExampleFile(datacenterDevPath, exampleDevDatacenterContent, "example dev datacenter")
78+
79+
// Create example datacenter.json file
80+
exampleProdDatacenterContent := `{
81+
"vpc_cidr": "10.2.0.0/16",
82+
"az_count": 3
83+
}`
84+
datacenterProdPath := filepath.Join(targetDir, "examples", "inventory", exampleOrg, "datacenter", "prod.json")
85+
writeExampleFile(datacenterProdPath, exampleProdDatacenterContent, "example prod datacenter")
86+
} else {
87+
exampleCmd = " export toasterurl=https://662cab7c5e116819738b01fe:supertoaster@toaster.altuhov.su\n"
88+
}
89+
90+
exampleCmd = exampleCmd +
91+
" tofugu cook -o " + exampleOrg + " -d account:dev -d datacenter:dev -t demo -- init\n" +
92+
" tofugu cook -o " + exampleOrg + " -d account:dev -d datacenter:dev -t demo -- plan\n" +
93+
"Notice output from opentofu and now execute with prod datacenter:\n" +
94+
" tofugu cook -o " + exampleOrg + " -d account:dev -d datacenter:prod -t demo -- init\n" +
95+
" tofugu cook -o " + exampleOrg + " -d account:dev -d datacenter:prod -t demo -- plan\n" +
96+
"Notice different output from opentofu based on different inventory data but same Terraform code!\n"
97+
98+
return exampleCmd
99+
}
100+
101+
// GetTofuguConfigContent returns the content for the .tofugu configuration file
102+
func CreateExampleTofuguConfigFile(tofuguConfigPath string) {
103+
content := `defaults:
104+
tofies_path: examples/tofies
105+
# shared_modules_path: examples/tofies/shared-modules
106+
inventory_path: examples/inventory
107+
cmd_to_exec: tofu
108+
# backend:
109+
# bucket: my-tfstates
110+
# key: $tofugu_state_path
111+
# region: us-east-1
112+
# Add additional organization-specific configurations as needed:
113+
# example-org:
114+
# backend:
115+
# bucket: example-org-tfstates
116+
# prefix: $tofugu_state_path
117+
`
118+
writeExampleFile(tofuguConfigPath, content, ".tofugu configuration")
119+
}

0 commit comments

Comments
 (0)