Both child CRDs resolve their own teamRef -> TerdutTeam.status via the new
shared resolveTeamAndClient helper (childref.go), never chaining up to
TerdutServer (DESIGN.md §5) -- TerdutTeam.status.serverEndpoint, added in
this same stage, is what makes that literally true.
TerdutEscalationRule: one PUT /api/teams/{id}/escalation per reconcile
(an upsert server-side, confirmed against source), resolving each "user"
target's username to a user_id via GET /api/users first and reporting
Ready: False, reason: UnknownUser if it doesn't resolve. No DELETE exists
for this resource, so its delete path PUTs an empty policy as the closest
available undo.
TerdutDeadmanSwitch: real create/update-in-place/delete, using
terdut-server v0.33.0's PUT (added specifically for this operator). No
unique-name constraint server-side, so idempotent-create here is
GET-list-and-match-by-name rather than adopt-on-409.
Extends tdclient with User/GetUserByUsername, the escalation request types
+ SetEscalation, and DeadmanSwitch + its CRUD methods. Also folds
ConditionTeamReady into the single shared ConditionReady constant, since
both were literally "Ready" and Stage 3 would otherwise have needed a
third same-valued constant.
internal/controller/terdutserver_controller_test.go's fakeTerdutServer
grows GET /api/users, PUT .../escalation, and the full dead man's switch
collection/item routes, replacing the old parseTeamPath/handleTeamByID
pair with a more general parseTeamSubPath/handleTeamSubPath dispatcher
that still covers every existing Stage 1/2 route unchanged.
make fmt lint test build all clean; envtest coverage for
internal/controller: 50.5% -> 71.7%.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// TerdutDeadmanSwitchSpec defines the desired state of TerdutDeadmanSwitch.
|
||||
//
|
||||
// One per switch (DESIGN.md §4.4). Reconciled with real update-in-place
|
||||
// (terdut-server v0.33.0 added PUT specifically for this, §5) -- but with no
|
||||
// unique-name constraint server-side, idempotent-create here means
|
||||
// GET-list-and-match-by-name, not adopt-on-409.
|
||||
type TerdutDeadmanSwitchSpec struct {
|
||||
// +required
|
||||
TeamRef TerdutTeamRef `json:"teamRef"`
|
||||
|
||||
// name is optional, same as the API: left empty, terdut-server derives
|
||||
// it from matcher's own canonical form, and that's what the
|
||||
// idempotent-create lookup matches against too.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// matcher names the alerts this switch watches, e.g.
|
||||
// "alertname=Watchdog,cluster=prod". One matcher per switch -- add
|
||||
// another TerdutDeadmanSwitch instead of separating with ";"
|
||||
// (terdut-server's own restriction, mirrored here so a bad spec is
|
||||
// rejected at apply time).
|
||||
// +required
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
// +kubebuilder:validation:XValidation:rule="!self.contains(';')",message="one matcher per switch: add another TerdutDeadmanSwitch instead of separating with ;"
|
||||
Matcher string `json:"matcher"`
|
||||
|
||||
// timeout is a Go duration string, e.g. "15m".
|
||||
// +required
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Timeout string `json:"timeout"`
|
||||
|
||||
// +kubebuilder:validation:Enum=critical;error;warning;info
|
||||
// +kubebuilder:default=critical
|
||||
// +optional
|
||||
Severity string `json:"severity,omitempty"`
|
||||
}
|
||||
|
||||
// TerdutDeadmanSwitchStatus defines the observed state of TerdutDeadmanSwitch.
|
||||
type TerdutDeadmanSwitchStatus struct {
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
|
||||
// switchID is the server-side id.
|
||||
// +optional
|
||||
SwitchID int64 `json:"switchID,omitempty"`
|
||||
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="Team",type=string,JSONPath=`.spec.teamRef.name`
|
||||
// +kubebuilder:printcolumn:name="SwitchID",type=integer,JSONPath=`.status.switchID`
|
||||
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
|
||||
// +kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].reason`
|
||||
|
||||
// TerdutDeadmanSwitch is the Schema for the terdutdeadmanswitches API
|
||||
type TerdutDeadmanSwitch struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// metadata is a standard object metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||
|
||||
// spec defines the desired state of TerdutDeadmanSwitch
|
||||
// +required
|
||||
Spec TerdutDeadmanSwitchSpec `json:"spec"`
|
||||
|
||||
// status defines the observed state of TerdutDeadmanSwitch
|
||||
// +optional
|
||||
Status TerdutDeadmanSwitchStatus `json:"status,omitzero"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// TerdutDeadmanSwitchList contains a list of TerdutDeadmanSwitch
|
||||
type TerdutDeadmanSwitchList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitzero"`
|
||||
Items []TerdutDeadmanSwitch `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(func(s *runtime.Scheme) error {
|
||||
s.AddKnownTypes(SchemeGroupVersion, &TerdutDeadmanSwitch{}, &TerdutDeadmanSwitchList{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// TerdutTeamRef names the TerdutTeam this resource belongs to. Always
|
||||
// same-namespace as the CR itself (DESIGN.md §1: only TerdutTeam.spec.serverRef
|
||||
// crosses namespaces in v1) -- no namespace field, unlike TerdutServerRef.
|
||||
type TerdutTeamRef struct {
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// EscalationTargetKind is who one rung of the ladder pages.
|
||||
// +kubebuilder:validation:Enum=oncall;user
|
||||
type EscalationTargetKind string
|
||||
|
||||
const (
|
||||
EscalationTargetOncall EscalationTargetKind = "oncall"
|
||||
EscalationTargetUser EscalationTargetKind = "user"
|
||||
)
|
||||
|
||||
// EscalationTarget is one page within a level. username is required iff
|
||||
// kind is "user" (terdut-server's own validation, internal/api/escalation.go's
|
||||
// handleSetEscalation -- mirrored here as a CEL rule so a bad spec is
|
||||
// rejected at apply time, not discovered on the next failed PUT).
|
||||
// +kubebuilder:validation:XValidation:rule="self.kind != 'user' || has(self.username)",message="username is required when kind is user"
|
||||
// +kubebuilder:validation:XValidation:rule="self.kind != 'oncall' || !has(self.username)",message="username must not be set when kind is oncall"
|
||||
type EscalationTarget struct {
|
||||
// +required
|
||||
Kind EscalationTargetKind `json:"kind"`
|
||||
// +optional
|
||||
Username string `json:"username,omitempty"`
|
||||
}
|
||||
|
||||
// EscalationLevel is one rung of the ladder: how long to wait, and who to
|
||||
// page if nobody's acknowledged by then.
|
||||
type EscalationLevel struct {
|
||||
// timeout is a Go duration string, e.g. "5m".
|
||||
// +required
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
Timeout string `json:"timeout"`
|
||||
|
||||
// +required
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
Targets []EscalationTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// TerdutEscalationRuleSpec defines the desired state of TerdutEscalationRule.
|
||||
//
|
||||
// One per team (DESIGN.md §4.3) -- terdut-server models a policy as one row
|
||||
// with an owned list of levels, reconciled with a single whole-policy PUT.
|
||||
// Not enforced at admission if two CRs name the same team (no webhooks in
|
||||
// v1, §1); they would simply clobber each other every reconcile.
|
||||
type TerdutEscalationRuleSpec struct {
|
||||
// +required
|
||||
TeamRef TerdutTeamRef `json:"teamRef"`
|
||||
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
// +kubebuilder:validation:Maximum=10
|
||||
// +optional
|
||||
RepeatCount int64 `json:"repeatCount,omitempty"`
|
||||
|
||||
// +optional
|
||||
FallbackTopic string `json:"fallbackTopic,omitempty"`
|
||||
|
||||
// +required
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
Levels []EscalationLevel `json:"levels"`
|
||||
}
|
||||
|
||||
// Condition reasons shared by TerdutEscalationRule and TerdutDeadmanSwitch
|
||||
// (both resolve a teamRef the same way, DESIGN.md §5).
|
||||
const (
|
||||
// ReasonTeamRefNotFound: spec.teamRef names no TerdutTeam (yet).
|
||||
ReasonTeamRefNotFound = "TeamRefNotFound"
|
||||
// ReasonWaitingForTeam: the referenced TerdutTeam exists but isn't
|
||||
// Ready yet (no status.credentialsSecretRef to read).
|
||||
ReasonWaitingForTeam = "WaitingForTeam"
|
||||
// ReasonUnknownUser: an escalation target's username doesn't resolve to
|
||||
// any user server-side (TerdutEscalationRule only).
|
||||
ReasonUnknownUser = "UnknownUser"
|
||||
// ReasonChildAdopted: the happy path, shared by both child kinds.
|
||||
ReasonChildAdopted = "Adopted"
|
||||
)
|
||||
|
||||
// TerdutEscalationRuleStatus defines the observed state of TerdutEscalationRule.
|
||||
type TerdutEscalationRuleStatus struct {
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="Team",type=string,JSONPath=`.spec.teamRef.name`
|
||||
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
|
||||
// +kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].reason`
|
||||
|
||||
// TerdutEscalationRule is the Schema for the terdutescalationrules API
|
||||
type TerdutEscalationRule struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// metadata is a standard object metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||
|
||||
// spec defines the desired state of TerdutEscalationRule
|
||||
// +required
|
||||
Spec TerdutEscalationRuleSpec `json:"spec"`
|
||||
|
||||
// status defines the observed state of TerdutEscalationRule
|
||||
// +optional
|
||||
Status TerdutEscalationRuleStatus `json:"status,omitzero"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// TerdutEscalationRuleList contains a list of TerdutEscalationRule
|
||||
type TerdutEscalationRuleList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitzero"`
|
||||
Items []TerdutEscalationRule `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(func(s *runtime.Scheme) error {
|
||||
s.AddKnownTypes(SchemeGroupVersion, &TerdutEscalationRule{}, &TerdutEscalationRuleList{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -45,11 +45,6 @@ type TerdutTeamSpec struct {
|
||||
OIDC TerdutTeamOIDC `json:"oidc,omitempty"`
|
||||
}
|
||||
|
||||
// Condition types this controller sets on TerdutTeam.
|
||||
const (
|
||||
ConditionTeamReady = "Ready"
|
||||
)
|
||||
|
||||
// Condition reasons this controller sets.
|
||||
const (
|
||||
// ReasonServerRefNotFound: spec.serverRef names no TerdutServer (yet).
|
||||
@@ -85,6 +80,13 @@ type TerdutTeamStatus struct {
|
||||
// +optional
|
||||
CredentialsSecretRef *SecretKeyRef `json:"credentialsSecretRef,omitempty"`
|
||||
|
||||
// serverEndpoint is the resolved TerdutServer's base URL, resolved once
|
||||
// here so no child controller (TerdutEscalationRule, TerdutDeadmanSwitch,
|
||||
// TerdutAlertSource) ever needs its own RBAC on terdutservers just to
|
||||
// find out where to send a request (DESIGN.md §5).
|
||||
// +optional
|
||||
ServerEndpoint string `json:"serverEndpoint,omitempty"`
|
||||
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
}
|
||||
|
||||
@@ -85,6 +85,41 @@ func (in *DeadmanSpec) DeepCopy() *DeadmanSpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *EscalationLevel) DeepCopyInto(out *EscalationLevel) {
|
||||
*out = *in
|
||||
if in.Targets != nil {
|
||||
in, out := &in.Targets, &out.Targets
|
||||
*out = make([]EscalationTarget, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EscalationLevel.
|
||||
func (in *EscalationLevel) DeepCopy() *EscalationLevel {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EscalationLevel)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *EscalationTarget) DeepCopyInto(out *EscalationTarget) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EscalationTarget.
|
||||
func (in *EscalationTarget) DeepCopy() *EscalationTarget {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EscalationTarget)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageSpec) DeepCopyInto(out *ImageSpec) {
|
||||
*out = *in
|
||||
@@ -205,6 +240,207 @@ func (in *SweeperSpec) DeepCopy() *SweeperSpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutDeadmanSwitch) DeepCopyInto(out *TerdutDeadmanSwitch) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutDeadmanSwitch.
|
||||
func (in *TerdutDeadmanSwitch) DeepCopy() *TerdutDeadmanSwitch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutDeadmanSwitch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TerdutDeadmanSwitch) 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 *TerdutDeadmanSwitchList) DeepCopyInto(out *TerdutDeadmanSwitchList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]TerdutDeadmanSwitch, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutDeadmanSwitchList.
|
||||
func (in *TerdutDeadmanSwitchList) DeepCopy() *TerdutDeadmanSwitchList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutDeadmanSwitchList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TerdutDeadmanSwitchList) 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 *TerdutDeadmanSwitchSpec) DeepCopyInto(out *TerdutDeadmanSwitchSpec) {
|
||||
*out = *in
|
||||
out.TeamRef = in.TeamRef
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutDeadmanSwitchSpec.
|
||||
func (in *TerdutDeadmanSwitchSpec) DeepCopy() *TerdutDeadmanSwitchSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutDeadmanSwitchSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutDeadmanSwitchStatus) DeepCopyInto(out *TerdutDeadmanSwitchStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutDeadmanSwitchStatus.
|
||||
func (in *TerdutDeadmanSwitchStatus) DeepCopy() *TerdutDeadmanSwitchStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutDeadmanSwitchStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutEscalationRule) DeepCopyInto(out *TerdutEscalationRule) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutEscalationRule.
|
||||
func (in *TerdutEscalationRule) DeepCopy() *TerdutEscalationRule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutEscalationRule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TerdutEscalationRule) 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 *TerdutEscalationRuleList) DeepCopyInto(out *TerdutEscalationRuleList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]TerdutEscalationRule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutEscalationRuleList.
|
||||
func (in *TerdutEscalationRuleList) DeepCopy() *TerdutEscalationRuleList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutEscalationRuleList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *TerdutEscalationRuleList) 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 *TerdutEscalationRuleSpec) DeepCopyInto(out *TerdutEscalationRuleSpec) {
|
||||
*out = *in
|
||||
out.TeamRef = in.TeamRef
|
||||
if in.Levels != nil {
|
||||
in, out := &in.Levels, &out.Levels
|
||||
*out = make([]EscalationLevel, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutEscalationRuleSpec.
|
||||
func (in *TerdutEscalationRuleSpec) DeepCopy() *TerdutEscalationRuleSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutEscalationRuleSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutEscalationRuleStatus) DeepCopyInto(out *TerdutEscalationRuleStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutEscalationRuleStatus.
|
||||
func (in *TerdutEscalationRuleStatus) DeepCopy() *TerdutEscalationRuleStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutEscalationRuleStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutServer) DeepCopyInto(out *TerdutServer) {
|
||||
*out = *in
|
||||
@@ -403,6 +639,21 @@ func (in *TerdutTeamOIDC) DeepCopy() *TerdutTeamOIDC {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutTeamRef) DeepCopyInto(out *TerdutTeamRef) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TerdutTeamRef.
|
||||
func (in *TerdutTeamRef) DeepCopy() *TerdutTeamRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TerdutTeamRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TerdutTeamSpec) DeepCopyInto(out *TerdutTeamSpec) {
|
||||
*out = *in
|
||||
|
||||
Reference in New Issue
Block a user