diff --git a/apis/installer/v1alpha1/hub_cluster_robot_types.go b/apis/installer/v1alpha1/hub_cluster_robot_types.go
new file mode 100644
index 00000000..837fb961
--- /dev/null
+++ b/apis/installer/v1alpha1/hub_cluster_robot_types.go
@@ -0,0 +1,65 @@
+/*
+Copyright AppsCode Inc. and 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 v1alpha1
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+const (
+ ResourceKindHubManagerRobot = "HubManagerRobot"
+ ResourceHubManagerRobot = "hubmanagerrobot"
+ ResourceHubManagerRobots = "hubmanagerrobots"
+)
+
+// HubManagerRobot defines the schama for HubManagerRobot.
+
+// +genclient
+// +genclient:skipVerbs=updateStatus
+// +k8s:openapi-gen=true
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:path=hubmanagerrobots,singular=hubmanagerrobot,categories={kubeops,appscode}
+type HubManagerRobot struct {
+ metav1.TypeMeta `json:",inline,omitempty"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+ Spec HubManagerRobotSpec `json:"spec,omitempty"`
+}
+
+// HubManagerRobotSpec is the schema for Identity Server values file
+type HubManagerRobotSpec struct {
+ //+optional
+ NameOverride string `json:"nameOverride"`
+ //+optional
+ FullnameOverride string `json:"fullnameOverride"`
+ // +optional
+ KubeconfigSecretName string `json:"kubeconfigSecretName"`
+ // +optional
+ AddonManagerNamespace string `json:"addonManagerNamespace"`
+ Kubectl DockerImage `json:"kubectl"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// HubManagerRobotList is a list of HubManagerRobots
+type HubManagerRobotList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ // Items is a list of HubManagerRobot CRD objects
+ Items []HubManagerRobot `json:"items,omitempty"`
+}
diff --git a/apis/installer/v1alpha1/register.go b/apis/installer/v1alpha1/register.go
index c3251ed9..ac1faf15 100644
--- a/apis/installer/v1alpha1/register.go
+++ b/apis/installer/v1alpha1/register.go
@@ -61,6 +61,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ClusterManagerHubList{},
&ClusterManagerSpoke{},
&ClusterManagerSpokeList{},
+ &HubManagerRobot{},
+ &HubManagerRobotList{},
)
scheme.AddKnownTypes(SchemeGroupVersion,
diff --git a/apis/installer/v1alpha1/zz_generated.deepcopy.go b/apis/installer/v1alpha1/zz_generated.deepcopy.go
index d8eafd27..9309da4b 100644
--- a/apis/installer/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/installer/v1alpha1/zz_generated.deepcopy.go
@@ -571,6 +571,80 @@ func (in *HubInfo) DeepCopy() *HubInfo {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HubManagerRobot) DeepCopyInto(out *HubManagerRobot) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ out.Spec = in.Spec
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HubManagerRobot.
+func (in *HubManagerRobot) DeepCopy() *HubManagerRobot {
+ if in == nil {
+ return nil
+ }
+ out := new(HubManagerRobot)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *HubManagerRobot) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HubManagerRobotList) DeepCopyInto(out *HubManagerRobotList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]HubManagerRobot, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HubManagerRobotList.
+func (in *HubManagerRobotList) DeepCopy() *HubManagerRobotList {
+ if in == nil {
+ return nil
+ }
+ out := new(HubManagerRobotList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *HubManagerRobotList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HubManagerRobotSpec) DeepCopyInto(out *HubManagerRobotSpec) {
+ *out = *in
+ out.Kubectl = in.Kubectl
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HubManagerRobotSpec.
+func (in *HubManagerRobotSpec) DeepCopy() *HubManagerRobotSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(HubManagerRobotSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageRef) DeepCopyInto(out *ImageRef) {
*out = *in
diff --git a/charts/hub-cluster-robot/Chart.yaml b/charts/hub-cluster-robot/Chart.yaml
new file mode 100644
index 00000000..8bbff164
--- /dev/null
+++ b/charts/hub-cluster-robot/Chart.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+description: Hub Cluster Robot
+name: hub-cluster-robot
+version: v2024.8.9
+appVersion: v0.0.1
+home: https://github.com/kluster-manager/cluster-auth
+icon: https://cdn.appscode.com/images/products/searchlight/icons/android-icon-192x192.png
+sources:
+- https://github.com/kluster-manager/cluster-auth
+maintainers:
+- name: appscode
+ email: support@appscode.com
diff --git a/charts/hub-cluster-robot/README.md b/charts/hub-cluster-robot/README.md
new file mode 100644
index 00000000..3b7fc8cd
--- /dev/null
+++ b/charts/hub-cluster-robot/README.md
@@ -0,0 +1,68 @@
+# Hub Cluster Robot
+
+[Hub Cluster Robot](https://github.com/kluster-manager) - Hub Cluster Robot
+
+## TL;DR;
+
+```bash
+$ helm repo add appscode https://charts.appscode.com/stable
+$ helm repo update
+$ helm search repo appscode/hub-cluster-robot --version=v2024.8.9
+$ helm upgrade -i hub-cluster-robot appscode/hub-cluster-robot -n open-cluster-management --create-namespace --version=v2024.8.9
+```
+
+## Introduction
+
+This chart deploys a Hub Cluster Robot on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
+
+## Prerequisites
+
+- Kubernetes 1.21+
+
+## Installing the Chart
+
+To install/upgrade the chart with the release name `hub-cluster-robot`:
+
+```bash
+$ helm upgrade -i hub-cluster-robot appscode/hub-cluster-robot -n open-cluster-management --create-namespace --version=v2024.8.9
+```
+
+The command deploys a Hub Cluster Robot on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
+
+> **Tip**: List all releases using `helm list`
+
+## Uninstalling the Chart
+
+To uninstall the `hub-cluster-robot`:
+
+```bash
+$ helm uninstall hub-cluster-robot -n open-cluster-management
+```
+
+The command removes all the Kubernetes components associated with the chart and deletes the release.
+
+## Configuration
+
+The following table lists the configurable parameters of the `hub-cluster-robot` chart and their default values.
+
+| Parameter | Description | Default |
+|-----------------------|-------------|----------------------------------------------------|
+| nameOverride | | ""
|
+| fullnameOverride | | ""
|
+| kubeconfigSecretName | | ""
|
+| addonManagerNamespace | | open-cluster-management-cluster-auth
|
+| kubectl.image | | ghcr.io/appscode/kubectl-nonroot:1.25
|
+
+
+Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade -i`. For example:
+
+```bash
+$ helm upgrade -i hub-cluster-robot appscode/hub-cluster-robot -n open-cluster-management --create-namespace --version=v2024.8.9 --set addonManagerNamespace=open-cluster-management-cluster-auth
+```
+
+Alternatively, a YAML file that specifies the values for the parameters can be provided while
+installing the chart. For example:
+
+```bash
+$ helm upgrade -i hub-cluster-robot appscode/hub-cluster-robot -n open-cluster-management --create-namespace --version=v2024.8.9 --values values.yaml
+```
diff --git a/charts/hub-cluster-robot/common/rbac/cluster_role.yaml b/charts/hub-cluster-robot/common/rbac/cluster_role.yaml
new file mode 100644
index 00000000..3c588d2f
--- /dev/null
+++ b/charts/hub-cluster-robot/common/rbac/cluster_role.yaml
@@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: open-cluster-management:hub-cluster-robot:cluster-auth
+rules:
+ - apiGroups: [""]
+ resources: ["secrets", "serviceaccounts"]
+ verbs: ["get", "list", "watch"]
+ - apiGroups: [ "authentication.k8s.appscode.com" ]
+ resources: [ "*" ]
+ verbs: [ "*" ]
diff --git a/charts/hub-cluster-robot/common/rbac/role_binding.yaml b/charts/hub-cluster-robot/common/rbac/role_binding.yaml
new file mode 100644
index 00000000..524e2fd4
--- /dev/null
+++ b/charts/hub-cluster-robot/common/rbac/role_binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: open-cluster-management:hub-cluster-robot:cluster-auth
+ namespace: open-cluster-management-cluster-auth
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: open-cluster-management:hub-cluster-robot
+subjects:
+ - kind: ServiceAccount
+ name: hub-cluster-robot
+ namespace: {{ .Release.Namespace }}
diff --git a/charts/hub-cluster-robot/common/rbac/service_account.yaml b/charts/hub-cluster-robot/common/rbac/service_account.yaml
new file mode 100644
index 00000000..77a18c6a
--- /dev/null
+++ b/charts/hub-cluster-robot/common/rbac/service_account.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: hub-cluster-robot
+ namespace: {{ .Release.Namespace }}
diff --git a/charts/hub-cluster-robot/doc.yaml b/charts/hub-cluster-robot/doc.yaml
new file mode 100644
index 00000000..df0c4e73
--- /dev/null
+++ b/charts/hub-cluster-robot/doc.yaml
@@ -0,0 +1,18 @@
+project:
+ name: Hub Cluster Robot
+ shortName: Hub Cluster Robot
+ url: https://github.com/kluster-manager
+ description: Hub Cluster Robot
+ app: a Hub Cluster Robot
+repository:
+ url: https://charts.appscode.com/stable
+ name: appscode
+chart:
+ name: hub-cluster-robot
+ values: -- generate from values file --
+ valuesExample: -- generate from values file --
+prerequisites:
+- Kubernetes 1.21+
+release:
+ name: hub-cluster-robot
+ namespace: open-cluster-management
diff --git a/charts/hub-cluster-robot/templates/_helpers.tpl b/charts/hub-cluster-robot/templates/_helpers.tpl
new file mode 100644
index 00000000..806506c9
--- /dev/null
+++ b/charts/hub-cluster-robot/templates/_helpers.tpl
@@ -0,0 +1,69 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "hub-cluster-robot.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "hub-cluster-robot.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "hub-cluster-robot.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "hub-cluster-robot.labels" -}}
+helm.sh/chart: {{ include "hub-cluster-robot.chart" . }}
+{{ include "hub-cluster-robot.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "hub-cluster-robot.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "hub-cluster-robot.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "hub-cluster-robot.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "hub-cluster-robot.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Addon manager namespace
+*/}}
+{{- define "hub-cluster-robot.namespace" -}}
+{{ ternary .Release.Namespace (required "A valid .Values.addonManagerNamespace is required!" .Values.addonManagerNamespace) (empty .Values.kubeconfigSecretName) }}
+{{- end }}
diff --git a/charts/hub-cluster-robot/templates/k8s/addon.yaml b/charts/hub-cluster-robot/templates/k8s/addon.yaml
new file mode 100644
index 00000000..0019a134
--- /dev/null
+++ b/charts/hub-cluster-robot/templates/k8s/addon.yaml
@@ -0,0 +1,12 @@
+{{- if not .Values.kubeconfigSecretName }}
+
+{{- $restpl := $.Files.Get "common/rbac/service_account.yaml" }}
+{{ tpl $restpl $ }}
+---
+{{- $restpl := $.Files.Get "common/rbac/cluster_role.yaml" }}
+{{ tpl $restpl $ }}
+---
+{{- $restpl := $.Files.Get "common/rbac/role_binding.yaml" }}
+{{ tpl $restpl $ }}
+
+{{- end }}
diff --git a/charts/hub-cluster-robot/templates/ocm-mc/addon.yaml b/charts/hub-cluster-robot/templates/ocm-mc/addon.yaml
new file mode 100644
index 00000000..150e7d9e
--- /dev/null
+++ b/charts/hub-cluster-robot/templates/ocm-mc/addon.yaml
@@ -0,0 +1,49 @@
+{{- if .Values.kubeconfigSecretName }}
+
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: cluster-auth-configure-addon
+ namespace: {{ .Release.Namespace }}
+ annotations:
+ "helm.sh/hook-weight": "2"
+ "helm.sh/hook": post-install,post-upgrade,post-rollback
+ "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed
+spec:
+ ttlSecondsAfterFinished: 0
+ backoffLimit: 3
+ template:
+ spec:
+ automountServiceAccountToken: false
+ containers:
+ - name: kubectl
+ image: {{ .Values.kubectl.image }}
+ workingDir: /var/run/secrets/ocm
+ command:
+ - sh
+ - -c
+ - |
+ sleep 2; \
+ kubectl --kubeconfig=auth/kubeconfig create ns {{ include "hub-cluster-robot.namespace" $ }} || true; \
+ kubectl --kubeconfig=auth/kubeconfig apply -f - <