Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
78 changes: 78 additions & 0 deletions api/v2/application_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,89 @@ type ApplicationSpec struct {
Jobs []batchv1.Job `json:"jobs,omitempty"`
CronJobs []batchv1.CronJob `json:"cronJobs,omitempty"`

// Triage declares the bounded diagnostic actions that may be requested for
// this application through TriageRun resources.
// +optional
Triage *ApplicationTriageSpec `json:"triage,omitempty"`

// HTTPRouteTemplate is the desired HTTPRoute spec. Nil means no HTTPRoute.
// +optional
HTTPRouteTemplate *HTTPRouteTemplateSpec `json:"httpRouteTemplate,omitempty"`
}

// ApplicationTriageSpec contains the shared diagnostic runner and the actions
// exposed by an Application. TriageRun selects actions by name. The default
// action runs the declared runner unchanged; named actions receive an explicit
// --action selector.
type ApplicationTriageSpec struct {
// ContainerName selects a container from the Application pod template. It
// may be omitted when the Application has exactly one container.
// +optional
ContainerName string `json:"containerName,omitempty"`

// Command replaces the selected container's entrypoint when non-empty.
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=64
// +optional
Command []string `json:"command,omitempty"`

// Args replaces the selected container's arguments when non-empty. For a
// named action, the controller appends "--action", the selected action name,
// and then that action's Args. The default action only appends its Args.
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=64
// +optional
Args []string `json:"args,omitempty"`

// Env adds or overrides environment variables inherited from the selected
// application container.
// +kubebuilder:validation:MaxItems=128
// +optional
Env []corev1.EnvVar `json:"env,omitempty"`

// Resources deliberately does not inherit the parent container's resource
// requirements. When omitted, the controller applies small bounded
// defaults suitable for diagnostics.
// +optional
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`

// TimeoutSeconds is the Job execution deadline. Zero selects the controller
// default.
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=3600
// +optional
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"`

// Actions lists the stable action names and metadata exposed to callers.
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=16
// +listType=map
// +listMapKey=name
Actions []TriageActionSpec `json:"actions"`
}

// TriageActionSpec describes one action exposed by the shared diagnostic
// runner. Execution identity and resource settings remain on the parent
// ApplicationTriageSpec so every action uses the same bounded runtime.
type TriageActionSpec struct {
// Name is the stable identifier selected by TriageRun. "default" invokes the
// shared runner without an action selector; every other name is passed as
// "--action <name>".
Name TriageActionName `json:"name"`

// Description is human-readable help shown by clients such as Watchtower.
// +kubebuilder:validation:MaxLength=512
// +optional
Description string `json:"description,omitempty"`

// Args are appended after the optional action selector when starting the
// diagnostic runner. They are suitable for action-specific flags, not
// executable paths.
// +kubebuilder:validation:MaxItems=32
// +optional
Args []string `json:"args,omitempty"`
}

// HTTPRouteTemplateSpec contains the fields needed to build a Gateway API HTTPRoute.
type HTTPRouteTemplateSpec struct {
ParentRefs []gatewayv1.ParentReference `json:"parentRefs"`
Expand Down
69 changes: 69 additions & 0 deletions api/v2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/wandb/operator/pkg/wandb/spec/channel/deployer"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/discovery"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client/config"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"

Expand Down Expand Up @@ -339,6 +340,22 @@ func main() {
os.Exit(1)
}

kubernetesClient, err := kubernetes.NewForConfig(mgr.GetConfig())
if err != nil {
setupLog.Error(err, "unable to create Kubernetes client", "controller", "TriageRun")
os.Exit(1)
}
if err = (&controller.TriageRunReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
PodLogs: &controller.KubernetesTriagePodLogReader{
CoreV1: kubernetesClient.CoreV1(),
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TriageRun")
os.Exit(1)
}

if enableWebhooks && enableV2 {
if err := webhookv2.SetupApplicationWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Application")
Expand Down
164 changes: 164 additions & 0 deletions config/crd/bases/apps.wandb.com_applications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12801,6 +12801,170 @@ spec:
type:
type: string
type: object
triage:
properties:
actions:
items:
properties:
args:
items:
type: string
maxItems: 32
type: array
description:
maxLength: 512
type: string
name:
minLength: 1
type: string
required:
- name
type: object
maxItems: 16
minItems: 1
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
args:
items:
type: string
maxItems: 64
minItems: 1
type: array
command:
items:
type: string
maxItems: 64
minItems: 1
type: array
containerName:
type: string
env:
items:
properties:
name:
type: string
value:
type: string
valueFrom:
properties:
configMapKeyRef:
properties:
key:
type: string
name:
default: ""
type: string
optional:
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
fieldRef:
properties:
apiVersion:
type: string
fieldPath:
type: string
required:
- fieldPath
type: object
x-kubernetes-map-type: atomic
fileKeyRef:
properties:
key:
type: string
optional:
default: false
type: boolean
path:
type: string
volumeName:
type: string
required:
- key
- path
- volumeName
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
properties:
containerName:
type: string
divisor:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
resource:
type: string
required:
- resource
type: object
x-kubernetes-map-type: atomic
secretKeyRef:
properties:
key:
type: string
name:
default: ""
type: string
optional:
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
type: object
required:
- name
type: object
maxItems: 128
type: array
resources:
properties:
claims:
items:
properties:
name:
type: string
request:
type: string
required:
- name
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
limits:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
requests:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
type: object
timeoutSeconds:
format: int64
maximum: 3600
minimum: 1
type: integer
required:
- actions
type: object
volumeClaimTemplates:
items:
properties:
Expand Down
Loading
Loading