Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Add support for HelmRelease v1 resources
Browse files Browse the repository at this point in the history
This commit adds support for HelmRelease v1 resources with backwards
compatability for v1beta1 resources, it also reintroduces some of the
removed `integrations/` packages, as those resources have been removed
from the Helm operator.

The v1 resource is prioritized over v1beta1 resources, as Flux is only
aware of the resource kind and not the api version. The prioritization
means that if there are two resources with the same namespace and name,
Flux will only see the v1 resource. The fallback is based on returned
errors from the API, this comes at a cost, as errors during the first
try may actually be relevant.

The version of `github.com/fluxcd/helm-operator` has been pinpointed on
`1.0.0-rc1`.
  • Loading branch information
hiddeco committed Aug 15, 2019
1 parent a46fdeb commit a9f8b0a
Show file tree
Hide file tree
Showing 58 changed files with 3,679 additions and 208 deletions.
20 changes: 13 additions & 7 deletions cluster/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,47 @@ import (
"fmt"
"sync"

hrclient "github.com/fluxcd/helm-operator/pkg/client/clientset/versioned"
"github.com/go-kit/kit/log"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
apiv1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
fhrclient "github.com/fluxcd/helm-operator/pkg/client/clientset/versioned"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
k8sclientdynamic "k8s.io/client-go/dynamic"
k8sclient "k8s.io/client-go/kubernetes"

"github.com/weaveworks/flux/cluster"
kresource "github.com/weaveworks/flux/cluster/kubernetes/resource"
"github.com/weaveworks/flux/ssh"
fhrclient "github.com/weaveworks/flux/integrations/client/clientset/versioned"
"github.com/weaveworks/flux/resource"
"github.com/weaveworks/flux/ssh"
)

type coreClient k8sclient.Interface
type dynamicClient k8sclientdynamic.Interface
type fluxHelmClient fhrclient.Interface
type helmOperatorClient hrclient.Interface
type discoveryClient discovery.DiscoveryInterface

type ExtendedClient struct {
coreClient
dynamicClient
fluxHelmClient
helmOperatorClient
discoveryClient
}

func MakeClusterClientset(core coreClient, dyn dynamicClient, fluxhelm fluxHelmClient, disco discoveryClient) ExtendedClient {
func MakeClusterClientset(core coreClient, dyn dynamicClient, fluxhelm fluxHelmClient,
helmop helmOperatorClient, disco discoveryClient) ExtendedClient {

return ExtendedClient{
coreClient: core,
dynamicClient: dyn,
fluxHelmClient: fluxhelm,
discoveryClient: disco,
coreClient: core,
dynamicClient: dyn,
fluxHelmClient: fluxhelm,
helmOperatorClient: helmop,
discoveryClient: disco,
}
}

Expand Down
2 changes: 1 addition & 1 deletion cluster/kubernetes/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func applyManifestPatch(originalManifests, patchManifests []byte, originalSource
func getFullScheme() *runtime.Scheme {
fullScheme := runtime.NewScheme()
utilruntime.Must(k8sscheme.AddToScheme(fullScheme))
// HelmRelease and FluxHelmRelease are intentionally not added to the scheme.
// HelmRelease and HelmRelease are intentionally not added to the scheme.
// This is done for two reasons:
// 1. The kubernetes strategic merge patcher chokes on the freeform
// values under `values:`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

// ReleaseContainerName is the name used when Flux interprets a
// FluxHelmRelease as having a container with an image, by virtue of
// HelmRelease as having a container with an image, by virtue of
// having a `values` stanza with an image field:
//
// spec:
Expand All @@ -20,11 +20,11 @@ import (
// The name refers to the source of the image value.
const ReleaseContainerName = "chart-image"

// FluxHelmRelease echoes the generated type for the custom resource
// HelmRelease echoes the generated type for the custom resource
// definition. It's here so we can 1. get `baseObject` in there, and
// 3. control the YAML serialisation of fields, which we can't do
// (easily?) with the generated type.
type FluxHelmRelease struct {
type HelmRelease struct {
baseObject
Spec struct {
Values map[string]interface{}
Expand All @@ -47,13 +47,13 @@ func sorted_keys(values map[string]interface{}) []string {
return keys
}

// FindFluxHelmReleaseContainers examines the Values from a
// FluxHelmRelease (manifest, or cluster resource, or otherwise) and
// FindHelmReleaseContainers examines the Values from a
// HelmRelease (manifest, or cluster resource, or otherwise) and
// calls visit with each container name and image it finds, as well as
// procedure for changing the image value. It will return an error if
// it cannot interpret the values as specifying images, or if the
// `visit` function itself returns an error.
func FindFluxHelmReleaseContainers(values map[string]interface{}, visit func(string, image.Ref, ImageSetter) error) error {
func FindHelmReleaseContainers(values map[string]interface{}, visit func(string, image.Ref, ImageSetter) error) error {
// an image defined at the top-level is given a standard container name:
if image, setter, ok := interpretAsContainer(stringMap(values)); ok {
visit(ReleaseContainerName, image, setter)
Expand All @@ -70,7 +70,7 @@ func FindFluxHelmReleaseContainers(values map[string]interface{}, visit func(str
}

// The following is some machinery for interpreting a
// FluxHelmRelease's `values` field as defining images to be
// HelmRelease's `values` field as defining images to be
// interpolated into the chart templates.
//
// The top-level value is a map[string]interface{}, but beneath that,
Expand Down Expand Up @@ -221,11 +221,11 @@ func interpretAsImage(m mapper) (image.Ref, ImageSetter, bool) {
}

// Containers returns the containers that are defined in the
// FluxHelmRelease.
func (fhr FluxHelmRelease) Containers() []resource.Container {
// HelmRelease.
func (hr HelmRelease) Containers() []resource.Container {
var containers []resource.Container
// If there's an error in interpreting, return what we have.
_ = FindFluxHelmReleaseContainers(fhr.Spec.Values, func(container string, image image.Ref, _ ImageSetter) error {
_ = FindHelmReleaseContainers(hr.Spec.Values, func(container string, image image.Ref, _ ImageSetter) error {
containers = append(containers, resource.Container{
Name: container,
Image: image,
Expand All @@ -237,11 +237,11 @@ func (fhr FluxHelmRelease) Containers() []resource.Container {

// SetContainerImage mutates this resource by setting the `image`
// field of `values`, or a subvalue therein, per one of the
// interpretations in `FindFluxHelmReleaseContainers` above. NB we can
// interpretations in `FindHelmReleaseContainers` above. NB we can
// get away with a value-typed receiver because we set a map entry.
func (fhr FluxHelmRelease) SetContainerImage(container string, ref image.Ref) error {
func (hr HelmRelease) SetContainerImage(container string, ref image.Ref) error {
found := false
if err := FindFluxHelmReleaseContainers(fhr.Spec.Values, func(name string, image image.Ref, setter ImageSetter) error {
if err := FindHelmReleaseContainers(hr.Spec.Values, func(name string, image image.Ref, setter ImageSetter) error {
if container == name {
setter(ref)
found = true
Expand All @@ -251,7 +251,7 @@ func (fhr FluxHelmRelease) SetContainerImage(container string, ref image.Ref) er
return err
}
if !found {
return fmt.Errorf("did not find container %s in FluxHelmRelease", container)
return fmt.Errorf("did not find container %s in HelmRelease", container)
}
return nil
}
Loading

0 comments on commit a9f8b0a

Please sign in to comment.