<commit_before>/*
Copyright 2019 The Jetstack cert-manager contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package acmeorders

import (
	"bytes"
	"context"
	"encoding/pem"
	"fmt"
	"reflect"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
	"k8s.io/apimachinery/pkg/util/sets"

	"github.com/golang/glog"
	"github.com/jetstack/cert-manager/pkg/acme"
	acmecl "github.com/jetstack/cert-manager/pkg/acme/client"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
	acmeapi "github.com/jetstack/cert-manager/third_party/crypto/acme"
)

var (
	orderGvk = cmapi.SchemeGroupVersion.WithKind("Order")
)

// Sync will process this ACME Order.
// It is the core control function for ACME Orders, and handles:
// - creating orders
// - deciding/validated configured challenge mechanisms
// - create a Challenge resource in order to fulfill required validations
// - waiting for Challenge resources to enter the 'ready' state
func (c *Controller) Sync(ctx context.Context, o *cmapi.Order) (err error) {
	oldOrder := o
	o = o.DeepCopy()

	defer func() {
		// TODO: replace with more efficient comparison
		if reflect.DeepEqual(oldOrder.Status, o.Status) {
			return
		}
		_, updateErr := c.CMClient.CertmanagerV1alpha1().Orders(o.Namespace).Update(o)
		if err != nil {
			err = utilerrors.NewAggregate([]error{err, updateErr})
		}
	}()

	genericIssuer, err := c.helper.GetGenericIssuer(o.Spec.IssuerRef, o.Namespace)
	if err != nil {
		return fmt.Errorf("error reading (cluster)issuer %q: %v", o.Spec.IssuerRef.Name, err)
	}

	cl, err := c.acmeHelper.ClientForIssuer(genericIssuer)
	if err != nil {
		return err
	}

	if o.Status.URL == "" {
		err := c.createOrder(ctx, cl, genericIssuer, o)

		if err != nil {
			// If we get a 4xx error, we mark the Order as 'error'.
			// 4xx error codes include rate limit errors (429).
			// This will cause the Certificate controller to retry the Order
			// after the regular back-off algorithm has been applied.
			acmeErr, ok := err.(*acmeapi.Error)
			if ok && acmeErr.StatusCode >= 400 && acmeErr.StatusCode < 500 {
				c.setOrderState(&o.Status, cmapi.Errored)
				o.Status.Reason = fmt.Sprintf("Failed to create order: %v", err)
				return err
			}

			return err
		}

		// Return here and allow the updating of the Status field to trigger
		// a resync.
		// This ensures we have observed the `status.url` field being set, preventing
		// us accidentally creating duplicate orders with the ACME server.
		return nil
	}

	// Handle an edge case where the Order has entered a 'valid' state but the
	// actual Certificate resource has not been set on the Order.
	// This shouldn't ever really happen, but can occasionally occur if
	// cert-manager has failed to persist the Certificate and/or status field
	// for whatever reason.
	if o.Status.State == acmeapi.StatusValid && o.Status.Certificate == nil {
		acmeOrder, err := cl.GetOrder(ctx, o.Status.URL)
		if err != nil {
			// TODO: mark the order as 'errored' if this is a 404 or similar
			return err
		}

		certs, err := cl.GetCertificate(ctx, acmeOrder.CertificateURL)
		if err != nil {
			// TODO: mark the order as 'errored' if this is a 404 or similar
			return err
		}

		err = c.storeCertificateOnStatus(o, certs)
		if err != nil {
			return err
		}

		return nil
	}

	// If an order is in a final state, we bail out early as there is nothing
	// left for us to do here.
	// TODO: we should find a way to periodically update the state of the resource
	// to reflect the current/actual state in the ACME server.<commit_msg>Update order status if state changes will retrieving an existing certificate<commit_after>/*
Copyright 2019 The Jetstack cert-manager contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package acmeorders

import (
	"bytes"
	"context"
	"encoding/pem"
	"fmt"
	"reflect"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
	"k8s.io/apimachinery/pkg/util/sets"

	"github.com/golang/glog"
	"github.com/jetstack/cert-manager/pkg/acme"
	acmecl "github.com/jetstack/cert-manager/pkg/acme/client"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
	acmeapi "github.com/jetstack/cert-manager/third_party/crypto/acme"
)

var (
	orderGvk = cmapi.SchemeGroupVersion.WithKind("Order")
)

// Sync will process this ACME Order.
// It is the core control function for ACME Orders, and handles:
// - creating orders
// - deciding/validated configured challenge mechanisms
// - create a Challenge resource in order to fulfill required validations
// - waiting for Challenge resources to enter the 'ready' state
func (c *Controller) Sync(ctx context.Context, o *cmapi.Order) (err error) {
	oldOrder := o
	o = o.DeepCopy()

	defer func() {
		// TODO: replace with more efficient comparison
		if reflect.DeepEqual(oldOrder.Status, o.Status) {
			return
		}
		_, updateErr := c.CMClient.CertmanagerV1alpha1().Orders(o.Namespace).Update(o)
		if err != nil {
			err = utilerrors.NewAggregate([]error{err, updateErr})
		}
	}()

	genericIssuer, err := c.helper.GetGenericIssuer(o.Spec.IssuerRef, o.Namespace)
	if err != nil {
		return fmt.Errorf("error reading (cluster)issuer %q: %v", o.Spec.IssuerRef.Name, err)
	}

	cl, err := c.acmeHelper.ClientForIssuer(genericIssuer)
	if err != nil {
		return err
	}

	if o.Status.URL == "" {
		err := c.createOrder(ctx, cl, genericIssuer, o)

		if err != nil {
			// If we get a 4xx error, we mark the Order as 'error'.
			// 4xx error codes include rate limit errors (429).
			// This will cause the Certificate controller to retry the Order
			// after the regular back-off algorithm has been applied.
			acmeErr, ok := err.(*acmeapi.Error)
			if ok && acmeErr.StatusCode >= 400 && acmeErr.StatusCode < 500 {
				c.setOrderState(&o.Status, cmapi.Errored)
				o.Status.Reason = fmt.Sprintf("Failed to create order: %v", err)
				return err
			}

			return err
		}

		// Return here and allow the updating of the Status field to trigger
		// a resync.
		// This ensures we have observed the `status.url` field being set, preventing
		// us accidentally creating duplicate orders with the ACME server.
		return nil
	}

	// Handle an edge case where the Order has entered a 'valid' state but the
	// actual Certificate resource has not been set on the Order.
	// This shouldn't ever really happen, but can occasionally occur if
	// cert-manager has failed to persist the Certificate and/or status field
	// for whatever reason.
	if o.Status.State == acmeapi.StatusValid && o.Status.Certificate == nil {
		acmeOrder, err := cl.GetOrder(ctx, o.Status.URL)
		if err != nil {
			// TODO: mark the order as 'errored' if this is a 404 or similar
			return err
		}

		// If the Order state has actually changed and we've not observed it,
		// update the order status and let the change in the resource trigger
		// a resync
		if acmeOrder.Status != acmeapi.StatusValid {
			c.setOrderStatus(&o.Status, acmeOrder)
			return nil
		}

		certs, err := cl.GetCertificate(ctx, acmeOrder.CertificateURL)
		if err != nil {
			// TODO: mark the order as 'errored' if this is a 404 or similar
			return err
		}

		err = c.storeCertificateOnStatus(o, certs)
		if err != nil {
			return err
		}

		return nil
	}

	// If an order is in a final state, we bail out early as there is nothing
	// left for us to do here.
	// TODO: we should find a way to periodically update the state of the resource
	// to reflect the current/actual state in the ACME server.
{'fraction_non_alphanumeric': 0.10293609671848014, 'fraction_numerical': 0.008981001727115717, 'mean_word_length': 3.4935333678220384, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7038080', 'n_tokens_mistral': 2977, 'n_tokens_neox': 2730, 'n_words': 978}