Skip to content

Instantly share code, notes, and snippets.

@niski84
Last active April 23, 2024 23:54
Show Gist options
  • Save niski84/cd68872554c091671b7b53b2f1a2ce06 to your computer and use it in GitHub Desktop.
Save niski84/cd68872554c091671b7b53b2f1a2ce06 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/elasticbeanstalk"
"github.com/aws/aws-sdk-go/service/elbv2"
)
func main() {
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))
envName := "my-elasticbeanstalk-env"
// Get Load Balancer Name
lbName, err := GetLoadBalancerName(sess, envName)
if err != nil {
log.Fatalf("Error fetching load balancer name: %v", err)
}
// Get ALB Details
ruleArn, targetGroupArn, err := GetALBDetails(sess, lbName)
if err != nil {
log.Fatalf("Error fetching ALB details: %v", err)
}
fmt.Printf("Rule ARN: %s\n", ruleArn)
fmt.Printf("Target Group ARN: %s\n", targetGroupArn)
// Redirect traffic to ipchicken.com during maintenance
redirectURL := "ipchicken.com"
if err := RedirectTraffic(sess, ruleArn, redirectURL); err != nil {
log.Fatalf("Error redirecting traffic: %v", err)
}
fmt.Println("Traffic is now redirected to:", redirectURL)
// Include logic or monitoring to determine when to switch back
// Restore original routing
if err := RestoreOriginalTraffic(sess, ruleArn, targetGroupArn); err != nil {
log.Fatalf("Error restoring original traffic: %v", err)
}
fmt.Println("Traffic is now restored to the original site")
}
// GetLoadBalancerName retrieves the name of the Load Balancer associated with a given Elastic Beanstalk environment.
func GetLoadBalancerName(sess *session.Session, envName string) (string, error) {
ebSvc := elasticbeanstalk.New(sess)
input := &elasticbeanstalk.DescribeEnvironmentResourcesInput{
EnvironmentName: aws.String(envName),
}
resp, err := ebSvc.DescribeEnvironmentResources(input)
if err != nil {
return "", err
}
if len(resp.EnvironmentResources.LoadBalancers) == 0 {
return "", fmt.Errorf("no load balancer found for environment %s", envName)
}
return *resp.EnvironmentResources.LoadBalancers[0].Name, nil
}
// GetALBDetails retrieves the rule ARN and target group ARN for the given load balancer name.
func GetALBDetails(sess *session.Session, lbName string) (string, string, error) {
elbSvc := elbv2.New(sess)
// Retrieve load balancer details using its name
lbInput := &elbv2.DescribeLoadBalancersInput{
Names: []*string{aws.String(lbName)},
}
lbOutput, err := elbSvc.DescribeLoadBalancers(lbInput)
if err != nil {
return "", "", err
}
if len(lbOutput.LoadBalancers) == 0 {
return "", "", fmt.Errorf("load balancer %s not found", lbName)
}
lbArn := lbOutput.LoadBalancers[0].LoadBalancerArn
// Retrieve the listener using the Load Balancer ARN
listenerInput := &elbv2.DescribeListenersInput{
LoadBalancerArn: lbArn,
}
listenerOutput, err := elbSvc.DescribeListeners(listenerInput)
if err != nil {
return "", "", err
}
if len(listenerOutput.Listeners) == 0 {
return "", "", fmt.Errorf("no listeners found for load balancer %s", lbName)
}
// Assuming the first listener and the first rule
// For more complex setups, you might need to iterate or filter based on specific conditions
listenerArn := listenerOutput.Listeners[0].ListenerArn
ruleInput := &elbv2.DescribeRulesInput{
ListenerArn: listenerArn,
}
ruleOutput, err := elbSvc.DescribeRules(ruleInput)
if err != nil {
return "", "", err
}
if len(ruleOutput.Rules) == 0 {
return "", "", fmt.Errorf("no rules found for listener %s", *listenerArn)
}
ruleArn := *ruleOutput.Rules[0].RuleArn
var targetGroupArn string
for _, action := range ruleOutput.Rules[0].Actions {
if *action.Type == "forward" {
targetGroupArn = *action.TargetGroupArn
break
}
}
if targetGroupArn == "" {
return "", "", fmt.Errorf("no forwarding actions found in rules for listener %s", *listenerArn)
}
return ruleArn, targetGroupArn, nil
}
// RedirectTraffic sets up an ALB rule to redirect all traffic to a specified URL.
func RedirectTraffic(sess *session.Session, ruleArn string, redirectURL string) error {
svc := elbv2.New(sess)
modifyRuleInput := &elbv2.ModifyRuleInput{
RuleArn: aws.String(ruleArn),
Actions: []*elbv2.Action{
{
Type: aws.String("redirect"),
RedirectConfig: &elbv2.RedirectActionConfig{
Protocol: aws.String("HTTPS"), // Ensure the protocol matches your requirements
Host: aws.String(redirectURL), // No need to specify the entire URL, just the host
Port: aws.String("443"), // Standard HTTPS port
Path: aws.String("/#{path}"),
Query: aws.String("#{query}"),
StatusCode: aws.String("HTTP_302"),
},
},
},
}
_, err := svc.ModifyRule(modifyRuleInput)
return err
}
// RestoreOriginalTraffic restores the original rule to forward traffic to the primary target group.
func RestoreOriginalTraffic(sess *session.Session, ruleArn string, targetGroupArn string) error {
svc := elbv2.New(sess)
modifyRuleInput := &elbv2.ModifyRuleInput{
RuleArn: aws.String(ruleArn),
Actions: []*elbv2.Action{
{
Type: aws.String("forward"),
TargetGroupArn: aws.String(targetGroupArn),
},
},
}
_, err := svc.ModifyRule(modifyRuleInput)
return err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment