Skip to content
This repository was archived by the owner on Mar 10, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/manager_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type AccountConfig struct {
type K8SConfig struct {
KubeConfigPath string `mapstructure:"kube_config_path"`
IsInCluster bool `mapstructure:"in_cluster"`
CRDNamespace string `mapstructure:"crd_namespace"`
}

var managerCfg *ManageConfig
Expand Down
73 changes: 73 additions & 0 deletions deployment/crds/schedulingintent-crd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: schedulingintents.gthulhu.io
spec:
group: gthulhu.io
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
strategyID:
type: string
podID:
type: string
podName:
type: string
nodeID:
type: string
k8sNamespace:
type: string
commandRegex:
type: string
priority:
type: integer
executionTime:
type: integer
format: int64
podLabels:
type: object
additionalProperties:
type: string
state:
type: integer
creatorID:
type: string
updaterID:
type: string
createdTime:
type: integer
format: int64
updatedTime:
type: integer
format: int64
additionalPrinterColumns:
- name: Strategy
type: string
jsonPath: .spec.strategyID
- name: Pod
type: string
jsonPath: .spec.podName
- name: Node
type: string
jsonPath: .spec.nodeID
- name: State
type: integer
jsonPath: .spec.state
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
scope: Namespaced
names:
plural: schedulingintents
singular: schedulingintent
kind: SchedulingIntent
shortNames:
- si
66 changes: 66 additions & 0 deletions deployment/crds/schedulingstrategy-crd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: schedulingstrategies.gthulhu.io
spec:
group: gthulhu.io
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
strategyNamespace:
type: string
labelSelectors:
type: array
items:
type: object
properties:
key:
type: string
value:
type: string
k8sNamespaces:
type: array
items:
type: string
commandRegex:
type: string
priority:
type: integer
executionTime:
type: integer
format: int64
creatorID:
type: string
updaterID:
type: string
createdTime:
type: integer
format: int64
updatedTime:
type: integer
format: int64
additionalPrinterColumns:
- name: Priority
type: integer
jsonPath: .spec.priority
- name: Creator
type: string
jsonPath: .spec.creatorID
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
scope: Namespaced
names:
plural: schedulingstrategies
singular: schedulingstrategy
kind: SchedulingStrategy
shortNames:
- ss
35 changes: 35 additions & 0 deletions deployment/rbac/manager-crd-rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# ClusterRole granting the API Server (manager mode) full access to
# SchedulingStrategy and SchedulingIntent custom resources.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gthulhu-manager-crd
rules:
- apiGroups: ["gthulhu.io"]
resources: ["schedulingstrategies", "schedulingintents"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
# Bind the ClusterRole to the manager ServiceAccount so that only the
# manager pods can manipulate scheduling CRs.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gthulhu-manager-crd-binding
subjects:
- kind: ServiceAccount
name: gthulhu-manager
namespace: gthulhu-system

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ClusterRoleBinding targets ServiceAccount gthulhu-manager in namespace gthulhu-system, but the existing manager deployment manifest uses ServiceAccount manager in namespace gthulhu-api-local (deployment/kind/manager/deployment.yaml). As-is, applying this RBAC in the kind environment won't grant the manager pod access to the CRDs. Consider aligning the subject to the actual ServiceAccount/namespace used by your deployment manifests (or providing environment-specific overlays/templates).

Suggested change
name: gthulhu-manager
namespace: gthulhu-system
name: manager
namespace: gthulhu-api-local

Copilot uses AI. Check for mistakes.
roleRef:
kind: ClusterRole
name: gthulhu-manager-crd
apiGroup: rbac.authorization.k8s.io
---
# Read-only ClusterRole for monitoring / dashboards.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gthulhu-crd-viewer
rules:
- apiGroups: ["gthulhu.io"]
resources: ["schedulingstrategies", "schedulingintents"]
verbs: ["get", "list", "watch"]
22 changes: 22 additions & 0 deletions manager/app/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"github.com/Gthulhu/api/manager/service"
"github.com/Gthulhu/api/pkg/container"
"go.uber.org/fx"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
dynamicfake "k8s.io/client-go/dynamic/fake"
)

// ConfigModule creates an Fx module that provides configuration structs
Expand Down Expand Up @@ -48,6 +52,12 @@ func AdapterModule() (fx.Option, error) {
InCluster: k8sConfig.IsInCluster,
})
}),
fx.Provide(func(k8sConfig config.K8SConfig) (dynamic.Interface, error) {
return k8sadapter.NewDynamicClient(k8sadapter.Options{
KubeConfigPath: k8sConfig.KubeConfigPath,
InCluster: k8sConfig.IsInCluster,
})
}),
fx.Provide(client.NewDecisionMakerClient),
), nil
}
Expand Down Expand Up @@ -100,6 +110,18 @@ func TestRepoModule(cfg config.ManageConfig, containerBuilder *container.Contain
}
return fx.Options(
configModule,
fx.Provide(NewFakeDynamicClient),
fx.Provide(repository.NewRepository),
), nil
}

// NewFakeDynamicClient returns a fake Kubernetes dynamic client for testing.
func NewFakeDynamicClient() dynamic.Interface {
scheme := runtime.NewScheme()
return dynamicfake.NewSimpleDynamicClientWithCustomListKinds(scheme,
map[schema.GroupVersionResource]string{
{Group: "gthulhu.io", Version: "v1alpha1", Resource: "schedulingstrategies"}: "SchedulingStrategyList",
{Group: "gthulhu.io", Version: "v1alpha1", Resource: "schedulingintents"}: "SchedulingIntentList",
},
)
}
2 changes: 1 addition & 1 deletion manager/domain/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ type Repository interface {
BatchUpdateIntentsState(ctx context.Context, intentIDs []bson.ObjectID, newState IntentState) error
QueryStrategies(ctx context.Context, opt *QueryStrategyOptions) error
QueryIntents(ctx context.Context, opt *QueryIntentOptions) error
UpdateStrategy(ctx context.Context, strategyID bson.ObjectID, update bson.M) error
UpdateStrategy(ctx context.Context, strategy *ScheduleStrategy) error
DeleteStrategy(ctx context.Context, strategyID bson.ObjectID) error
DeleteIntents(ctx context.Context, intentIDs []bson.ObjectID) error
DeleteIntentsByStrategyID(ctx context.Context, strategyID bson.ObjectID) error
Expand Down
Loading