diff --git a/cmd/controller/app/BUILD.bazel b/cmd/controller/app/BUILD.bazel index fbd601fe4..d6e3814dd 100644 --- a/cmd/controller/app/BUILD.bazel +++ b/cmd/controller/app/BUILD.bazel @@ -11,6 +11,7 @@ go_library( "//pkg/client/clientset/versioned/scheme:go_default_library", "//pkg/client/informers/externalversions:go_default_library", "//pkg/controller:go_default_library", + "//pkg/controller/certificaterequests/acme:go_default_library", "//pkg/controller/certificaterequests/ca:go_default_library", "//pkg/controller/certificaterequests/selfsigned:go_default_library", "//pkg/controller/certificaterequests/vault:go_default_library", diff --git a/cmd/controller/app/controller.go b/cmd/controller/app/controller.go index c6f8d5d8d..7c14b40ac 100644 --- a/cmd/controller/app/controller.go +++ b/cmd/controller/app/controller.go @@ -42,6 +42,7 @@ import ( intscheme "github.com/jetstack/cert-manager/pkg/client/clientset/versioned/scheme" informers "github.com/jetstack/cert-manager/pkg/client/informers/externalversions" "github.com/jetstack/cert-manager/pkg/controller" + cracmecontroller "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/acme" crcacontroller "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/ca" crselfsignedcontroller "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/selfsigned" crvaultcontroller "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/vault" @@ -80,6 +81,7 @@ func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) { if utilfeature.DefaultFeatureGate.Enabled(feature.CertificateRequestControllers) { opts.EnabledControllers = append(opts.EnabledControllers, []string{ + cracmecontroller.CRControllerName, crcacontroller.CRControllerName, crselfsignedcontroller.CRControllerName, crvaultcontroller.CRControllerName, diff --git a/pkg/controller/certificaterequests/BUILD.bazel b/pkg/controller/certificaterequests/BUILD.bazel index 617abe04e..78117a01e 100644 --- a/pkg/controller/certificaterequests/BUILD.bazel +++ b/pkg/controller/certificaterequests/BUILD.bazel @@ -66,6 +66,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//pkg/controller/certificaterequests/acme:all-srcs", "//pkg/controller/certificaterequests/ca:all-srcs", "//pkg/controller/certificaterequests/fake:all-srcs", "//pkg/controller/certificaterequests/selfsigned:all-srcs", diff --git a/pkg/controller/certificaterequests/acme/BUILD.bazel b/pkg/controller/certificaterequests/acme/BUILD.bazel new file mode 100644 index 000000000..dc303140c --- /dev/null +++ b/pkg/controller/certificaterequests/acme/BUILD.bazel @@ -0,0 +1,56 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["acme.go"], + importpath = "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/acme", + visibility = ["//visibility:public"], + deps = [ + "//pkg/acme:go_default_library", + "//pkg/api/util:go_default_library", + "//pkg/apis/certmanager/v1alpha1:go_default_library", + "//pkg/client/clientset/versioned/typed/certmanager/v1alpha1:go_default_library", + "//pkg/client/listers/certmanager/v1alpha1:go_default_library", + "//pkg/controller:go_default_library", + "//pkg/controller/certificaterequests:go_default_library", + "//pkg/controller/certificaterequests/util:go_default_library", + "//pkg/issuer:go_default_library", + "//pkg/logs:go_default_library", + "//pkg/util/pki:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["acme_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/apis/certmanager:go_default_library", + "//pkg/apis/certmanager/v1alpha1:go_default_library", + "//pkg/client/listers/certmanager/v1alpha1:go_default_library", + "//pkg/controller/certificaterequests/test:go_default_library", + "//pkg/controller/test:go_default_library", + "//pkg/controller/test/fake:go_default_library", + "//test/unit/gen:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/controller/certificaterequests/acme/acme.go b/pkg/controller/certificaterequests/acme/acme.go new file mode 100644 index 000000000..47606464c --- /dev/null +++ b/pkg/controller/certificaterequests/acme/acme.go @@ -0,0 +1,194 @@ +/* +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 acme + +import ( + "context" + "crypto/x509" + "encoding/json" + "fmt" + "hash/fnv" + + k8sErrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/record" + + "github.com/jetstack/cert-manager/pkg/acme" + apiutil "github.com/jetstack/cert-manager/pkg/api/util" + "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1" + cmclientset "github.com/jetstack/cert-manager/pkg/client/clientset/versioned/typed/certmanager/v1alpha1" + cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1alpha1" + controllerpkg "github.com/jetstack/cert-manager/pkg/controller" + "github.com/jetstack/cert-manager/pkg/controller/certificaterequests" + crutil "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/util" + issuerpkg "github.com/jetstack/cert-manager/pkg/issuer" + logf "github.com/jetstack/cert-manager/pkg/logs" + "github.com/jetstack/cert-manager/pkg/util/pki" +) + +const ( + CRControllerName = "certificaterequests-issuer-acme" +) + +type ACME struct { + // used to record Events about resources to the API + recorder record.EventRecorder + issuerOptions controllerpkg.IssuerOptions + + orderLister cmlisters.OrderLister + cmClientV cmclientset.CertmanagerV1alpha1Interface + helper issuerpkg.Helper +} + +func init() { + // create certificate request controller for acme issuer + controllerpkg.Register(CRControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { + acme := NewACME(ctx) + + orderInformer := ctx.SharedInformerFactory.Certmanager().V1alpha1().Orders().Informer() + controller := certificaterequests.New(apiutil.IssuerACME, acme, orderInformer) + + c, err := controllerpkg.New(ctx, CRControllerName, controller) + if err != nil { + return nil, err + } + + return c.Run, nil + }) +} + +func NewACME(ctx *controllerpkg.Context) *ACME { + ctx.CMClient.CertmanagerV1alpha1() + return &ACME{ + recorder: ctx.Recorder, + issuerOptions: ctx.IssuerOptions, + orderLister: ctx.SharedInformerFactory.Certmanager().V1alpha1().Orders().Lister(), + cmClientV: ctx.CMClient.CertmanagerV1alpha1(), + } +} + +func (a *ACME) Sign(ctx context.Context, cr *v1alpha1.CertificateRequest, issuer v1alpha1.GenericIssuer) (*issuerpkg.IssueResponse, error) { + log := logf.FromContext(ctx, "sign") + reporter := crutil.NewReporter(cr, a.recorder) + resourceNamespace := a.issuerOptions.ResourceNamespace(issuer) + + // If we can't decode the CSR PEM we have to hard fail + csr, err := pki.DecodeX509CertificateRequestBytes(cr.Spec.CSRPEM) + if err != nil { + reporter.Failed(err, "ErrorParsingCSR", "Failed to decode CSR in spec") + return nil, nil + } + + // If we fail to build the order we have to hard fail. + expectedOrder, err := buildOrder(cr, csr) + if err != nil { + reporter.Failed(err, "ErrorBuildingOrder", "Failed to build order") + return nil, nil + } + + order, err := a.orderLister.Orders(expectedOrder.Namespace).Get(expectedOrder.Name) + if err != nil { + if k8sErrors.IsNotFound(err) { + // Failing to create the order here is most likely network related. + // We should backoff and keep trying. + order, err = a.cmClientV.Orders(resourceNamespace).Create(expectedOrder) + if err != nil { + reporter.Pending(err, "ErrorCreatingOrder", + fmt.Sprintf("Failed create new order resource %s/%s", resourceNamespace, expectedOrder.Name)) + + return nil, err + } + + } else { + // We are probably in a network error here so we should backoff and retry + reporter.Pending(err, "ErrorGettingOrder", + fmt.Sprintf("Failed to get order resource %s/%s", resourceNamespace, expectedOrder.Name)) + return nil, err + } + } + + // If the acme order has failed then so too does the CertificateRequest meet the same fate. + if acme.IsFailureState(order.Status.State) { + reporter.Failed(fmt.Errorf("order is in failure state %q", order.Status.State), "OrderFailed", + fmt.Sprintf("Failed to resolve order resource %s/%s", resourceNamespace, expectedOrder.Name)) + return nil, nil + } + + // Order valid, return cert. The calling controller will update with ready if it's happy with the cert. + if order.Status.State == v1alpha1.Valid { + log.Info("certificate issued") + + return &issuerpkg.IssueResponse{ + Certificate: order.Status.Certificate, + }, nil + } + + // We update here to just normal pending while we wait for the order to be resolved. + reporter.Pending(fmt.Errorf("order is currently pending: %q", order.Status.State), "OrderPending", + fmt.Sprintf("Waiting on certificate issuance from order %s/%s", resourceNamespace, expectedOrder.Name)) + + log.Info("acme Order resource is not in a valid state, waiting...", "state", order.Status.State) + + return nil, nil +} + +// Build order. If we error here it is a terminating failure. +func buildOrder(cr *v1alpha1.CertificateRequest, csr *x509.CertificateRequest) (*v1alpha1.Order, error) { + spec := v1alpha1.OrderSpec{ + CSR: cr.Spec.CSRPEM, + IssuerRef: cr.Spec.IssuerRef, + CommonName: csr.Subject.CommonName, + DNSNames: csr.DNSNames, + } + hash, err := hashOrder(spec) + if err != nil { + return nil, err + } + + // truncate certificate name so final name will be <= 63 characters. + // hash (uint32) will be at most 10 digits long, and we account for + // the hyphen. + return &v1alpha1.Order{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%.52s-%d", cr.Name, hash), + Namespace: cr.Namespace, + Labels: cr.Labels, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(cr, v1alpha1.SchemeGroupVersion.WithKind(v1alpha1.CertificateRequestKind)), + }, + }, + Spec: spec, + }, nil +} + +func hashOrder(orderSpec v1alpha1.OrderSpec) (uint32, error) { + // create a shallow copy of the OrderSpec so we can overwrite the CSR field + orderSpec.CSR = nil + + orderSpecBytes, err := json.Marshal(orderSpec) + if err != nil { + return 0, err + } + + hashF := fnv.New32() + _, err = hashF.Write(orderSpecBytes) + if err != nil { + return 0, err + } + + return hashF.Sum32(), nil +} diff --git a/pkg/controller/certificaterequests/acme/acme_test.go b/pkg/controller/certificaterequests/acme/acme_test.go new file mode 100644 index 000000000..c45926584 --- /dev/null +++ b/pkg/controller/certificaterequests/acme/acme_test.go @@ -0,0 +1,211 @@ +/* +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 acme + +import ( + "context" + "crypto/x509" + "errors" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + coretesting "k8s.io/client-go/testing" + + "github.com/jetstack/cert-manager/pkg/apis/certmanager" + "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1" + cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1alpha1" + testcr "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/test" + testpkg "github.com/jetstack/cert-manager/pkg/controller/test" + testfake "github.com/jetstack/cert-manager/pkg/controller/test/fake" + "github.com/jetstack/cert-manager/test/unit/gen" +) + +func buildOrderMust(t *testing.T, cr *v1alpha1.CertificateRequest, + csr *x509.CertificateRequest) *v1alpha1.Order { + order, err := buildOrder(cr, csr) + if err != nil { + t.Errorf("failed to build order during testing: %s", err) + t.FailNow() + } + + return order +} + +func TestSign(t *testing.T) { + rsaPK := testcr.GenerateRSAPrivateKey(t) + csr, csrPEM := testcr.GenerateCSR(t, rsaPK) + + testCR := gen.CertificateRequest("test-cr", + gen.SetCertificateRequestCSR(csrPEM), + gen.SetCertificateRequestIsCA(true), + gen.SetCertificateRequestDuration(&metav1.Duration{Duration: time.Hour * 24 * 60}), + gen.SetCertificateRequestIssuer(v1alpha1.ObjectReference{ + Name: "acme-issuer", + Group: certmanager.GroupName, + Kind: "Issuer", + }), + ) + + _, rsaPEMCert := testcr.GenerateSelfSignedCertFromCR(t, testCR, rsaPK, time.Hour*24*60) + testOrder := buildOrderMust(t, testCR, csr) + + tests := map[string]testT{ + "a badly formed CSR should report failure": { + issuer: gen.Issuer("acme-issuer"), + certificateRequest: gen.CertificateRequestFrom(testCR, + gen.SetCertificateRequestCSR([]byte("a bad csr")), + ), + builder: &testpkg.Builder{ + KubeObjects: []runtime.Object{}, + CertManagerObjects: []runtime.Object{}, + ExpectedEvents: []string{ + "Warning ErrorParsingCSR Failed to decode CSR in spec: error decoding certificate request PEM block", + }, + CheckFn: testcr.MustNoResponse, + }, + expectedErr: false, + }, + + //TODO: Think of a creative way to get `buildOrder` to fail :thinking_face: + + "if order doesn't exist then attempt to create one": { + issuer: gen.Issuer("acme-issuer"), + certificateRequest: testCR, + builder: &testpkg.Builder{ + CertManagerObjects: []runtime.Object{}, + ExpectedActions: []testpkg.Action{ + testpkg.NewAction(coretesting.NewCreateAction( + v1alpha1.SchemeGroupVersion.WithResource("orders"), + gen.DefaultTestNamespace, + testOrder, + )), + }, + ExpectedEvents: []string{ + `Normal OrderPending Waiting on certificate issuance from order default-unit-test-ns/test-cr-3958469914: order is currently pending: ""`, + }, + CheckFn: testcr.MustNoResponse, + }, + expectedErr: false, + }, + + "if we fail to get the order resource then we should report pending": { + issuer: gen.Issuer("acme-issuer"), + certificateRequest: testCR, + builder: &testpkg.Builder{ + ExpectedEvents: []string{ + `Normal ErrorGettingOrder Failed to get order resource default-unit-test-ns/test-cr-3958469914: this is a network error`, + }, + CheckFn: testcr.MustNoResponse, + }, + expectedErr: true, + FakeOrderLister: &testfake.FakeOrderLister{ + OrdersFn: func(namespace string) cmlisters.OrderNamespaceLister { + return &testfake.FakeOrderNamespaceLister{ + GetFn: func(name string) (ret *v1alpha1.Order, err error) { + return nil, errors.New("this is a network error") + }, + } + }, + }, + }, + + "if the order resource is in a failed state then we should report failure": { + issuer: gen.Issuer("acme-issuer"), + certificateRequest: testCR, + builder: &testpkg.Builder{ + ExpectedEvents: []string{ + `Warning OrderFailed Failed to resolve order resource default-unit-test-ns/test-cr-3958469914: order is in failure state "invalid"`, + }, + CertManagerObjects: []runtime.Object{gen.OrderFrom(testOrder, + gen.SetOrderState(v1alpha1.Invalid), + )}, + CheckFn: testcr.MustNoResponse, + }, + expectedErr: false, + }, + + "if the order is in a non failure state or valid, then report pending": { + issuer: gen.Issuer("acme-issuer"), + certificateRequest: testCR, + builder: &testpkg.Builder{ + ExpectedEvents: []string{ + `Normal OrderPending Waiting on certificate issuance from order default-unit-test-ns/test-cr-3958469914: order is currently pending: ""`, + }, + CertManagerObjects: []runtime.Object{gen.OrderFrom(testOrder, + gen.SetOrderState(""), + )}, + CheckFn: testcr.MustNoResponse, + }, + expectedErr: false, + }, + + "if the order is in Valid state then return the certificate as response": { + issuer: gen.Issuer("acme-issuer"), + certificateRequest: testCR, + builder: &testpkg.Builder{ + ExpectedEvents: []string{}, + CertManagerObjects: []runtime.Object{gen.OrderFrom(testOrder, + gen.SetOrderState(v1alpha1.Valid), + gen.SetOrderCertificate(rsaPEMCert), + )}, + CheckFn: testcr.NoPrivateKeyFieldsSetCheck(nil), + }, + expectedErr: false, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + runTest(t, test) + }) + } +} + +type testT struct { + builder *testpkg.Builder + certificateRequest *v1alpha1.CertificateRequest + issuer v1alpha1.GenericIssuer + + checkFn func(*testpkg.Builder, ...interface{}) + expectedErr bool + + FakeOrderLister *testfake.FakeOrderLister +} + +func runTest(t *testing.T, test testT) { + test.builder.T = t + test.builder.Start() + defer test.builder.Stop() + + a := NewACME(test.builder.Context) + test.builder.Sync() + + if test.FakeOrderLister != nil { + a.orderLister = test.FakeOrderLister + } + + resp, err := a.Sign(context.Background(), test.certificateRequest, test.issuer) + if err != nil && !test.expectedErr { + t.Errorf("expected to not get an error, but got: %v", err) + } + if err == nil && test.expectedErr { + t.Errorf("expected to get an error but did not get one") + } + test.builder.CheckAndFinish(resp, err) +} diff --git a/pkg/controller/certificaterequests/controller.go b/pkg/controller/certificaterequests/controller.go index 0dd845d3a..ad580b936 100644 --- a/pkg/controller/certificaterequests/controller.go +++ b/pkg/controller/certificaterequests/controller.go @@ -69,6 +69,11 @@ type Controller struct { issuerLister cmlisters.IssuerLister clusterIssuerLister cmlisters.ClusterIssuerLister + // Extra informers that should be watched by this certificate request + // controller instance. These resources can be owned by certificate requests + // that we resolve. + extraInformers []cache.SharedIndexInformer + // Issuer to call sign function issuer Issuer @@ -78,7 +83,7 @@ type Controller struct { reporter *util.Reporter } -func New(issuerType string, issuer Issuer) *Controller { +func New(issuerType string, issuer Issuer, extraInformers ...cache.SharedIndexInformer) *Controller { return &Controller{ issuerType: issuerType, issuer: issuer, @@ -103,10 +108,17 @@ func (c *Controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin // build a list of InformerSynced functions that will be returned by the Register method. // the controller will only begin processing items once all of these informers have synced. - mustSync := []cache.InformerSynced{ + + // Ensure we also catch all extra informers for this certificate controller instance + var extraInformersMustSync []cache.InformerSynced + for _, i := range c.extraInformers { + extraInformersMustSync = append(extraInformersMustSync, i.HasSynced) + } + + mustSync := append([]cache.InformerSynced{ certificateRequestInformer.Informer().HasSynced, issuerInformer.Informer().HasSynced, - } + }, extraInformersMustSync...) // if scoped to a single namespace // if we are running in non-namespaced mode (i.e. --namespace=""), we also @@ -124,6 +136,14 @@ func (c *Controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin // register handler functions certificateRequestInformer.Informer().AddEventHandler(&controllerpkg.QueuingEventHandler{Queue: c.queue}) + issuerInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{WorkFunc: c.handleGenericIssuer}) + + // Ensure we catch extra informers that are owned by certificate requests + for _, i := range c.extraInformers { + i.AddEventHandler(&controllerpkg.BlockingEventHandler{ + WorkFunc: controllerpkg.HandleOwnedResourceNamespacedFunc(c.log, c.queue, certificateRequestGvk, certificateRequestGetter(c.certificateRequestLister)), + }) + } // instantiate metrics interface with default metrics implementation c.metrics = metrics.Default @@ -165,3 +185,9 @@ func (c *Controller) ProcessItem(ctx context.Context, key string) error { ctx = logf.NewContext(ctx, logf.WithResource(log, cr)) return c.Sync(ctx, cr) } + +func certificateRequestGetter(lister cmlisters.CertificateRequestLister) func(namespace, name string) (interface{}, error) { + return func(namespace, name string) (interface{}, error) { + return lister.CertificateRequests(namespace).Get(name) + } +} diff --git a/pkg/controller/certificaterequests/fake/BUILD.bazel b/pkg/controller/certificaterequests/fake/BUILD.bazel index 60908a35d..5ecd38902 100644 --- a/pkg/controller/certificaterequests/fake/BUILD.bazel +++ b/pkg/controller/certificaterequests/fake/BUILD.bazel @@ -7,7 +7,9 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/apis/certmanager/v1alpha1:go_default_library", + "//pkg/controller/test:go_default_library", "//pkg/issuer:go_default_library", + "//pkg/util/pki:go_default_library", ], ) diff --git a/pkg/controller/certificaterequests/sync.go b/pkg/controller/certificaterequests/sync.go index 39b2f299e..e6732526c 100644 --- a/pkg/controller/certificaterequests/sync.go +++ b/pkg/controller/certificaterequests/sync.go @@ -34,6 +34,10 @@ import ( "github.com/jetstack/cert-manager/pkg/util/pki" ) +var ( + certificateRequestGvk = v1alpha1.SchemeGroupVersion.WithKind("CertificateRequest") +) + func (c *Controller) Sync(ctx context.Context, cr *v1alpha1.CertificateRequest) (err error) { c.metrics.IncrementSyncCallCount(ControllerName) diff --git a/pkg/controller/test/BUILD.bazel b/pkg/controller/test/BUILD.bazel index 0ff8b28b0..99618eaa5 100644 --- a/pkg/controller/test/BUILD.bazel +++ b/pkg/controller/test/BUILD.bazel @@ -40,7 +40,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/controller/test/fake:all-srcs", + ], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/pkg/controller/test/fake/BUILD.bazel b/pkg/controller/test/fake/BUILD.bazel new file mode 100644 index 000000000..369caa7ff --- /dev/null +++ b/pkg/controller/test/fake/BUILD.bazel @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["orderlister.go"], + importpath = "github.com/jetstack/cert-manager/pkg/controller/test/fake", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/certmanager/v1alpha1:go_default_library", + "//pkg/client/listers/certmanager/v1alpha1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/controller/test/fake/orderlister.go b/pkg/controller/test/fake/orderlister.go new file mode 100644 index 000000000..8a84e5a66 --- /dev/null +++ b/pkg/controller/test/fake/orderlister.go @@ -0,0 +1,73 @@ +/* +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 fake + +import ( + "k8s.io/apimachinery/pkg/labels" + + "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1" + cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1alpha1" +) + +var _ cmlisters.OrderLister = &FakeOrderLister{} +var _ cmlisters.OrderNamespaceLister = &FakeOrderNamespaceLister{} + +type FakeOrderLister struct { + ListFn func(selector labels.Selector) (ret []*v1alpha1.Order, err error) + OrdersFn func(namespace string) cmlisters.OrderNamespaceLister +} + +type FakeOrderNamespaceLister struct { + ListFn func(selector labels.Selector) (ret []*v1alpha1.Order, err error) + GetFn func(name string) (ret *v1alpha1.Order, err error) +} + +func NewFakeOrderLister() *FakeOrderLister { + return &FakeOrderLister{ + ListFn: func(selector labels.Selector) (ret []*v1alpha1.Order, err error) { + return nil, nil + }, + + OrdersFn: func(namespace string) cmlisters.OrderNamespaceLister { + return nil + }, + } +} + +func NewFakeOrderNamespaceLister() *FakeOrderNamespaceLister { + return &FakeOrderNamespaceLister{ + ListFn: func(selector labels.Selector) (ret []*v1alpha1.Order, err error) { + return nil, nil + }, + GetFn: func(name string) (ret *v1alpha1.Order, err error) { + return nil, nil + }, + } +} + +func (f *FakeOrderLister) List(selector labels.Selector) (ret []*v1alpha1.Order, err error) { + return f.ListFn(selector) +} + +func (f *FakeOrderLister) Orders(namespace string) cmlisters.OrderNamespaceLister { + return f.OrdersFn(namespace) +} + +func (f *FakeOrderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Order, err error) { + return f.ListFn(selector) +} + +func (f *FakeOrderNamespaceLister) Get(name string) (*v1alpha1.Order, error) { + return f.GetFn(name) +}