Skip to content

Commit f46c13d

Browse files
committed
feat : Add devcontainer and vscode config
-> Add Devcontainer to cloud deployment -> devcontainer docker from docker to use host system -> Add vscode debug configs -> Add debug extenstions -> unique jwt key generations Signed-off-by: Nabendu Maiti <nabendu.bikash.maiti@intel.com>
1 parent efd3346 commit f46c13d

8 files changed

Lines changed: 598 additions & 0 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
2+
3+
# 1. Define the arguments to accept them from devcontainer.json
4+
ARG HTTP_PROXY
5+
ARG HTTPS_PROXY
6+
ARG NO_PROXY
7+
ARG http_proxy
8+
ARG https_proxy
9+
ARG no_proxy
10+
11+
# 2. Export them as environment variables
12+
ENV HTTP_PROXY=$HTTP_PROXY
13+
ENV HTTPS_PROXY=$HTTPS_PROXY
14+
ENV NO_PROXY=$NO_PROXY
15+
ENV http_proxy=$http_proxy
16+
ENV https_proxy=$https_proxy
17+
ENV no_proxy=$no_proxy
18+
19+
# 3. Ensure sudo keeps these variables (crucial for features that use sudo)
20+
RUN echo 'Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy"' >> /etc/sudoers
21+
22+
# 4. Prime the apt cache with proxy settings active
23+
RUN apt-get update
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"features": {
3+
"ghcr.io/devcontainers/features/common-utils:2": {
4+
"version": "2.5.9",
5+
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
6+
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
7+
},
8+
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
9+
"version": "1.10.0",
10+
"resolved": "ghcr.io/devcontainers/features/docker-outside-of-docker@sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e",
11+
"integrity": "sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e"
12+
},
13+
"ghcr.io/devcontainers/features/go:1": {
14+
"version": "1.3.4",
15+
"resolved": "ghcr.io/devcontainers/features/go@sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032",
16+
"integrity": "sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032"
17+
},
18+
"ghcr.io/devcontainers/features/node:2": {
19+
"version": "2.1.0",
20+
"resolved": "ghcr.io/devcontainers/features/node@sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857",
21+
"integrity": "sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857"
22+
}
23+
}
24+
}

.devcontainer/devcontainer.json

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"name": "Cloud Deployment Dev Container",
3+
"build": {
4+
"dockerfile": "Dockerfile",
5+
"args": {
6+
"HTTP_PROXY": "${localEnv:HTTP_PROXY:}",
7+
"HTTPS_PROXY": "${localEnv:HTTPS_PROXY:}",
8+
"NO_PROXY": "${localEnv:NO_PROXY:}",
9+
"http_proxy": "${localEnv:http_proxy:}",
10+
"https_proxy": "${localEnv:https_proxy:}",
11+
"no_proxy": "${localEnv:no_proxy:}"
12+
}
13+
},
14+
"features": {
15+
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
16+
"version": "latest",
17+
"enableNonRootDocker": "true",
18+
"moby": "true"
19+
},
20+
"ghcr.io/devcontainers/features/node:2": {
21+
"version": "lts"
22+
},
23+
"ghcr.io/devcontainers/features/go:1": {
24+
"version": "latest"
25+
},
26+
"ghcr.io/devcontainers/features/common-utils:2": {
27+
"installZsh": true,
28+
"configureZshAsDefaultShell": true,
29+
"installOhMyZsh": true,
30+
"upgradePackages": true
31+
}
32+
},
33+
"containerEnv": {
34+
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}",
35+
"HTTP_PROXY": "${localEnv:HTTP_PROXY:}",
36+
"HTTPS_PROXY": "${localEnv:HTTPS_PROXY:}",
37+
"NO_PROXY": "${localEnv:NO_PROXY:}",
38+
"http_proxy": "${localEnv:http_proxy:}",
39+
"https_proxy": "${localEnv:https_proxy:}",
40+
"no_proxy": "${localEnv:no_proxy:}"
41+
},
42+
"forwardPorts": [
43+
4200,
44+
3000,
45+
8081,
46+
8003
47+
],
48+
"customizations": {
49+
"vscode": {
50+
"extensions": [
51+
"ms-azuretools.vscode-docker",
52+
"dbaeumer.vscode-eslint",
53+
"golang.go",
54+
"ms-vscode.cpptools",
55+
"ryu1kn.text-marker",
56+
"shd101wyy.markdown-preview-enhanced",
57+
"shardulm94.trailing-spaces",
58+
"waderyan.gitblame",
59+
"esbenp.prettier-vscode"
60+
]
61+
}
62+
},
63+
"initializeCommand": "bash .devcontainer/pre-create.sh",
64+
"postCreateCommand": "/bin/bash .devcontainer/post-create.sh"
65+
}

.devcontainer/post-create.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Unset empty proxy variables
5+
for var in HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy; do
6+
eval v="\${$var}"
7+
if [ -z "$v" ]; then unset $var; fi
8+
done
9+
10+
# Strip all trailing '/' or '\\' from proxy URLs for apt config
11+
strip_trailing_slash() {
12+
local url="$1"
13+
# Remove all trailing / or \
14+
url="${url%%*(/|\\)}"
15+
# Fallback for Bash < 4.0 (no extglob): use sed
16+
echo "$url" | sed 's%[\\/]*$%%'
17+
}
18+
19+
if [ -n "$HTTP_PROXY" ] || [ -n "$http_proxy" ] || [ -n "$HTTPS_PROXY" ] || [ -n "$https_proxy" ]; then
20+
echo "Configuring apt to use proxy..."
21+
sudo mkdir -p /etc/apt/apt.conf.d
22+
# Remove all trailing / or \\ from proxy URLs
23+
apt_http_proxy="$(strip_trailing_slash "${HTTP_PROXY:-${http_proxy:-}}")"
24+
apt_https_proxy="$(strip_trailing_slash "${HTTPS_PROXY:-${https_proxy:-}}")"
25+
sudo tee /etc/apt/apt.conf.d/99proxy > /dev/null <<EOF
26+
Acquire::http::Proxy "$apt_http_proxy";
27+
Acquire::https::Proxy "$apt_https_proxy";
28+
EOF
29+
fi
30+
31+
# Update package lists and install build tools
32+
sudo apt-get update && sudo apt-get install -y build-essential cmake
33+
34+
# Install Go development tools
35+
go install github.com/air-verse/air@latest
36+
go install github.com/go-delve/delve/cmd/dlv@latest
37+
go install github.com/google/go-licenses@latest
38+
39+
echo "✓ Post-create setup completed successfully"

.devcontainer/pre-create.sh

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#!/bin/bash
2+
3+
# This script runs on the host machine BEFORE the container is created.
4+
# It is cross-platform compatible (Windows with Git Bash, Linux, macOS)
5+
6+
set -e
7+
8+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
10+
11+
TEMPLATE_FILE="$REPO_ROOT/.env.template"
12+
OUTPUT_FILE="$REPO_ROOT/.env"
13+
KONG_FILE="$REPO_ROOT/kong.yaml"
14+
CYPRESS_CONFIG="$REPO_ROOT/sample-web-ui/cypress.config.ts"
15+
DOCKER_COMPOSE_FILE="$REPO_ROOT/docker-compose.yml"
16+
README_FILE="$REPO_ROOT/Readme.md"
17+
REPO_TYPE=""
18+
19+
# Function to generate random 32-character string (cross-platform)
20+
generate_random_string() {
21+
if command -v openssl &> /dev/null; then
22+
openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32
23+
elif [[ -c /dev/urandom ]]; then
24+
tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 32
25+
elif command -v python3 &> /dev/null; then
26+
python3 -c "import random; import string; print(''.join(random.choices(string.ascii_letters + string.digits, k=32)))"
27+
else
28+
# Fallback: use timestamp + random
29+
date +%s%N | sha256sum | tr -dc 'a-zA-Z0-9' | head -c 32
30+
fi
31+
}
32+
33+
# Function to get the host IP address (cross-platform)
34+
get_host_ip() {
35+
if command -v hostname &> /dev/null && hostname -I &> /dev/null 2>&1; then
36+
# Linux
37+
hostname -I | awk '{print $1}'
38+
elif [[ "$OSTYPE" == "darwin"* ]]; then
39+
# macOS
40+
ipconfig getifaddr en0 2>/dev/null || echo "localhost"
41+
else
42+
# Windows (Git Bash) or fallback
43+
echo "localhost"
44+
fi
45+
}
46+
47+
# Cross-platform sed replacement (handles both GNU sed and BSD sed)
48+
sed_replace() {
49+
local file="$1"
50+
local pattern="$2"
51+
local replacement="$3"
52+
53+
if [[ "$OSTYPE" == "darwin"* ]]; then
54+
# macOS uses BSD sed
55+
sed -i '' "s|$pattern|$replacement|g" "$file"
56+
else
57+
# Linux and others use GNU sed
58+
sed -i "s|$pattern|$replacement|g" "$file"
59+
fi
60+
}
61+
62+
# Function to validate repository
63+
validate_repository() {
64+
if [ -f "$README_FILE" ] && grep -q "Device Management Toolkit (formerly known as Open AMT Cloud Toolkit)" "$README_FILE"; then
65+
REPO_TYPE="DMT"
66+
echo "✓ Detected: Device Management Toolkit repository"
67+
return 0
68+
fi
69+
70+
echo "✗ Error: Unrecognized repository. This script must be run from the Device Management Toolkit repository."
71+
exit 1
72+
}
73+
74+
# Function to handle DMT-specific operations
75+
dmt_operations() {
76+
echo "=========================================="
77+
echo "Environment Configuration Setup"
78+
echo "=========================================="
79+
80+
dmt_generate_defaults
81+
dmt_populate_env_file
82+
dmt_update_kong_config
83+
dmt_update_cypress_config
84+
dmt_update_docker_compose
85+
86+
echo "=========================================="
87+
echo "Configuration complete!"
88+
echo "=========================================="
89+
}
90+
91+
# Function to generate default values for DMT
92+
dmt_generate_defaults() {
93+
DEFAULT_MPS_COMMON_NAME=$(get_host_ip) # Automatically detected system IP address
94+
DEFAULT_MPS_WEB_ADMIN_USER="hspeoob" # Default admin username for MPS web interface
95+
DEFAULT_MPS_WEB_ADMIN_PASSWORD="Apple-1234" # Default admin password for MPS web interface
96+
DEFAULT_MPS_JWT_SECRET=$(generate_random_string) # Randomly generated 32-char JWT secret
97+
DEFAULT_MPS_JWT_ISSUER=$(generate_random_string) # Randomly generated 32-char JWT issuer key
98+
DEFAULT_POSTGRES_PASSWORD="Apple-1234" # Default PostgreSQL database password
99+
DEFAULT_VAULT_TOKEN=$(generate_random_string) # Randomly generated 32-char Vault token
100+
}
101+
102+
# Function to populate .env file for DMT
103+
dmt_populate_env_file() {
104+
if [ -f "$OUTPUT_FILE" ] && grep -qE "^MPS_JWT_SECRET=.+$" "$OUTPUT_FILE"; then
105+
echo "✓ Existing .env with MPS_JWT_SECRET found; skipping .env generation."
106+
return 0
107+
fi
108+
109+
echo "Creating and populating .env file..."
110+
cp "$TEMPLATE_FILE" "$OUTPUT_FILE"
111+
112+
sed_replace "$OUTPUT_FILE" "^MPS_COMMON_NAME=.*" "MPS_COMMON_NAME=$DEFAULT_MPS_COMMON_NAME"
113+
sed_replace "$OUTPUT_FILE" "^MPS_WEB_ADMIN_USER=.*" "MPS_WEB_ADMIN_USER=$DEFAULT_MPS_WEB_ADMIN_USER"
114+
sed_replace "$OUTPUT_FILE" "^MPS_WEB_ADMIN_PASSWORD=.*" "MPS_WEB_ADMIN_PASSWORD=$DEFAULT_MPS_WEB_ADMIN_PASSWORD"
115+
sed_replace "$OUTPUT_FILE" "^MPS_JWT_SECRET=.*" "MPS_JWT_SECRET=$DEFAULT_MPS_JWT_SECRET"
116+
sed_replace "$OUTPUT_FILE" "^MPS_JWT_ISSUER=.*" "MPS_JWT_ISSUER=$DEFAULT_MPS_JWT_ISSUER"
117+
sed_replace "$OUTPUT_FILE" "^POSTGRES_PASSWORD=.*" "POSTGRES_PASSWORD=$DEFAULT_POSTGRES_PASSWORD"
118+
sed_replace "$OUTPUT_FILE" "^VAULT_TOKEN=.*" "VAULT_TOKEN=$DEFAULT_VAULT_TOKEN"
119+
120+
echo "✓ .env file has been created and populated with default values."
121+
}
122+
123+
# Function to update kong.yaml for DMT
124+
dmt_update_kong_config() {
125+
if [ -f "$KONG_FILE" ]; then
126+
# Check if MPS_JWT_SECRET in .env is empty
127+
if grep -qE "^MPS_JWT_SECRET=.+$" "$OUTPUT_FILE"; then
128+
echo "Updating kong.yaml with JWT secrets..."
129+
# Read the actual values from .env file
130+
ACTUAL_JWT_SECRET=$(grep "^MPS_JWT_SECRET=" "$OUTPUT_FILE" | cut -d'=' -f2)
131+
ACTUAL_JWT_ISSUER=$(grep "^MPS_JWT_ISSUER=" "$OUTPUT_FILE" | cut -d'=' -f2)
132+
133+
sed_replace "$KONG_FILE" "key: [a-zA-Z0-9]* #sample key" "key: $ACTUAL_JWT_ISSUER #sample key"
134+
sed_replace "$KONG_FILE" "secret:.*" "secret: \"$ACTUAL_JWT_SECRET\""
135+
echo "✓ kong.yaml has been updated with JWT secrets."
136+
else
137+
echo "⚠ Warning: MPS_JWT_SECRET in .env is empty, skipping Kong configuration."
138+
fi
139+
else
140+
echo "⚠ Warning: kong.yaml not found, skipping Kong configuration."
141+
fi
142+
}
143+
144+
# Function to update cypress.config.ts for DMT
145+
dmt_update_cypress_config() {
146+
if [ -f "$CYPRESS_CONFIG" ]; then
147+
echo "Updating cypress.config.ts with credentials..."
148+
sed_replace "$CYPRESS_CONFIG" "MPS_USERNAME: '.*'" "MPS_USERNAME: '$DEFAULT_MPS_WEB_ADMIN_USER'"
149+
sed_replace "$CYPRESS_CONFIG" "MPS_PASSWORD: '.*'" "MPS_PASSWORD: '$DEFAULT_MPS_WEB_ADMIN_PASSWORD'"
150+
sed_replace "$CYPRESS_CONFIG" "VAULT_TOKEN: '.*'" "VAULT_TOKEN: '$DEFAULT_VAULT_TOKEN'"
151+
echo "✓ cypress.config.ts has been updated with credentials."
152+
else
153+
echo "⚠ Warning: cypress.config.ts not found, skipping Cypress configuration."
154+
fi
155+
}
156+
157+
# Function to update docker-compose.yml with proxy and workspace folder
158+
dmt_update_docker_compose() {
159+
if [ -f "$DOCKER_COMPOSE_FILE" ]; then
160+
echo "Updating docker-compose.yml with workspace folder variable..."
161+
162+
# Replace relative volume paths with ${LOCAL_WORKSPACE_FOLDER:-.} literal variable reference
163+
sed_replace "$DOCKER_COMPOSE_FILE" "- \\./nginx\\.conf:" "- \${LOCAL_WORKSPACE_FOLDER:-.}/nginx.conf:"
164+
sed_replace "$DOCKER_COMPOSE_FILE" "- \\./data:" "- \${LOCAL_WORKSPACE_FOLDER:-.}/data:"
165+
sed_replace "$DOCKER_COMPOSE_FILE" "- \\./kong\\.yaml:" "- \${LOCAL_WORKSPACE_FOLDER:-.}/kong.yaml:"
166+
sed_replace "$DOCKER_COMPOSE_FILE" "- \\./mosquitto\\.conf:" "- \${LOCAL_WORKSPACE_FOLDER:-.}/mosquitto.conf:"
167+
echo " ✓ Volume paths updated with \${LOCAL_WORKSPACE_FOLDER:-.}"
168+
169+
# Update proxy environment variables from host system
170+
HTTP_PROXY="${HTTP_PROXY:-}"
171+
HTTPS_PROXY="${HTTPS_PROXY:-}"
172+
NO_PROXY="${NO_PROXY:-}"
173+
http_proxy="${http_proxy:-}"
174+
https_proxy="${https_proxy:-}"
175+
no_proxy="${no_proxy:-}"
176+
177+
if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ] || [ -n "$NO_PROXY" ]; then
178+
echo " Configuring HTTP proxy: $HTTP_PROXY"
179+
echo " Configuring HTTPS proxy: $HTTPS_PROXY"
180+
echo " Configuring NO_PROXY: $NO_PROXY"
181+
fi
182+
183+
# Note: The proxy settings are already parameterized in docker-compose.yml
184+
# They will be picked up from the environment when docker-compose runs
185+
echo "✓ docker-compose.yml has been updated with workspace folder and proxy settings."
186+
else
187+
echo "⚠ Warning: docker-compose.yml not found, skipping Docker Compose configuration."
188+
fi
189+
}
190+
191+
# Main execution
192+
main() {
193+
validate_repository
194+
195+
if [ "$REPO_TYPE" = "DMT" ]; then
196+
dmt_operations
197+
fi
198+
}
199+
200+
# Run main function
201+
main

0 commit comments

Comments
 (0)