Skip to content

Commit 08d08a3

Browse files
committed
Add scripts/tfbackend-cli
1 parent 1256cd5 commit 08d08a3

File tree

7 files changed

+198
-60
lines changed

7 files changed

+198
-60
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,3 @@ appsettings.Development.json
356356
.terraform/
357357
.terraform.lock.hcl
358358
errored.tfstate
359-
360-
# temp script files
361-
scripts/add-user.js

CONTRIBUTING.md

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
# Contribution guide
22

3-
## Application
3+
## Application codebase
44

5-
The code is entirely based on open-source, cross-platform (Linux/Windows), highly performant, free, object-oriented technologies: .NET / C#.
6-
7-
### Projects
5+
### .NET projects
86

97
Project name | Technology | Project type
108
---------------------------|------------|---------------------------
@@ -15,7 +13,7 @@ Project name | Technology | Project type
1513
`Infrastructure.MongoDb` | .NET 8 | Library
1614
`WebApi` | ASP.NET 8 | Web application (REST API)
1715

18-
### Packages (NuGet)
16+
### .NET packages (NuGet)
1917

2018
Name | Description
2119
-------------------------|-----------------------------
@@ -24,16 +22,10 @@ Name | Description
2422
`Swashbuckle.AspNetCore` | OpenAPI / Swagger generation
2523
`System.Text.Json` | JSON support
2624

27-
### Clients
28-
29-
- [OpenTofu](https://opentofu.org/)
30-
- [Terraform](https://www.terraform.io)
31-
- [HTTP backend](https://developer.hashicorp.com/terraform/language/backend/http)
32-
- [Remote state backend](https://github.com/hashicorp/terraform/tree/main/internal/backend/remote-state)
33-
34-
### Backing services
25+
### Terraform specifications
3526

36-
- [MongoDB](https://www.mongodb.com/)
27+
- [HTTP backend](https://developer.hashicorp.com/terraform/language/backend/http)
28+
- [Remote state backend](https://github.com/hashicorp/terraform/tree/main/internal/backend/remote-state)
3729

3830
### Other community implementations
3931

@@ -74,7 +66,7 @@ dotnet run --project src/WebApi
7466

7567
Open Swagger in a browser: [localhost:5293/swagger](http://localhost:5293/swagger).
7668

77-
## Documentation
69+
## Documentation codebase
7870

7971
The documentation is a static website built with [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/).
8072

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Welcome
22

3-
This project provides an HTTP backend for Terraform and OpenTofu that will save and manage state data in a MongoDB database.
3+
This project provides an HTTP backend for [Terraform](https://www.terraform.io) and [OpenTofu](https://opentofu.org/) that will save and manage state data in a [MongoDB](https://www.mongodb.com/) database.
44

55
As the state is a JSON content, it makes sense to use the best-in-class database technology to work with it.
66

docs/project.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ New features:
2727

2828
- :material-square: Store in the database only one version of the state in tf_state (the latest) and save the others in tf_state_revision
2929
- :material-square: Send traces, logs, metrics to OpenTelemetry Collector
30+
31+
## Design
32+
33+
### Programming languages
34+
35+
The code is mainly written in C# / .NET: open-source, cross-platform (Linux/Windows), highly performant, object-oriented.

scripts/mongo-create-index.js

Lines changed: 0 additions & 2 deletions
This file was deleted.

scripts/mongo-create-user.sh

Lines changed: 0 additions & 39 deletions
This file was deleted.

scripts/tfbackend-cli

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#!/bin/bash
2+
3+
# tfbackend-cli create-index
4+
# tfbackend-cli create-user myusername mypassword mytenant
5+
6+
MONGODB_URI="${MONGODB_URI:-mongodb://mongodb:27017}"
7+
MONGODB_DB="${MONGODB_DB:-test}"
8+
MONGODB_CONTAINERNAME="${MONGODB_CONTAINERNAME:-mongodb}"
9+
10+
MONGODB_INDEX_COMMANDS=(
11+
'db.tf_state.createIndex({"tenant": 1, "name": 1})'
12+
'db.tf_state_lock.createIndex({"tenant": 1, "name": 1})'
13+
)
14+
15+
log_info() {
16+
local message="$1"
17+
echo -e "$message"
18+
}
19+
20+
log_header() {
21+
local message="$1"
22+
echo -e "\033[1;34m$message\033[0m" # blue
23+
}
24+
25+
log_success() {
26+
local message="$1"
27+
echo -e "\033[1;32m$message\033[0m" # green
28+
}
29+
30+
log_warn() {
31+
local message="$1"
32+
echo -e "\033[1;33mWarn: $message\033[0m" # yello
33+
}
34+
35+
log_error() {
36+
local message="$1"
37+
echo -e "\033[1;31mError: $message\033[0m" # red
38+
}
39+
40+
usage() {
41+
echo -e "\033[1;34mUsage:\033[0m $0 [command] [arguments...]"
42+
echo -e "\033[1;34mCommands:\033[0m"
43+
echo " create-index : Create indexes in database"
44+
echo " create-user <username> <password> <tenant> : Create user in database"
45+
echo " help : Show this help message"
46+
# echo " (no arguments) : Run in interactive mode"
47+
exit 1
48+
}
49+
50+
check_command() {
51+
local cmd=$1
52+
if command -v "$cmd" &> /dev/null; then
53+
return 0
54+
else
55+
return 1
56+
fi
57+
}
58+
59+
check_htpasswd() {
60+
if ! command -v htpasswd &> /dev/null; then
61+
log_error "htpasswd is not installed."
62+
log_info "Please install apache2-utils (on Debian/Ubuntu) or httpd-tools (on CentOS/RHEL)."
63+
log_info "Installation commands:"
64+
log_info " Debian/Ubuntu: sudo apt-get install apache2-utils"
65+
log_info " CentOS/RHEL: sudo yum install httpd-tools"
66+
exit 1
67+
fi
68+
}
69+
70+
execute_mongosh() {
71+
local mongo_cmd="$1"
72+
if check_command "mongosh"; then
73+
execute_mongosh_package "$mongo_cmd" || exit 1
74+
else
75+
if check_command "docker"; then
76+
execute_mongosh_docker "$mongo_cmd" || exit 1
77+
else
78+
echo "Error: Neither mongosh nor Docker is installed. Please install one to proceed."
79+
exit 1
80+
fi
81+
fi
82+
}
83+
84+
execute_mongosh_package() {
85+
local mongo_cmd="$1"
86+
log_info "Executing MongoDB command in the shell: $mongo_cmd"
87+
if output=$(mongosh "$MONGODB_URI/$MONGODB_DB" --quiet --eval "$mongo_cmd" 2>&1); then
88+
log_info "Output:\n$output"
89+
else
90+
log_warn "$output"
91+
return 1
92+
fi
93+
}
94+
95+
execute_mongosh_docker() {
96+
local mongo_cmd="$1"
97+
log_info "Executing MongoDB command in a container: $mongo_cmd"
98+
if output=$(docker run --rm --link "$MONGODB_CONTAINERNAME" mongo:8.0 bash -c "mongosh \"$MONGODB_URI/$MONGODB_DB\" --quiet --eval \"$mongo_cmd\"" 2>&1); then
99+
log_info "Output:\n$output"
100+
else
101+
log_warn "$output"
102+
return 1
103+
fi
104+
}
105+
106+
create_mongodb_indexes() {
107+
local status=0
108+
log_header "Creating predefined MongoDB indexes"
109+
for cmd in "${MONGODB_INDEX_COMMANDS[@]}"; do
110+
execute_mongosh "$cmd" || status=1
111+
done
112+
if [ $status -eq 0 ]; then
113+
log_success "All indexes created successfully"
114+
else
115+
log_error "One or more index creations failed"
116+
fi
117+
return $status
118+
}
119+
120+
create_user() {
121+
local username=$1
122+
local password=$2
123+
local tenant=$3
124+
125+
hash=$(htpasswd -bnBC 10 "" "$password" | tr -d ':\n')
126+
if [ $? -ne 0 ] || [ -z "$hash" ]; then
127+
log_error "Failed to generate BCrypt hash"
128+
exit 1
129+
fi
130+
131+
creation_command=$(cat <<EOF
132+
db.user.insertOne({
133+
username: '$username',
134+
password_hash: '$(printf "%q" "$hash")',
135+
tenant: '$tenant'
136+
})
137+
EOF
138+
)
139+
140+
execute_mongosh "$creation_command" || return 1
141+
execute_mongosh "db.user.createIndex({\"username\": 1}, {unique: true})" || return 1
142+
}
143+
144+
# checks for command-line arguments
145+
if [ $# -gt 0 ]; then
146+
case "$1" in
147+
"create-index")
148+
create_mongodb_indexes
149+
exit $?
150+
;;
151+
"create-user")
152+
check_htpasswd
153+
shift
154+
if [ -z "$1" ]; then
155+
log_error "No username provided"
156+
usage
157+
fi
158+
username="$1"
159+
shift
160+
if [ -z "$1" ]; then
161+
log_error "No password provided"
162+
usage
163+
fi
164+
password="$1"
165+
shift
166+
if [ -z "$1" ]; then
167+
log_error "No tenant provided"
168+
usage
169+
fi
170+
tenant="$1"
171+
create_user "$username" "$password" "$tenant"
172+
exit $?
173+
;;
174+
"help")
175+
usage
176+
;;
177+
*)
178+
log_error "Invalid command: $1"
179+
usage
180+
;;
181+
esac
182+
fi
183+
184+
usage

0 commit comments

Comments
 (0)