Skip to content

Commit

Permalink
adding url source type
Browse files Browse the repository at this point in the history
  • Loading branch information
Skarlso committed Jul 28, 2023
1 parent 986bb5c commit 943a512
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 32 deletions.
49 changes: 45 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,59 @@ Welcome to CRD bootstrapper. The name explains what this controller does. It kee

Simple as that. There are three types of bootstrap options (the third is underway).

- URL (soon)
- URL
- ConfigMap
- GitHub release page

Let's look at each of them.

## URL

(soon)
There are two ways to fetch CRDs from a URL.

In this CRD a simple URL can be used with a digest as version. It will fetch the content on every interval, calculate a
digest, and if it's different, apply it.
First, by defining a Digest. If a digest is defined together with a URL the operator will _only_ apply the content that
corresponds to the digest.

For example:

```yaml
apiVersion: delivery.crd-bootstrap/v1alpha1
kind: Bootstrap
metadata:
name: bootstrap-sample
namespace: crd-bootstrap-system
spec:
interval: 10s
source:
url:
url: https://raw.githubusercontent.com/krok-o/operator/main/config/crd/bases/delivery.krok.app_krokevents.yaml
version:
digest: 7162957068d512154ed353d31b9a0a5a9ff148b4611bd85ba704467a4fcd101a
```
This object will only apply this CRD when the digest matches with the fetched content. The digest is a sum256 digest.
You should be able to produce it by running:
```
sha256sum < krok_event_crd.yaml
```

The second options is to omit this digest. In which case it will keep applying the CRD if there is a new "version"
available. This means, every interval it will download the content and create a digest from it. If that digest does not
match with the last applied digest, it will apply the content.

```yaml
apiVersion: delivery.crd-bootstrap/v1alpha1
kind: Bootstrap
metadata:
name: bootstrap-sample
namespace: crd-bootstrap-system
spec:
interval: 10s
source:
url:
url: https://raw.githubusercontent.com/krok-o/operator/main/config/crd/bases/delivery.krok.app_krokevents.yaml
```
## ConfigMap
Expand Down
13 changes: 7 additions & 6 deletions api/v1alpha1/bootstrap_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ type URL struct {
// URL defines the URL from which do download the YAML content from.
// +required
URL string `json:"url"`
// Digest must be provided to check for new instances of the raw YAML content.
// +required
Digest string `json:"digest"`
// SecretRef contains a pointed to a Token in case the URL isn't public.
// +optional
SecretRef *v1.LocalObjectReference `json:"secretRef,omitempty"`
}

// Source defines options from where to fetch CRD content.
Expand Down Expand Up @@ -108,9 +108,10 @@ type BootstrapSpec struct {
Source *Source `json:"source"`

// Version defines constraints for sources to check against. It can either be a semver constraint or a Digest
// in case of URLs.
// +required
Version Version `json:"version"`
// in case of URLs. If a digest is defined, URL sync will ONLY SYNC that digest. If the digest
// differs, it will NOT install it.
// +optional
Version Version `json:"version,omitempty"`

// Template defines a set of values to test a new version against.
// +optional
Expand Down
7 changes: 6 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 7 additions & 9 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,20 @@ import (
"flag"
"os"

_ "k8s.io/client-go/plugin/pkg/client/auth"

deliveryv1alpha1 "github.com/Skarlso/crd-bootstrap/api/v1alpha1"
"github.com/Skarlso/crd-bootstrap/internal/controller"
"github.com/Skarlso/crd-bootstrap/pkg/source/configmap"
"github.com/Skarlso/crd-bootstrap/pkg/source/github"
"github.com/Skarlso/crd-bootstrap/pkg/source/url"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"

"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

deliveryv1alpha1 "github.com/Skarlso/crd-bootstrap/api/v1alpha1"
"github.com/Skarlso/crd-bootstrap/internal/controller"
//+kubebuilder:scaffold:imports
)

Expand Down Expand Up @@ -83,7 +80,8 @@ func main() {
os.Exit(1)
}

githubProvider := github.NewSource(mgr.GetClient(), nil)
urlProvider := url.NewSource(mgr.GetClient(), nil)
githubProvider := github.NewSource(mgr.GetClient(), urlProvider)
configMapProvider := configmap.NewSource(mgr.GetClient(), githubProvider)
if err = (&controller.BootstrapReconciler{
Client: mgr.GetClient(),
Expand Down
18 changes: 12 additions & 6 deletions config/crd/bases/delivery.crd-bootstrap_bootstraps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,21 @@ spec:
url:
description: URL type source.
properties:
digest:
description: Digest must be provided to check for new instances
of the raw YAML content.
type: string
secretRef:
description: SecretRef contains a pointed to a Token in case
the URL isn't public.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
url:
description: URL defines the URL from which do download the
YAML content from.
type: string
required:
- digest
- url
type: object
type: object
Expand All @@ -125,6 +130,8 @@ spec:
version:
description: Version defines constraints for sources to check against.
It can either be a semver constraint or a Digest in case of URLs.
If a digest is defined, URL sync will ONLY SYNC that digest. If
the digest differs, it will NOT install it.
properties:
digest:
description: Digest defines the digest of the content pointing
Expand All @@ -136,7 +143,6 @@ spec:
type: object
required:
- source
- version
type: object
status:
description: BootstrapStatus defines the observed state of Bootstrap.
Expand Down
10 changes: 10 additions & 0 deletions config/samples/delivery_v1alpha1_bootstrap_url.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: delivery.crd-bootstrap/v1alpha1
kind: Bootstrap
metadata:
name: bootstrap-sample
namespace: crd-bootstrap-system
spec:
interval: 10s
source:
url:
url: https://raw.githubusercontent.com/krok-o/operator/main/config/crd/bases/delivery.krok.app_krokevents.yaml
3 changes: 3 additions & 0 deletions docs/release_notes/v0.2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Release v0.2.0

This release introduces the URL source type.
16 changes: 10 additions & 6 deletions internal/controller/bootstrap_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ func (r *BootstrapReconciler) SetupWithManager(mgr ctrl.Manager) error {
func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, err error) {
logger := log.FromContext(ctx)

logger.Info("applying request")

obj := &v1alpha1.Bootstrap{}
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
if apierrors.IsNotFound(err) {
Expand All @@ -100,6 +98,8 @@ func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
return ctrl.Result{}, nil
}

logger.Info("starting reconcile loop")

patchHelper := patch.NewSerialPatcher(obj, r.Client)

// AddFinalizer if not present already.
Expand All @@ -120,7 +120,7 @@ func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}
}()

update, version, err := r.SourceProvider.HasUpdate(ctx, obj)
update, revision, err := r.SourceProvider.HasUpdate(ctx, obj)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to check version: %w", err)
}
Expand All @@ -132,7 +132,9 @@ func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
}

obj.Status.LastAttemptedRevision = version
logger.Info("fetching CRD content")

obj.Status.LastAttemptedRevision = revision

temp, err := os.MkdirTemp("", "crd")
if err != nil {
Expand All @@ -144,7 +146,7 @@ func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

// should probably return a file system / single YAML. Because they can be super large, it's
// not vise to store it in memory as a buffer.
location, err := r.SourceProvider.FetchCRD(ctx, temp, obj, version)
location, err := r.SourceProvider.FetchCRD(ctx, temp, obj, revision)
if err != nil {
err := fmt.Errorf("failed to fetch source: %w", err)
conditions.MarkFalse(obj, meta.ReadyCondition, "CRDFetchFailed", err.Error())
Expand Down Expand Up @@ -214,10 +216,12 @@ func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}

obj.Status.LastAppliedCRDNames = applied
obj.Status.LastAppliedRevision = version
obj.Status.LastAppliedRevision = revision

conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, "Successfully applied crd(s)")

logger.Info("all done")

return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
}

Expand Down
Loading

0 comments on commit 943a512

Please sign in to comment.