in pkg/controller/ingress/ingress_controller.go [224:340]
func (r *ReconcileIngress) Reconcile(request reconcile.Request) (reconcile.Result, error) {
// Fetch the Ingress instance
instance := &extensionsv1beta1.Ingress{}
err := r.Get(context.TODO(), request.NamespacedName, instance)
if err != nil {
if errors.IsNotFound(err) {
// Object not found, return. Created objects are automatically garbage collected.
// For additional cleanup logic use finalizers.
return reconcile.Result{}, nil
}
// Error reading the object - requeue the request.
return reconcile.Result{}, err
}
// Ignore other ingress resources
if instance.Annotations[IngressClassAnnotation] != "apigateway" {
return reconcile.Result{}, nil
}
if len(instance.GetObjectMeta().GetName()) > ingressNameLengthLimit {
return reconcile.Result{}, fmt.Errorf("ingress name must be < %d characters", ingressNameLengthLimit)
}
// Delete if timestamp is set
if instance.ObjectMeta.DeletionTimestamp.IsZero() == false {
if finalizers.HasFinalizer(instance, FinalizerCFNStack) {
// r.log.Info("deleting apigateway cloudformation stack", zap.String("stackName", instance.ObjectMeta.Name))
instance, requeue, err := r.delete(instance)
if requeue != nil {
return *requeue, nil
}
if err != nil {
return reconcile.Result{}, err
}
return reconcile.Result{}, r.Update(context.TODO(), instance)
}
return reconcile.Result{}, nil
}
// Check if stack exists
stack, err := cfn.DescribeStack(r.cfnSvc, instance.ObjectMeta.Name)
if err != nil && cfn.IsDoesNotExist(err, instance.ObjectMeta.Name) {
r.log.Info("creating apigateway", zap.String("stackName", instance.ObjectMeta.Name))
instance, err := r.create(instance)
if err != nil {
return reconcile.Result{}, err
}
if err := r.Update(context.TODO(), instance); err != nil {
return reconcile.Result{}, err
}
return reconcile.Result{Requeue: true}, nil
} else if err != nil {
r.log.Error("error describing stack", zap.Error(err))
return reconcile.Result{}, err
}
r.log.Info("Found Stack", zap.String("stackName", instance.ObjectMeta.Name), zap.String("StackStatus", *stack.StackStatus))
if cfn.IsFailed(*stack.StackStatus) {
return reconcile.Result{}, r.Update(context.TODO(), instance)
}
if cfn.IsComplete(*stack.StackStatus) == false {
r.log.Info("Not complete, requeuing", zap.String("status", *stack.StackStatus))
return reconcile.Result{RequeueAfter: 5 * time.Second}, r.Update(context.TODO(), instance)
}
if cfn.IsComplete(*stack.StackStatus) && shouldUpdate(stack, instance) {
r.log.Info("updating apigateway cloudformation stack", zap.String("stackName", instance.ObjectMeta.Name))
if err := r.update(instance); err != nil {
return reconcile.Result{}, err
}
return reconcile.Result{Requeue: true}, nil
}
outputs := cfn.StackOutputMap(stack)
// Deploy API so changes are applied after Update
r.log.Info("creating apigateway deployment", zap.String(cfn.OutputKeyRestApiID, outputs[cfn.OutputKeyRestApiID]), zap.String("stage", getStageName(instance)))
if _, err := r.apigatewaySvc.CreateDeployment(&apigateway.CreateDeploymentInput{
RestApiId: aws.String(outputs[cfn.OutputKeyRestApiID]),
StageName: aws.String(getStageName(instance)),
}); err != nil {
r.log.Error("unable to deploy ApiGateway Rest API", zap.Error(err))
return reconcile.Result{}, err
}
u, err := url.Parse(outputs[cfn.OutputKeyAPIGatewayEndpoint])
if err != nil {
r.log.Error("unable to parse url from stack output", zap.Error(err), zap.String("output", outputs[cfn.OutputKeyAPIGatewayEndpoint]))
return reconcile.Result{}, err
}
err = r.attachTGToASG(instance)
if err != nil {
r.log.Error("unable to verify ASG after create/update", zap.Error(err))
return reconcile.Result{}, err
}
r.log.Info("Stack Create/Update Complete")
instance.Status = extensionsv1beta1.IngressStatus{
LoadBalancer: corev1.LoadBalancerStatus{
Ingress: []corev1.LoadBalancerIngress{
corev1.LoadBalancerIngress{Hostname: u.Host},
},
},
}
return reconcile.Result{}, r.Status().Update(context.TODO(), instance)
}