1+ #! /bin/bash
2+ set -e
3+
4+ # Enable debug mode if requested
5+ if [[ " ${INPUT_DEBUG} " == " true" ]]; then
6+ set -x
7+ export HELM_DEBUG=" true"
8+ fi
9+
10+ # Color codes for output
11+ RED=' \033[0;31m'
12+ GREEN=' \033[0;32m'
13+ YELLOW=' \033[1;33m'
14+ BLUE=' \033[0;34m'
15+ NC=' \033[0m' # No Color
16+
17+ # Logging functions
18+ log_info () {
19+ echo -e " ${BLUE} [INFO]${NC} $1 "
20+ }
21+
22+ log_warn () {
23+ echo -e " ${YELLOW} [WARN]${NC} $1 "
24+ }
25+
26+ log_error () {
27+ echo -e " ${RED} [ERROR]${NC} $1 "
28+ }
29+
30+ log_success () {
31+ echo -e " ${GREEN} [SUCCESS]${NC} $1 "
32+ }
33+
34+ # Set default values from inputs or environment variables
35+ CLUSTER_NAME=" ${INPUT_CLUSTER_NAME:- ${CLUSTER_NAME} } "
36+ REGION_CODE=" ${INPUT_REGION:- ${REGION_CODE} } "
37+ PRIVATE_CLUSTER=" ${INPUT_PRIVATE_CLUSTER:- false} "
38+ HELM_REGISTRY_URL=" ${INPUT_HELM_REGISTRY_URL} "
39+ HELM_REGISTRY_USERNAME=" ${INPUT_HELM_REGISTRY_USERNAME} "
40+ HELM_REGISTRY_PASSWORD=" ${INPUT_HELM_REGISTRY_PASSWORD} "
41+ HELM_REGISTRY_INSECURE=" ${INPUT_HELM_REGISTRY_INSECURE:- false} "
42+ KUBECTL_VERSION=" ${INPUT_KUBECTL_VERSION:- 1.28.4} "
43+ HELM_VERSION=" ${INPUT_HELM_VERSION:- 3.13.3} "
44+ TIMEOUT=" ${INPUT_TIMEOUT:- 300} "
45+ KUBECONFIG_PATH=" ${INPUT_KUBECONFIG_PATH:-/ opt/ kubernetes/ config} "
46+ DRY_RUN=" ${INPUT_DRY_RUN:- false} "
47+
48+ log_info " Starting EKS Helm Client v2.0.0"
49+ log_info " Cluster: ${CLUSTER_NAME} , Region: ${REGION_CODE} , Private: ${PRIVATE_CLUSTER} "
50+
51+ # Validate required parameters
52+ if [[ -z " ${CLUSTER_NAME} " ]]; then
53+ log_error " CLUSTER_NAME is required"
54+ log_error " Please provide either:"
55+ log_error " - Input parameter: cluster-name"
56+ log_error " - Environment variable: CLUSTER_NAME"
57+ exit 1
58+ fi
59+
60+ if [[ -z " ${REGION_CODE} " ]]; then
61+ log_error " REGION_CODE is required"
62+ log_error " Please provide either:"
63+ log_error " - Input parameter: region"
64+ log_error " - Environment variable: REGION_CODE"
65+ exit 1
66+ fi
67+
68+ # Install specific versions if different from default
69+ if [[ " ${KUBECTL_VERSION} " != " 1.28.4" ]]; then
70+ log_info " Installing kubectl version ${KUBECTL_VERSION} "
71+ curl -s -L " https://dl.k8s.io/release/v${KUBECTL_VERSION} /bin/linux/amd64/kubectl" -o /usr/local/bin/kubectl
72+ chmod +x /usr/local/bin/kubectl
73+ fi
74+
75+ if [[ " ${HELM_VERSION} " != " 3.13.3" ]]; then
76+ log_info " Installing Helm version ${HELM_VERSION} "
77+ curl -s -L " https://get.helm.sh/helm-v${HELM_VERSION} -linux-amd64.tar.gz" | tar -xzO linux-amd64/helm > /usr/local/bin/helm
78+ chmod +x /usr/local/bin/helm
79+ fi
80+
81+ # Set custom kubeconfig path
82+ export KUBECONFIG=" ${KUBECONFIG_PATH} "
83+
84+ # Function to test network connectivity
85+ test_connectivity () {
86+ local endpoint=$1
87+ local port=${2:- 443}
88+ log_info " Testing connectivity to ${endpoint} :${port} "
89+
90+ if timeout 10 nc -z " ${endpoint} " " ${port} " 2> /dev/null; then
91+ log_success " Connectivity test passed for ${endpoint} :${port} "
92+ return 0
93+ else
94+ log_warn " Connectivity test failed for ${endpoint} :${port} "
95+ return 1
96+ fi
97+ }
98+
99+ # Function to configure EKS cluster access
100+ configure_eks_access () {
101+ log_info " Configuring EKS cluster access"
102+
103+ # Get cluster information
104+ log_info " Retrieving cluster information from AWS EKS API"
105+
106+ CA_CERT=$( aws eks describe-cluster --region " ${REGION_CODE} " --name " ${CLUSTER_NAME} " --query " cluster.certificateAuthority.data" --output text 2> /dev/null)
107+ if [[ $? -ne 0 || -z " ${CA_CERT} " ]]; then
108+ log_error " Failed to retrieve certificate authority data for cluster ${CLUSTER_NAME} "
109+ log_error " Please verify:"
110+ log_error " - AWS credentials are configured correctly"
111+ log_error " - Cluster name '${CLUSTER_NAME} ' exists in region '${REGION_CODE} '"
112+ log_error " - IAM permissions include eks:DescribeCluster"
113+ exit 1
114+ fi
115+
116+ ENDPOINT_URL=$( aws eks describe-cluster --region " ${REGION_CODE} " --name " ${CLUSTER_NAME} " --query " cluster.endpoint" --output text 2> /dev/null)
117+ if [[ $? -ne 0 || -z " ${ENDPOINT_URL} " ]]; then
118+ log_error " Failed to retrieve endpoint URL for cluster ${CLUSTER_NAME} "
119+ exit 1
120+ fi
121+
122+ log_info " Cluster endpoint: ${ENDPOINT_URL} "
123+
124+ # Extract hostname from endpoint for connectivity test
125+ ENDPOINT_HOST=$( echo " ${ENDPOINT_URL} " | sed ' s|https://||' | sed ' s|/.*||' )
126+
127+ # Test connectivity to EKS API endpoint
128+ if [[ " ${PRIVATE_CLUSTER} " == " true" ]]; then
129+ log_warn " Private cluster detected. Ensure runner has network access to EKS API endpoint"
130+ if ! test_connectivity " ${ENDPOINT_HOST} " 443; then
131+ log_error " Cannot reach private EKS cluster endpoint. Ensure:"
132+ log_error " 1. GitHub runner is in the same VPC or has VPC connectivity"
133+ log_error " 2. Security groups allow access to EKS API endpoint"
134+ log_error " 3. VPC endpoints are configured if needed"
135+ exit 1
136+ fi
137+ else
138+ test_connectivity " ${ENDPOINT_HOST} " 443 || log_warn " Public endpoint connectivity test failed, but continuing..."
139+ fi
140+
141+ # Generate kubeconfig
142+ log_info " Generating kubeconfig file"
143+ export CA_CERT ENDPOINT_URL REGION_CODE CLUSTER_NAME
144+
145+ if [[ " ${PRIVATE_CLUSTER} " == " true" && -f " /private-config.template" ]]; then
146+ cat /private-config.template | envsubst > " ${KUBECONFIG} "
147+ else
148+ cat /config.template | envsubst > " ${KUBECONFIG} "
149+ fi
150+
151+ # Verify kubeconfig works
152+ log_info " Testing cluster connectivity"
153+ if timeout " ${TIMEOUT} " kubectl cluster-info --request-timeout=30s > /dev/null 2>&1 ; then
154+ log_success " Successfully connected to EKS cluster"
155+ else
156+ log_error " Failed to connect to EKS cluster. Check your AWS credentials and cluster access"
157+ log_error " Try running with debug: true for more detailed logs"
158+ exit 1
159+ fi
160+ }
161+
162+ # Function to configure private Helm registry
163+ configure_helm_registry () {
164+ if [[ -n " ${HELM_REGISTRY_URL} " ]]; then
165+ log_info " Configuring private Helm registry: ${HELM_REGISTRY_URL} "
166+
167+ # Prepare helm repo add command
168+ HELM_REPO_CMD=" helm repo add private-registry '${HELM_REGISTRY_URL} '"
169+
170+ if [[ -n " ${HELM_REGISTRY_USERNAME} " && -n " ${HELM_REGISTRY_PASSWORD} " ]]; then
171+ HELM_REPO_CMD=" ${HELM_REPO_CMD} --username '${HELM_REGISTRY_USERNAME} ' --password '${HELM_REGISTRY_PASSWORD} '"
172+ fi
173+
174+ if [[ " ${HELM_REGISTRY_INSECURE} " == " true" ]]; then
175+ HELM_REPO_CMD=" ${HELM_REPO_CMD} --insecure-skip-tls-verify"
176+ log_warn " Using insecure connection to Helm registry"
177+ fi
178+
179+ # Add private registry
180+ if eval " ${HELM_REPO_CMD} " ; then
181+ log_success " Private Helm registry added successfully"
182+ helm repo update
183+ else
184+ log_error " Failed to add private Helm registry"
185+ log_error " Please verify:"
186+ log_error " - Registry URL is correct: ${HELM_REGISTRY_URL} "
187+ log_error " - Credentials are valid"
188+ log_error " - Network connectivity to registry"
189+ exit 1
190+ fi
191+ fi
192+ }
193+
194+ # Function to verify Helm installation
195+ verify_helm () {
196+ log_info " Verifying Helm installation"
197+ if helm version --short; then
198+ log_success " Helm is working correctly"
199+ else
200+ log_error " Helm verification failed"
201+ exit 1
202+ fi
203+ }
204+
205+ # Function to display tool versions
206+ display_versions () {
207+ log_info " Tool versions:"
208+ echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
209+ kubectl version --client --short 2> /dev/null || echo " kubectl: version check failed"
210+ helm version --short 2> /dev/null || echo " Helm: version check failed"
211+ aws --version 2> /dev/null || echo " AWS CLI: version check failed"
212+ echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
213+ }
214+
215+ # Function to validate environment
216+ validate_environment () {
217+ log_info " Validating environment"
218+
219+ # Check required commands
220+ local required_commands=(" kubectl" " helm" " aws" " envsubst" )
221+ for cmd in " ${required_commands[@]} " ; do
222+ if ! command -v " $cmd " > /dev/null 2>&1 ; then
223+ log_error " Required command not found: $cmd "
224+ exit 1
225+ fi
226+ done
227+
228+ # Check AWS credentials
229+ if ! aws sts get-caller-identity > /dev/null 2>&1 ; then
230+ log_error " AWS credentials not configured or invalid"
231+ log_error " Please ensure AWS credentials are properly set up"
232+ exit 1
233+ fi
234+
235+ log_success " Environment validation passed"
236+ }
237+
238+ # Function for cleanup on exit
239+ cleanup () {
240+ log_info " Cleaning up sensitive data..."
241+
242+ # Remove kubeconfig
243+ if [[ -f " ${KUBECONFIG} " ]]; then
244+ rm -f " ${KUBECONFIG} " 2> /dev/null || true
245+ fi
246+
247+ # Clear sensitive environment variables
248+ unset HELM_REGISTRY_PASSWORD 2> /dev/null || true
249+ unset AWS_SECRET_ACCESS_KEY 2> /dev/null || true
250+ unset AWS_SESSION_TOKEN 2> /dev/null || true
251+
252+ # Clear Helm repository credentials
253+ if [[ -f " /opt/helm/repositories.yaml" ]]; then
254+ rm -f " /opt/helm/repositories.yaml" 2> /dev/null || true
255+ fi
256+
257+ log_info " Cleanup completed"
258+ }
259+
260+ # Function for enhanced error handling
261+ handle_error () {
262+ local exit_code=$?
263+ local line_number=$1
264+
265+ log_error " Script failed at line ${line_number} with exit code ${exit_code} "
266+
267+ if [[ " ${INPUT_DEBUG} " == " true" ]]; then
268+ log_info " Debug information:"
269+ echo " - Cluster: ${CLUSTER_NAME} "
270+ echo " - Region: ${REGION_CODE} "
271+ echo " - Private cluster: ${PRIVATE_CLUSTER} "
272+ echo " - Helm registry: ${HELM_REGISTRY_URL:- " none" } "
273+ echo " - kubectl version: ${KUBECTL_VERSION} "
274+ echo " - Helm version: ${HELM_VERSION} "
275+ fi
276+
277+ cleanup
278+ exit $exit_code
279+ }
280+
281+ # Set up error handling
282+ trap ' handle_error ${LINENO}' ERR
283+ trap cleanup EXIT
284+
285+ # Main execution
286+ main () {
287+ log_info " === EKS Helm Client v2.0.0 ==="
288+
289+ # Display versions if debug enabled
290+ if [[ " ${INPUT_DEBUG} " == " true" ]]; then
291+ display_versions
292+ fi
293+
294+ # Validate environment
295+ validate_environment
296+
297+ # Configure EKS access
298+ configure_eks_access
299+
300+ # Configure private Helm registry if provided
301+ configure_helm_registry
302+
303+ # Verify Helm
304+ verify_helm
305+
306+ # Execute user commands
307+ log_info " Executing user commands"
308+
309+ if [[ " ${DRY_RUN} " == " true" ]]; then
310+ log_warn " DRY RUN MODE: Commands will be displayed but not executed"
311+ echo " Commands to execute:"
312+ echo " ${@ } "
313+ log_success " Dry run completed successfully"
314+ else
315+ # Set timeout for kubectl operations
316+ export KUBECTL_TIMEOUT=" ${TIMEOUT} s"
317+
318+ # Execute the provided arguments
319+ log_info " Running: $* "
320+ timeout " ${TIMEOUT} " bash -c " $* "
321+
322+ if [[ $? -eq 0 ]]; then
323+ log_success " Commands executed successfully"
324+ else
325+ log_error " Command execution failed"
326+ exit 1
327+ fi
328+ fi
329+
330+ log_success " EKS Helm Client execution completed"
331+ }
332+
333+ # Validate that we have arguments to execute
334+ if [[ $# -eq 0 ]]; then
335+ log_error " No commands provided to execute"
336+ log_error " Please provide commands in the 'args' parameter"
337+ exit 1
338+ fi
339+
340+ # Run main function with all arguments
341+ main " $@ "
0 commit comments