Use Source interface instead of Git concrete type

- use TypedLocalObjectReference instead of LocalObjectReference for referencing a source
- update docs for GitRepository kind
- update source API to 0.0.1-alpha.1
This commit is contained in:
stefanprodan 2020-04-16 18:00:44 +03:00
parent 21309c3bf5
commit c564555eb0
9 changed files with 81 additions and 46 deletions

View File

@ -6,15 +6,15 @@ The kustomize-controller is a Kubernetes operator that applies kustomizations in
Features:
* watches for `Kustomization` objects
* fetches artifacts produced by `GitRepository` objects
* watches `GitRepository` objects for revision changes
* fetches artifacts produced by [source-controller](https://github.com/fluxcd/source-controller) from `Source` objects
* watches `Source` objects for revision changes
* builds the kustomization using the latest fetched artifact
* applies the resulting Kubernetes manifests on the cluster
* prunes the Kubernetes objects removed from git based on a label selector
* prunes the Kubernetes objects removed from source based on a label selector
## Kustomization API
A kustomization object defines the source of Kubernetes manifests by referencing a Git repository
A kustomization object defines the source of Kubernetes manifests by referencing a source
(managed by [source-controller](https://github.com/fluxcd/source-controller)),
the path to the kustomization file,
and a label selector used for garbage collection of resources removed from the Git source.
@ -34,9 +34,9 @@ type KustomizationSpec struct {
// +optional
Prune string `json:"prune,omitempty"`
// Reference of the Git repository where the kustomization source is.
// Reference of the source where the kustomization file is.
// +required
GitRepositoryRef corev1.LocalObjectReference `json:"gitRepositoryRef"`
SourceRef corev1.TypedLocalObjectReference `json:"sourceRef"`
// The interval at which to apply the kustomization.
// +required
@ -44,6 +44,9 @@ type KustomizationSpec struct {
}
```
Supported source kinds:
* [GitRepository](https://github.com/fluxcd/source-controller/blob/master/docs/spec/v1alpha1/gitrepositories.md)
## Usage
Build prerequisites:
@ -57,9 +60,8 @@ Build prerequisites:
Install source-controller with:
```bash
git clone https://github.com/fluxcd/source-controller
cd source-controller
make docker-build docker-push dev-deploy IMG=your-docker-hub-username/source-controller:test
kustomize build https://github.com/fluxcd/source-controller//config/default?ref=v0.0.1-alpha.1 \
kubectl apply -f-
```
Install kustomize-controller with:
@ -111,7 +113,8 @@ spec:
interval: 5m
path: "./overlays/dev/"
prune: "env=dev"
gitRepositoryRef:
sourceRef:
kind: GitRepository
name: podinfo
```
@ -190,7 +193,8 @@ spec:
interval: 10m
path: "./overlays/production/"
prune: "env=production"
gitRepositoryRef:
sourceRef:
kind: GitRepository
name: podinfo-releases
```

View File

@ -35,7 +35,7 @@ type KustomizationSpec struct {
// Reference of the Git repository where the kustomization source is.
// +required
GitRepositoryRef corev1.LocalObjectReference `json:"gitRepositoryRef"`
SourceRef corev1.TypedLocalObjectReference `json:"sourceRef"`
// The interval at which to apply the kustomization.
// +required

View File

@ -45,7 +45,7 @@ func (in *Kustomization) DeepCopyInto(out *Kustomization) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
@ -102,7 +102,7 @@ func (in *KustomizationList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KustomizationSpec) DeepCopyInto(out *KustomizationSpec) {
*out = *in
out.GitRepositoryRef = in.GitRepositoryRef
in.SourceRef.DeepCopyInto(&out.SourceRef)
out.Interval = in.Interval
}

View File

@ -46,15 +46,6 @@ spec:
spec:
description: KustomizationSpec defines the desired state of a kustomization.
properties:
gitRepositoryRef:
description: Reference of the Git repository where the kustomization
source is.
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
interval:
description: The interval at which to apply the kustomization.
type: string
@ -66,10 +57,29 @@ spec:
description: Label selector used for prune operations, e.g. env=staging.
pattern: ^.*=.*$
type: string
sourceRef:
description: Reference of the Git repository where the kustomization
source is.
properties:
apiGroup:
description: APIGroup is the group for the resource being referenced.
If APIGroup is not specified, the specified Kind must be in the
core API group. For any other third-party types, APIGroup is required.
type: string
kind:
description: Kind is the type of resource being referenced
type: string
name:
description: Name is the name of resource being referenced
type: string
required:
- kind
- name
type: object
required:
- gitRepositoryRef
- interval
- path
- sourceRef
type: object
status:
description: KustomizationStatus defines the observed state of a kustomization.

View File

@ -6,7 +6,8 @@ spec:
interval: 5m
path: "./overlays/dev/"
prune: "env=dev"
gitRepositoryRef:
sourceRef:
kind: GitRepository
name: podinfo
---
apiVersion: kustomize.fluxcd.io/v1alpha1
@ -17,7 +18,8 @@ spec:
interval: 5m
path: "./overlays/staging/"
prune: "env=staging"
gitRepositoryRef:
sourceRef:
kind: GitRepository
name: podinfo
---
apiVersion: kustomize.fluxcd.io/v1alpha1
@ -28,5 +30,6 @@ spec:
interval: 5m
path: "./overlays/production/"
prune: "env=production"
gitRepositoryRef:
sourceRef:
kind: GitRepository
name: podinfo-releases

View File

@ -63,6 +63,10 @@ func (r *GitRepositoryWatcher) Reconcile(req ctrl.Request) (ctrl.Result, error)
// trigger apply for each kustomization using this Git repository
for _, kustomization := range list.Items {
kustomization.Annotations[kustomizev1.SyncAtAnnotation] = metav1.Now().String()
if kustomization.Spec.SourceRef.APIGroup == nil {
emptyAPIGroup := ""
kustomization.Spec.SourceRef.APIGroup = &emptyAPIGroup
}
if err := r.Update(ctx, &kustomization); err != nil {
log.Error(err, "unable to annotate kustomization", "kustomization", kustomization.GetName())
}
@ -77,7 +81,10 @@ func (r *GitRepositoryWatcher) SetupWithManager(mgr ctrl.Manager) error {
err := mgr.GetFieldIndexer().IndexField(&kustomizev1.Kustomization{}, kustomizev1.SourceIndexKey,
func(rawObj runtime.Object) []string {
k := rawObj.(*kustomizev1.Kustomization)
return []string{k.Spec.GitRepositoryRef.Name}
if k.Spec.SourceRef.Kind == "GitRepository" {
return []string{k.Spec.SourceRef.Name}
}
return nil
},
)
if err != nil {

View File

@ -55,20 +55,31 @@ func (r *KustomizationReconciler) Reconcile(req ctrl.Request) (ctrl.Result, erro
log := r.Log.WithValues(kustomization.Kind, req.NamespacedName)
// get artifact source
var repository sourcev1.GitRepository
repositoryName := types.NamespacedName{
Namespace: kustomization.GetNamespace(),
Name: kustomization.Spec.GitRepositoryRef.Name,
var source sourcev1.Source
// get artifact source from Git repository
if kustomization.Spec.SourceRef.Kind == "GitRepository" {
var repository sourcev1.GitRepository
repositoryName := types.NamespacedName{
Namespace: kustomization.GetNamespace(),
Name: kustomization.Spec.SourceRef.Name,
}
err := r.Client.Get(ctx, repositoryName, &repository)
if err != nil {
log.Error(err, "GitRepository not found", "gitrepository", repositoryName)
return ctrl.Result{Requeue: true}, err
}
source = &repository
}
err := r.Client.Get(ctx, repositoryName, &repository)
if err != nil {
log.Error(err, "GitRepository not found", "gitrepository", repositoryName)
return ctrl.Result{Requeue: true}, err
if source == nil {
err := fmt.Errorf("source `%s` kind '%s' not supported",
kustomization.Spec.SourceRef.Name, kustomization.Spec.SourceRef.Kind)
return ctrl.Result{}, err
}
// try git sync
syncedKustomization, err := r.sync(ctx, *kustomization.DeepCopy(), repository)
syncedKustomization, err := r.sync(ctx, *kustomization.DeepCopy(), source)
if err != nil {
log.Error(err, "Kustomization sync failed")
}
@ -95,14 +106,14 @@ func (r *KustomizationReconciler) SetupWithManager(mgr ctrl.Manager) error {
func (r *KustomizationReconciler) sync(
ctx context.Context,
kustomization kustomizev1.Kustomization,
repository sourcev1.GitRepository) (kustomizev1.Kustomization, error) {
if repository.Status.Artifact == nil || repository.Status.Artifact.URL == "" {
err := fmt.Errorf("artifact not found in %s", repository.GetName())
source sourcev1.Source) (kustomizev1.Kustomization, error) {
if source.GetArtifact() == nil || source.GetArtifact().URL == "" {
err := fmt.Errorf("artifact not found in %s", kustomization.Spec.SourceRef.Name)
return kustomizev1.KustomizationNotReady(kustomization, kustomizev1.ArtifactFailedReason, err.Error()), err
}
// create tmp dir
tmpDir, err := ioutil.TempDir("", repository.Name)
tmpDir, err := ioutil.TempDir("", kustomization.Name)
if err != nil {
err = fmt.Errorf("tmp dir error: %w", err)
return kustomizev1.KustomizationNotReady(kustomization, sourcev1.StorageOperationFailedReason, err.Error()), err
@ -110,7 +121,7 @@ func (r *KustomizationReconciler) sync(
defer os.RemoveAll(tmpDir)
// download artifact and extract files
url := repository.Status.Artifact.URL
url := source.GetArtifact().URL
cmd := fmt.Sprintf("cd %s && curl -sL %s | tar -xz --strip-components=1 -C .", tmpDir, url)
command := exec.CommandContext(ctx, "/bin/sh", "-c", cmd)
output, err := command.CombinedOutput()

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/fluxcd/kustomize-controller
go 1.13
require (
github.com/fluxcd/source-controller v0.0.0-20200414154724-1e3bc471d5a8
github.com/fluxcd/source-controller v0.0.1-alpha.1
github.com/go-logr/logr v0.1.0
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.8.1

4
go.sum
View File

@ -118,8 +118,8 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fluxcd/source-controller v0.0.0-20200414154724-1e3bc471d5a8 h1:5c5rSkmLKf/7N9Ec7F/JqM8BWCijIhz7MtQ8l0htSmI=
github.com/fluxcd/source-controller v0.0.0-20200414154724-1e3bc471d5a8/go.mod h1:11wGvvFvaae1wW4ZyZfanCUfFj8qcowW2Z8hx//Q8To=
github.com/fluxcd/source-controller v0.0.1-alpha.1 h1:UgQ9xnTZdhJN2UMrOfxa6QUan/7ckScpInvy6C24mqQ=
github.com/fluxcd/source-controller v0.0.1-alpha.1/go.mod h1:11wGvvFvaae1wW4ZyZfanCUfFj8qcowW2Z8hx//Q8To=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=