func()

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)

}