Initial scaffold: project structure, CRDs, Makefile
- Agent CRD: deployment spec, workspace config, channels, judge integration - AgentGroup CRD: multi-agent orchestration with shared configs - JudgePolicy CRD: cluster-scoped authorization policies with per-agent overrides - Makefile: build, generate, install, test, helm targets - Go module: controller-runtime + apimachinery dependencies
This commit is contained in:
parent
e9c196cd60
commit
1a831bdfe5
7 changed files with 611 additions and 1 deletions
70
Makefile
Normal file
70
Makefile
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
.PHONY: all build run install uninstall generate manifests test lint
|
||||
|
||||
# Container image settings
|
||||
IMG ?= ghcr.io/sscoble/kubeclaw:latest
|
||||
CONTAINER_RUNTIME ?= docker
|
||||
|
||||
# Environment
|
||||
KUBECTL ?= kubectl
|
||||
CONTROLLER_GEN ?= $(shell go env GOPATH)/bin/controller-gen
|
||||
|
||||
all: build
|
||||
|
||||
##@ Build
|
||||
|
||||
build: manifests generate fmt vet
|
||||
go build -o bin/manager ./cmd/manager
|
||||
|
||||
run: manifests generate fmt vet
|
||||
go run ./cmd/manager
|
||||
|
||||
##@ CRDs
|
||||
|
||||
manifests: $(CONTROLLER_GEN)
|
||||
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./api/..." output:crd:artifacts:config=config/crd/bases
|
||||
|
||||
generate: $(CONTROLLER_GEN)
|
||||
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..."
|
||||
|
||||
install: manifests
|
||||
$(KUBECTL) apply -f config/crd/bases
|
||||
|
||||
uninstall: manifests
|
||||
$(KUBECTL) delete -f config/crd/bases
|
||||
|
||||
##@ Test
|
||||
|
||||
test: manifests generate fmt vet
|
||||
go test ./... -coverprofile cover.out
|
||||
|
||||
##@ Lint
|
||||
|
||||
fmt:
|
||||
go fmt ./...
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
lint:
|
||||
golangci-lint run
|
||||
|
||||
##@ Dependencies
|
||||
|
||||
$(CONTROLLER_GEN):
|
||||
go install sigs.k8s.io/controller-runtime/cmd/controller-gen@latest
|
||||
|
||||
##@ Helm
|
||||
|
||||
helm-package:
|
||||
helm package charts/kubeclaw -d bin/
|
||||
|
||||
helm-template:
|
||||
helm template kubeclaw charts/kubeclaw
|
||||
|
||||
##@ Container
|
||||
|
||||
docker-build:
|
||||
$(CONTAINER_RUNTIME) build -t ${IMG} .
|
||||
|
||||
docker-push:
|
||||
$(CONTAINER_RUNTIME) push ${IMG}
|
||||
95
README.md
95
README.md
|
|
@ -1,3 +1,96 @@
|
|||
# kubeclaw
|
||||
|
||||
OpenClaw operator for Kubernetes — CRDs, controller, and Helm chart for running Scobleclaw agents on K8s
|
||||
OpenClaw operator for Kubernetes.
|
||||
|
||||
## What it does
|
||||
|
||||
Kubeclaw runs Scobleclaw agents as Kubernetes workloads. It provides:
|
||||
|
||||
- **CRDs** for declaring agents, tool bindings, and judge policies as K8s resources
|
||||
- **Controller** that reconciles desired state → running pods with proper config injection
|
||||
- **Agent Judge integration** as a K8s admission webhook for per-tool authorization
|
||||
- **Helm chart** for easy deployment
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ Kubeclaw Controller Manager │
|
||||
│ │
|
||||
│ ┌─────────┐ ┌──────────┐ ┌───────────┐ │
|
||||
│ │ Agent │ │ Agent │ │ Judge │ │
|
||||
│ │ Reconciler│ │Group │ │ Webhook │ │
|
||||
│ │ │ │ Reconciler│ │ Handler │ │
|
||||
│ └────┬────┘ └────┬─────┘ └─────┬─────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌────▼────┐ ┌────▼─────┐ ┌────▼─────┐ │
|
||||
│ │ ConfigMap│ │ Secret │ │ Validating│ │
|
||||
│ │ Generator│ │ Generator│ │ Admission │ │
|
||||
│ └─────────┘ └──────────┘ └───────────┘ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## CRDs
|
||||
|
||||
### Agent
|
||||
Defines a single Scobleclaw agent deployment.
|
||||
|
||||
```yaml
|
||||
apiVersion: scobleclaw.ai/v1alpha1
|
||||
kind: Agent
|
||||
metadata:
|
||||
name: marcus-chief-of-staff
|
||||
spec:
|
||||
model: deepseek-v4-pro:cloud
|
||||
workspace:
|
||||
configMapRef: marcus-workspace
|
||||
channels:
|
||||
- discord:
|
||||
botTokenSecretRef:
|
||||
name: discord-bot-token
|
||||
key: token
|
||||
judge:
|
||||
enabled: true
|
||||
model: deepseek-v4-pro:cloud
|
||||
shadowMode: false
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
```
|
||||
|
||||
### AgentGroup
|
||||
Manages a group of related agents (e.g., all Scobleclaw departments).
|
||||
|
||||
### JudgePolicy
|
||||
Defines authorization policies for the Agent Judge admission webhook.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install CRDs
|
||||
make install
|
||||
|
||||
# Run controller locally
|
||||
make run
|
||||
|
||||
# Deploy to cluster
|
||||
helm install kubeclaw ./charts/kubeclaw
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Generate CRD manifests and client code
|
||||
make generate
|
||||
|
||||
# Run tests
|
||||
make test
|
||||
|
||||
# Build manager binary
|
||||
make build
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
191
api/v1alpha1/agent_types.go
Normal file
191
api/v1alpha1/agent_types.go
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
Copyright 2025 Scott Scoble.
|
||||
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// AgentSpec defines the desired state of an Agent.
|
||||
type AgentSpec struct {
|
||||
// Model is the LLM model identifier (e.g., "deepseek-v4-pro:cloud").
|
||||
Model string `json:"model"`
|
||||
|
||||
// Thinking is the thinking level override (e.g., "off", "low", "high").
|
||||
// +optional
|
||||
Thinking string `json:"thinking,omitempty"`
|
||||
|
||||
// Workspace configures the agent workspace volume and config.
|
||||
Workspace AgentWorkspace `json:"workspace"`
|
||||
|
||||
// Channels configures the communication channels for this agent.
|
||||
// +optional
|
||||
Channels []AgentChannel `json:"channels,omitempty"`
|
||||
|
||||
// Judge configures the Agent Judge authorization layer.
|
||||
// +optional
|
||||
Judge AgentJudgeConfig `json:"judge,omitempty"`
|
||||
|
||||
// Resources defines compute resource requirements.
|
||||
// +optional
|
||||
Resources ResourceRequirements `json:"resources,omitempty"`
|
||||
|
||||
// Image is the container image to run. Defaults to the Kubeclaw agent runner.
|
||||
// +optional
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// Replicas is the number of agent instances. Defaults to 1.
|
||||
// +optional
|
||||
Replicas *int32 `json:"replicas,omitempty"`
|
||||
|
||||
// AgentID is the OpenClaw agent identifier (e.g., "main", "engineering").
|
||||
AgentID string `json:"agentId"`
|
||||
}
|
||||
|
||||
// AgentWorkspace configures the workspace for the agent.
|
||||
type AgentWorkspace struct {
|
||||
// ConfigMapRef references a ConfigMap containing agent config files.
|
||||
ConfigMapRef string `json:"configMapRef"`
|
||||
|
||||
// SecretRefs lists Secrets containing sensitive agent data (API keys, tokens).
|
||||
// +optional
|
||||
SecretRefs []string `json:"secretRefs,omitempty"`
|
||||
|
||||
// PVCName references an optional persistent volume for workspace data.
|
||||
// +optional
|
||||
PVCName string `json:"pvcName,omitempty"`
|
||||
}
|
||||
|
||||
// AgentChannel configures a communication channel binding.
|
||||
type AgentChannel struct {
|
||||
// Type is the channel type (e.g., "discord", "slack", "telegram").
|
||||
Type string `json:"type"`
|
||||
|
||||
// BotTokenSecretRef references a Secret key containing the bot token.
|
||||
BotTokenSecretRef SecretKeyRef `json:"botTokenSecretRef"`
|
||||
|
||||
// ChannelIDs is the list of channel IDs this agent should listen to.
|
||||
// +optional
|
||||
ChannelIDs []string `json:"channelIds,omitempty"`
|
||||
|
||||
// Enabled controls whether this channel is active.
|
||||
// +optional
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// SecretKeyRef references a key in a Kubernetes Secret.
|
||||
type SecretKeyRef struct {
|
||||
// Name of the Secret.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Key within the Secret.
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// AgentJudgeConfig configures the Agent Judge authorization layer.
|
||||
type AgentJudgeConfig struct {
|
||||
// Enabled controls whether the judge is active.
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Model is the judge LLM model identifier.
|
||||
Model string `json:"model"`
|
||||
|
||||
// ShadowMode runs the judge in shadow mode (logs but doesn't enforce).
|
||||
// +optional
|
||||
ShadowMode bool `json:"shadowMode,omitempty"`
|
||||
|
||||
// Tiers configures tool classification tiers.
|
||||
// +optional
|
||||
Tiers JudgeTiers `json:"tiers,omitempty"`
|
||||
|
||||
// MaxClarifyRetries is the maximum number of CLARIFY rounds before auto-reject.
|
||||
// +optional
|
||||
MaxClarifyRetries int `json:"maxClarifyRetries,omitempty"`
|
||||
|
||||
// AuditDir is the directory for judge audit logs (inside the container).
|
||||
// +optional
|
||||
AuditDir string `json:"auditDir,omitempty"`
|
||||
}
|
||||
|
||||
// JudgeTiers configures tool classification into risk tiers.
|
||||
type JudgeTiers struct {
|
||||
// NoJudge tools are passed through without judge review.
|
||||
// +optional
|
||||
NoJudge []string `json:"noJudge,omitempty"`
|
||||
|
||||
// LightweightApproval tools get pattern-checked and logged.
|
||||
// +optional
|
||||
LightweightApproval []string `json:"lightweightApproval,omitempty"`
|
||||
|
||||
// FullJudgeReview tools require full LLM judge evaluation.
|
||||
// +optional
|
||||
FullJudgeReview []string `json:"fullJudgeReview,omitempty"`
|
||||
|
||||
// HumanOnly tools always require human approval.
|
||||
// +optional
|
||||
HumanOnly []string `json:"humanOnly,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceRequirements mirrors K8s resource requirements.
|
||||
type ResourceRequirements struct {
|
||||
// Requests are the minimum required resources.
|
||||
// +optional
|
||||
Requests map[string]string `json:"requests,omitempty"`
|
||||
|
||||
// Limits are the maximum allowed resources.
|
||||
// +optional
|
||||
Limits map[string]string `json:"limits,omitempty"`
|
||||
}
|
||||
|
||||
// AgentStatus defines the observed state of an Agent.
|
||||
type AgentStatus struct {
|
||||
// Phase is the current phase of the agent deployment.
|
||||
// +optional
|
||||
Phase string `json:"phase,omitempty"`
|
||||
|
||||
// ReadyReplicas is the number of ready pod replicas.
|
||||
// +optional
|
||||
ReadyReplicas int32 `json:"readyReplicas,omitempty"`
|
||||
|
||||
// Conditions holds the conditions for this agent.
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
|
||||
// LastJudgeAudit is the timestamp of the last judge audit entry.
|
||||
// +optional
|
||||
LastJudgeAudit string `json:"lastJudgeAudit,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:scope=Namespaced
|
||||
// +kubebuilder:printcolumn:name="Model",type=string,JSONPath=`.spec.model`
|
||||
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
|
||||
// +kubebuilder:printcolumn:name="Ready",type=integer,JSONPath=`.status.readyReplicas`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
|
||||
// Agent is the Schema for the agents API.
|
||||
type Agent struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec AgentSpec `json:"spec,omitempty"`
|
||||
Status AgentStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// AgentList contains a list of Agent.
|
||||
type AgentList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []Agent `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&Agent{}, &AgentList{})
|
||||
}
|
||||
112
api/v1alpha1/agentgroup_types.go
Normal file
112
api/v1alpha1/agentgroup_types.go
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright 2025 Scott Scoble.
|
||||
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// AgentGroupSpec defines the desired state of an AgentGroup.
|
||||
type AgentGroupSpec struct {
|
||||
// Agents lists the agents in this group.
|
||||
Agents []AgentGroupMember `json:"agents"`
|
||||
|
||||
// SharedWorkspace references a ConfigMap with shared workspace config.
|
||||
// +optional
|
||||
SharedWorkspaceConfigMap string `json:"sharedWorkspaceConfigMap,omitempty"`
|
||||
|
||||
// SharedSecrets references Secrets shared by all agents in the group.
|
||||
// +optional
|
||||
SharedSecrets []string `json:"sharedSecrets,omitempty"`
|
||||
|
||||
// JudgePolicyRef references a JudgePolicy to apply to all agents in this group.
|
||||
// +optional
|
||||
JudgePolicyRef string `json:"judgePolicyRef,omitempty"`
|
||||
|
||||
// NetworkPolicy controls inter-agent communication.
|
||||
// +optional
|
||||
NetworkPolicy NetworkPolicySpec `json:"networkPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// AgentGroupMember defines a member of an AgentGroup.
|
||||
type AgentGroupMember struct {
|
||||
// Name is the Agent resource name.
|
||||
Name string `json:"name"`
|
||||
|
||||
// AgentID is the OpenClaw agent identifier.
|
||||
AgentID string `json:"agentId"`
|
||||
|
||||
// Model overrides the default model for this agent.
|
||||
// +optional
|
||||
Model string `json:"model,omitempty"`
|
||||
|
||||
// Channels lists the channels this specific agent should bind to.
|
||||
// +optional
|
||||
Channels []AgentChannel `json:"channels,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkPolicySpec controls network access between agents.
|
||||
type NetworkPolicySpec struct {
|
||||
// AllowInterAgent controls whether agents can communicate with each other.
|
||||
AllowInterAgent bool `json:"allowInterAgent"`
|
||||
|
||||
// AllowEgress controls outbound network access.
|
||||
AllowEgress bool `json:"allowEgress"`
|
||||
|
||||
// AllowedHosts restricts egress to specific hosts.
|
||||
// +optional
|
||||
AllowedHosts []string `json:"allowedHosts,omitempty"`
|
||||
}
|
||||
|
||||
// AgentGroupStatus defines the observed state of an AgentGroup.
|
||||
type AgentGroupStatus struct {
|
||||
// ReadyAgents is the count of agents with ready pods.
|
||||
// +optional
|
||||
ReadyAgents int `json:"readyAgents,omitempty"`
|
||||
|
||||
// TotalAgents is the total count of agents in the group.
|
||||
// +optional
|
||||
TotalAgents int `json:"totalAgents,omitempty"`
|
||||
|
||||
// Phase is the overall phase of the agent group.
|
||||
// +optional
|
||||
Phase string `json:"phase,omitempty"`
|
||||
|
||||
// Conditions holds the conditions for this agent group.
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:scope=Namespaced
|
||||
// +kubebuilder:printcolumn:name="Ready",type=integer,JSONPath=`.status.readyAgents`
|
||||
// +kubebuilder:printcolumn:name="Total",type=integer,JSONPath=`.status.totalAgents`
|
||||
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
|
||||
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||
|
||||
// AgentGroup is the Schema for the agentgroups API.
|
||||
type AgentGroup struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec AgentGroupSpec `json:"spec,omitempty"`
|
||||
Status AgentGroupStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// AgentGroupList contains a list of AgentGroup.
|
||||
type AgentGroupList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []AgentGroup `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&AgentGroup{}, &AgentGroupList{})
|
||||
}
|
||||
25
api/v1alpha1/groupversion_info.go
Normal file
25
api/v1alpha1/groupversion_info.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright 2025 Scott Scoble.
|
||||
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Package v1alpha1 contains API Schema definitions for the scobleclaw v1alpha1 API group.
|
||||
// +groupName=scobleclaw.ai
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
GroupVersion = schema.GroupVersion{
|
||||
Group: "scobleclaw.ai",
|
||||
Version: "v1alpha1",
|
||||
}
|
||||
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
105
api/v1alpha1/judgepolicy_types.go
Normal file
105
api/v1alpha1/judgepolicy_types.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright 2025 Scott Scoble.
|
||||
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// JudgePolicySpec defines the desired state of a JudgePolicy.
|
||||
type JudgePolicySpec struct {
|
||||
// Enabled controls whether this policy is active.
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// ShadowMode runs the judge in shadow mode (logs but doesn't enforce).
|
||||
ShadowMode bool `json:"shadowMode"`
|
||||
|
||||
// JudgeModel is the LLM model used for judging.
|
||||
JudgeModel string `json:"judgeModel"`
|
||||
|
||||
// JudgeProvider is the LLM provider (e.g., "ollama", "openai").
|
||||
JudgeProvider string `json:"judgeProvider"`
|
||||
|
||||
// DefaultTiers sets the default tool classification.
|
||||
DefaultTiers JudgeTiers `json:"defaultTiers"`
|
||||
|
||||
// Overrides are per-agent or per-namespace tier overrides.
|
||||
// +optional
|
||||
Overrides []JudgePolicyOverride `json:"overrides,omitempty"`
|
||||
|
||||
// HumanEscalation configures how human escalation works.
|
||||
// +optional
|
||||
HumanEscalation HumanEscalationConfig `json:"humanEscalation,omitempty"`
|
||||
}
|
||||
|
||||
// JudgePolicyOverride allows per-agent or per-namespace tier overrides.
|
||||
type JudgePolicyOverride struct {
|
||||
// MatchAgentID matches agents by their agentId.
|
||||
// +optional
|
||||
MatchAgentID string `json:"matchAgentId,omitempty"`
|
||||
|
||||
// MatchNamespace matches agents in a specific namespace.
|
||||
// +optional
|
||||
MatchNamespace string `json:"matchNamespace,omitempty"`
|
||||
|
||||
// Tiers overrides the default tier classification for matching agents.
|
||||
Tiers JudgeTiers `json:"tiers"`
|
||||
}
|
||||
|
||||
// HumanEscalationConfig configures how human escalation works.
|
||||
type HumanEscalationConfig struct {
|
||||
// Channel is the notification channel (e.g., "discord", "slack").
|
||||
Channel string `json:"channel"`
|
||||
|
||||
// ChannelID is the specific channel/room ID for notifications.
|
||||
ChannelID string `json:"channelId"`
|
||||
|
||||
// TimeoutMs is how long to wait for human response before auto-deny.
|
||||
// +optional
|
||||
TimeoutMs int `json:"timeoutMs,omitempty"`
|
||||
}
|
||||
|
||||
// JudgePolicyStatus defines the observed state of a JudgePolicy.
|
||||
type JudgePolicyStatus struct {
|
||||
// ActiveAgents is the count of agents currently using this policy.
|
||||
// +optional
|
||||
ActiveAgents int `json:"activeAgents,omitempty"`
|
||||
|
||||
// TotalVerdicts is the total number of verdicts rendered under this policy.
|
||||
// +optional
|
||||
TotalVerdicts int64 `json:"totalVerdicts,omitempty"`
|
||||
|
||||
// LastVerdictTime is the timestamp of the most recent verdict.
|
||||
// +optional
|
||||
LastVerdictTime string `json:"lastVerdictTime,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:scope=Cluster
|
||||
|
||||
// JudgePolicy is the Schema for the judgepolicies API.
|
||||
type JudgePolicy struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec JudgePolicySpec `json:"spec,omitempty"`
|
||||
Status JudgePolicyStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// JudgePolicyList contains a list of JudgePolicy.
|
||||
type JudgePolicyList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []JudgePolicy `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&JudgePolicy{}, &JudgePolicyList{})
|
||||
}
|
||||
14
go.mod
Normal file
14
go.mod
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
module github.com/sscoble/kubeclaw
|
||||
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/onsi/ginkgo/v2 v2.23.3
|
||||
github.com/onsi/gomega v1.37.0
|
||||
k8s.io/api v0.33.0
|
||||
k8s.io/apiextensions-apiserver v0.33.0
|
||||
k8s.io/apimachinery v0.33.0
|
||||
k8s.io/client-go v0.33.0
|
||||
sigs.k8s.io/controller-runtime v0.20.4
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue