diff --git a/cmd/capacitor/main.go b/cmd/capacitor/main.go
index 86ac9f0..86b9cf0 100644
--- a/cmd/capacitor/main.go
+++ b/cmd/capacitor/main.go
@@ -51,6 +51,10 @@ func main() {
runController(err, ociRepositoryController, stopCh)
bucketController, err := controllers.BucketController(client, dynamicClient, clientHub)
runController(err, bucketController, stopCh)
+ helmRepositoryController, err := controllers.HelmRepositoryController(client, dynamicClient, clientHub)
+ runController(err, helmRepositoryController, stopCh)
+ helmChartController, err := controllers.HelmChartController(client, dynamicClient, clientHub)
+ runController(err, helmChartController, stopCh)
kustomizationController, err := controllers.KustomizeController(client, dynamicClient, clientHub)
runController(err, kustomizationController, stopCh)
helmReleaseController, err := controllers.HelmReleaseController(client, dynamicClient, clientHub)
diff --git a/deploy/k8s/rbac.yaml b/deploy/k8s/rbac.yaml
index d1e7c28..309aeb9 100644
--- a/deploy/k8s/rbac.yaml
+++ b/deploy/k8s/rbac.yaml
@@ -34,6 +34,8 @@ rules:
- gitrepositories
- ocirepositories
- buckets
+ - helmrepositories
+ - helmcharts
- kustomizations
- helmreleases
verbs:
diff --git a/pkg/controllers/helmChartController.go b/pkg/controllers/helmChartController.go
new file mode 100644
index 0000000..0e8e9d1
--- /dev/null
+++ b/pkg/controllers/helmChartController.go
@@ -0,0 +1,54 @@
+package controllers
+
+import (
+ "encoding/json"
+
+ "github.com/gimlet-io/capacitor/pkg/flux"
+ "github.com/gimlet-io/capacitor/pkg/streaming"
+ "github.com/sirupsen/logrus"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/kubernetes"
+)
+
+var helmChartResource = schema.GroupVersionResource{
+ Group: "source.toolkit.fluxcd.io",
+ Version: "v1beta2",
+ Resource: "helmcharts",
+}
+
+func HelmChartController(
+ client *kubernetes.Clientset,
+ dynamicClient *dynamic.DynamicClient,
+ clientHub *streaming.ClientHub,
+) (*Controller, error) {
+ return NewDynamicController(
+ "helmcharts.source.toolkit.fluxcd.io",
+ dynamicClient,
+ helmChartResource,
+ func(informerEvent Event, objectMeta metav1.ObjectMeta, obj interface{}) error {
+ switch informerEvent.eventType {
+ case "create":
+ fallthrough
+ case "update":
+ fallthrough
+ case "delete":
+ fluxState, err := flux.State(client, dynamicClient)
+ if err != nil {
+ logrus.Warnf("could not get flux state: %s", err)
+ return nil
+ }
+ fluxStateBytes, err := json.Marshal(streaming.Envelope{
+ Type: streaming.FLUX_STATE_RECEIVED,
+ Payload: fluxState,
+ })
+ if err != nil {
+ logrus.Warnf("could not marshal event: %s", err)
+ return nil
+ }
+ clientHub.Broadcast <- fluxStateBytes
+ }
+ return nil
+ })
+}
diff --git a/pkg/controllers/helmRepositoryController.go b/pkg/controllers/helmRepositoryController.go
new file mode 100644
index 0000000..a6d92bd
--- /dev/null
+++ b/pkg/controllers/helmRepositoryController.go
@@ -0,0 +1,54 @@
+package controllers
+
+import (
+ "encoding/json"
+
+ "github.com/gimlet-io/capacitor/pkg/flux"
+ "github.com/gimlet-io/capacitor/pkg/streaming"
+ "github.com/sirupsen/logrus"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/kubernetes"
+)
+
+var helmRepositoryResource = schema.GroupVersionResource{
+ Group: "source.toolkit.fluxcd.io",
+ Version: "v1beta2",
+ Resource: "helmrepositories",
+}
+
+func HelmRepositoryController(
+ client *kubernetes.Clientset,
+ dynamicClient *dynamic.DynamicClient,
+ clientHub *streaming.ClientHub,
+) (*Controller, error) {
+ return NewDynamicController(
+ "helmrepositories.source.toolkit.fluxcd.io",
+ dynamicClient,
+ helmRepositoryResource,
+ func(informerEvent Event, objectMeta metav1.ObjectMeta, obj interface{}) error {
+ switch informerEvent.eventType {
+ case "create":
+ fallthrough
+ case "update":
+ fallthrough
+ case "delete":
+ fluxState, err := flux.State(client, dynamicClient)
+ if err != nil {
+ logrus.Warnf("could not get flux state: %s", err)
+ return nil
+ }
+ fluxStateBytes, err := json.Marshal(streaming.Envelope{
+ Type: streaming.FLUX_STATE_RECEIVED,
+ Payload: fluxState,
+ })
+ if err != nil {
+ logrus.Warnf("could not marshal event: %s", err)
+ return nil
+ }
+ clientHub.Broadcast <- fluxStateBytes
+ }
+ return nil
+ })
+}
diff --git a/pkg/flux/flux.go b/pkg/flux/flux.go
index 259c08c..f0e1bfc 100644
--- a/pkg/flux/flux.go
+++ b/pkg/flux/flux.go
@@ -66,6 +66,18 @@ var (
Version: "v2beta1",
Resource: "helmreleases",
}
+
+ helmRepositoryGVR = schema.GroupVersionResource{
+ Group: "source.toolkit.fluxcd.io",
+ Version: "v1beta2",
+ Resource: "helmrepositories",
+ }
+
+ helmChartGVR = schema.GroupVersionResource{
+ Group: "source.toolkit.fluxcd.io",
+ Version: "v1beta2",
+ Resource: "helmcharts",
+ }
)
func helmServices(dc *dynamic.DynamicClient) ([]Service, error) {
@@ -336,12 +348,14 @@ func helmStatusWithResources(
func State(c *kubernetes.Clientset, dc *dynamic.DynamicClient) (*FluxState, error) {
fluxState := &FluxState{
- GitRepositories: []sourcev1.GitRepository{},
- OCIRepositories: []sourcev1beta2.OCIRepository{},
- Buckets: []sourcev1beta2.Bucket{},
- Kustomizations: []kustomizationv1.Kustomization{},
- HelmReleases: []helmv2beta2.HelmRelease{},
- FluxServices: []Service{},
+ GitRepositories: []sourcev1.GitRepository{},
+ OCIRepositories: []sourcev1beta2.OCIRepository{},
+ Buckets: []sourcev1beta2.Bucket{},
+ Kustomizations: []kustomizationv1.Kustomization{},
+ HelmReleases: []helmv2beta2.HelmRelease{},
+ HelmRepositories: []sourcev1beta2.HelmRepository{},
+ HelmCharts: []sourcev1beta2.HelmChart{},
+ FluxServices: []Service{},
}
gitRepositories, err := dc.Resource(gitRepositoryGVR).
@@ -442,6 +456,38 @@ func State(c *kubernetes.Clientset, dc *dynamic.DynamicClient) (*FluxState, erro
fluxState.HelmReleases = append(fluxState.HelmReleases, helmRelease)
}
+ helmRepositories, err := dc.Resource(helmRepositoryGVR).
+ Namespace("").
+ List(context.TODO(), metav1.ListOptions{})
+ if err != nil {
+ return nil, err
+ }
+ for _, h := range helmRepositories.Items {
+ unstructured := h.UnstructuredContent()
+ var helmRepository sourcev1beta2.HelmRepository
+ err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructured, &helmRepository)
+ if err != nil {
+ return nil, err
+ }
+ fluxState.HelmRepositories = append(fluxState.HelmRepositories, helmRepository)
+ }
+
+ helmCharts, err := dc.Resource(helmChartGVR).
+ Namespace("").
+ List(context.TODO(), metav1.ListOptions{})
+ if err != nil {
+ return nil, err
+ }
+ for _, h := range helmCharts.Items {
+ unstructured := h.UnstructuredContent()
+ var helmChart sourcev1beta2.HelmChart
+ err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructured, &helmChart)
+ if err != nil {
+ return nil, err
+ }
+ fluxState.HelmCharts = append(fluxState.HelmCharts, helmChart)
+ }
+
fluxServices, err := fluxServicesWithDetails(c)
if err != nil {
return nil, err
diff --git a/pkg/flux/reconcile.go b/pkg/flux/reconcile.go
index 96b587d..c3a6961 100644
--- a/pkg/flux/reconcile.go
+++ b/pkg/flux/reconcile.go
@@ -86,6 +86,18 @@ func NewReconcileCommand(resource string) *reconcileCommand {
groupVersion: sourcev1beta2.GroupVersion,
kind: sourcev1beta2.BucketKind,
}
+ case sourcev1beta2.HelmRepositoryKind:
+ return &reconcileCommand{
+ object: helmRepositoryAdapter{&sourcev1beta2.HelmRepository{}},
+ groupVersion: sourcev1beta2.GroupVersion,
+ kind: sourcev1beta2.HelmRepositoryKind,
+ }
+ case sourcev1beta2.HelmChartKind:
+ return &reconcileCommand{
+ object: helmChartAdapter{&sourcev1beta2.HelmChart{}},
+ groupVersion: sourcev1beta2.GroupVersion,
+ kind: sourcev1beta2.HelmChartKind,
+ }
}
return nil
diff --git a/pkg/flux/source.go b/pkg/flux/source.go
index 991db6e..108effa 100644
--- a/pkg/flux/source.go
+++ b/pkg/flux/source.go
@@ -84,3 +84,43 @@ func (obj bucketAdapter) lastHandledReconcileRequest() string {
func (obj bucketAdapter) successMessage() string {
return fmt.Sprintf("fetched revision %s", obj.Status.Artifact.Revision)
}
+
+type helmRepositoryAdapter struct {
+ *sourcev1beta2.HelmRepository
+}
+
+func (a helmRepositoryAdapter) asClientObject() client.Object {
+ return a.HelmRepository
+}
+
+func (obj helmRepositoryAdapter) isSuspended() bool {
+ return obj.HelmRepository.Spec.Suspend
+}
+
+func (obj helmRepositoryAdapter) lastHandledReconcileRequest() string {
+ return obj.Status.GetLastHandledReconcileRequest()
+}
+
+func (obj helmRepositoryAdapter) successMessage() string {
+ return fmt.Sprintf("fetched revision %s", obj.Status.Artifact.Revision)
+}
+
+type helmChartAdapter struct {
+ *sourcev1beta2.HelmChart
+}
+
+func (a helmChartAdapter) asClientObject() client.Object {
+ return a.HelmChart
+}
+
+func (obj helmChartAdapter) isSuspended() bool {
+ return obj.HelmChart.Spec.Suspend
+}
+
+func (obj helmChartAdapter) lastHandledReconcileRequest() string {
+ return obj.Status.GetLastHandledReconcileRequest()
+}
+
+func (obj helmChartAdapter) successMessage() string {
+ return fmt.Sprintf("fetched revision %s", obj.Status.Artifact.Revision)
+}
diff --git a/pkg/flux/types.go b/pkg/flux/types.go
index 8149cbd..fade128 100644
--- a/pkg/flux/types.go
+++ b/pkg/flux/types.go
@@ -13,12 +13,14 @@ import (
)
type FluxState struct {
- GitRepositories []sourcev1.GitRepository `json:"gitRepositories"`
- OCIRepositories []sourcev1beta2.OCIRepository `json:"ociRepositories"`
- Buckets []sourcev1beta2.Bucket `json:"buckets"`
- Kustomizations []kustomizationv1.Kustomization `json:"kustomizations"`
- HelmReleases []helmv2beta2.HelmRelease `json:"helmReleases"`
- FluxServices []Service `json:"fluxServices"`
+ GitRepositories []sourcev1.GitRepository `json:"gitRepositories"`
+ OCIRepositories []sourcev1beta2.OCIRepository `json:"ociRepositories"`
+ Buckets []sourcev1beta2.Bucket `json:"buckets"`
+ Kustomizations []kustomizationv1.Kustomization `json:"kustomizations"`
+ HelmReleases []helmv2beta2.HelmRelease `json:"helmReleases"`
+ HelmRepositories []sourcev1beta2.HelmRepository `json:"helmRepositories"`
+ HelmCharts []sourcev1beta2.HelmChart `json:"helmCharts"`
+ FluxServices []Service `json:"fluxServices"`
}
type Service struct {
diff --git a/web/src/ExpandedFooter.jsx b/web/src/ExpandedFooter.jsx
index a6717ed..b11d292 100644
--- a/web/src/ExpandedFooter.jsx
+++ b/web/src/ExpandedFooter.jsx
@@ -39,7 +39,7 @@ export function ExpandedFooter(props) {
{release.chartVersion}@{release.chartName}
{statusLabel}
-