Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d6e3712
chore: remove 2 v1alpha1 metrics (#352)
weng271190436 Dec 1, 2025
5832681
feat: make hub statefulset work by stripping some properties from gen…
weng271190436 Dec 1, 2025
d5fcf88
feat: publish image to ghcr with tag (#353)
weng271190436 Dec 1, 2025
0376725
chore: bump controller runtime version to v0.22.x (#354)
michaelawyu Dec 2, 2025
2e50010
feat: add beforeStageTasks to stagedUpdateRun (#328)
britaniar Dec 2, 2025
2b1e9a7
feat: implement initialize and execute states within update run (#346)
britaniar Dec 3, 2025
83bc664
fix: use the uncached client when validating override (#351)
zhiying-lin Dec 4, 2025
ba884f5
fix: fix the update run states (#363)
britaniar Dec 4, 2025
3820bb0
feat: trim work object status if the object exceeds size limit (#357)
michaelawyu Dec 5, 2025
efedeca
fix: add label to update run approval object to distinguish between b…
britaniar Dec 7, 2025
1753dfb
chore: bump step-security/harden-runner from 2.13.2 to 2.13.3 (#372)
dependabot[bot] Dec 8, 2025
95016ce
chore: bump actions/checkout from 6.0.0 to 6.0.1 (#371)
dependabot[bot] Dec 8, 2025
0f449dc
test: fix the TestPickBindingsToRoll ut (#365)
zhiying-lin Dec 8, 2025
58b6de2
fix: fix the validation webhook (#359)
ryanzhang-oss Dec 8, 2025
6862d17
fix: continue to propagate PVC when workload is not enabled (#368)
ryanzhang-oss Dec 8, 2025
00e6b82
Merge remote-tracking branch 'origin/main' into weiweng/backport-2025…
Dec 8, 2025
5730600
Revert "feat: publish image to ghcr with tag (#353)"
Dec 8, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/chart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.0
- uses: actions/checkout@v6.0.1
with:
submodules: true
fetch-depth: 0
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Check out code into the Go module directory
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1

- name: Set up Ginkgo CLI
run: |
Expand Down Expand Up @@ -90,7 +90,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Check out code into the Go module directory
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1

- name: Move Docker data directory to /mnt
# The default storage device on GitHub-hosted runners is running low during e2e tests.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/code-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Checkout
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1
with:
submodules: true

Expand All @@ -64,7 +64,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Check out code into the Go module directory
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1

- name: golangci-lint
run: make lint
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
with:
egress-policy: audit

- uses: actions/checkout@c2d88d3ecc89a9ef08eebf45d9637801dcee7eb5 # v4.1.7
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
- uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # master
with:
check_filenames: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/markdown-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.0
- uses: actions/checkout@v6.0.1
- uses: tcort/github-action-markdown-link-check@v1
with:
# this will only show errors in the output
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/trivy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Checkout code
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1

- name: Login to ${{ env.REGISTRY }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/upgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Check out code into the Go module directory
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1
with:
# Fetch the history of all branches and tags.
# This is needed for the test suite to switch between releases.
Expand Down Expand Up @@ -146,7 +146,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Check out code into the Go module directory
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1
with:
# Fetch the history of all branches and tags.
# This is needed for the test suite to switch between releases.
Expand Down Expand Up @@ -248,7 +248,7 @@ jobs:
go-version: ${{ env.GO_VERSION }}

- name: Check out code into the Go module directory
uses: actions/checkout@v6.0.0
uses: actions/checkout@v6.0.1
with:
# Fetch the history of all branches and tags.
# This is needed for the test suite to switch between releases.
Expand Down
18 changes: 15 additions & 3 deletions apis/placement/v1beta1/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ const (
UpdateRunFinalizer = FleetPrefix + "stagedupdaterun-finalizer"

// TargetUpdateRunLabel indicates the target update run on a staged run related object.
TargetUpdateRunLabel = FleetPrefix + "targetupdaterun"
TargetUpdateRunLabel = FleetPrefix + "targetUpdateRun"

// TaskTypeLabel indicates the task type (before-stage or after-stage) on a staged run related object.
TaskTypeLabel = FleetPrefix + "taskType"

// UpdateRunDeleteStageName is the name of delete stage in the staged update run.
UpdateRunDeleteStageName = FleetPrefix + "deleteStage"
Expand All @@ -167,8 +170,17 @@ const (
// TargetUpdatingStageNameLabel indicates the updating stage name on a staged run related object.
TargetUpdatingStageNameLabel = FleetPrefix + "targetUpdatingStage"

// ApprovalTaskNameFmt is the format of the approval task name.
ApprovalTaskNameFmt = "%s-%s"
// BeforeStageTaskLabelValue is the before stage task label value.
BeforeStageTaskLabelValue = "beforeStage"

// AfterStageTaskLabelValue is the after stage task label value.
AfterStageTaskLabelValue = "afterStage"

// BeforeStageApprovalTaskNameFmt is the format of the before stage approval task name.
BeforeStageApprovalTaskNameFmt = "%s-before-%s"

// AfterStageApprovalTaskNameFmt is the format of the after stage approval task name.
AfterStageApprovalTaskNameFmt = "%s-after-%s"
)

var (
Expand Down
38 changes: 17 additions & 21 deletions apis/placement/v1beta1/stageupdate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,29 +152,25 @@ func (c *ClusterStagedUpdateRun) SetUpdateRunStatus(status UpdateRunStatus) {
type State string

const (
// StateNotStarted describes user intent to initialize but not execute the update run.
// StateInitialize describes user intent to initialize but not run the update run.
// This is the default state when an update run is created.
StateNotStarted State = "Initialize"
// Users can subsequently set the state to Run.
StateInitialize State = "Initialize"

// StateStarted describes user intent to execute (or resume execution if paused).
// Users can subsequently set the state to Pause or Abandon.
StateStarted State = "Execute"
// StateRun describes user intent to execute (or resume execution if stopped).
// Users can subsequently set the state to Stop.
StateRun State = "Run"

// StateStopped describes user intent to pause the update run.
// Users can subsequently set the state to Execute or Abandon.
StateStopped State = "Pause"

// StateAbandoned describes user intent to abandon the update run.
// This is a terminal state; once set, it cannot be changed.
StateAbandoned State = "Abandon"
// StateStop describes user intent to stop the update run.
// Users can subsequently set the state to Run.
StateStop State = "Stop"
)

// UpdateRunSpec defines the desired rollout strategy and the snapshot indices of the resources to be updated.
// It specifies a stage-by-stage update process across selected clusters for the given ResourcePlacement object.
// +kubebuilder:validation:XValidation:rule="!(has(oldSelf.state) && oldSelf.state == 'Initialize' && self.state == 'Pause')",message="invalid state transition: cannot transition from Initialize to Pause"
// +kubebuilder:validation:XValidation:rule="!(has(oldSelf.state) && oldSelf.state == 'Execute' && self.state == 'Initialize')",message="invalid state transition: cannot transition from Execute to Initialize"
// +kubebuilder:validation:XValidation:rule="!(has(oldSelf.state) && oldSelf.state == 'Pause' && self.state == 'Initialize')",message="invalid state transition: cannot transition from Pause to Initialize"
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.state) || oldSelf.state != 'Abandon' || self.state == 'Abandon'",message="invalid state transition: Abandon is a terminal state and cannot transition to any other state"
// +kubebuilder:validation:XValidation:rule="!(has(oldSelf.state) && oldSelf.state == 'Initialize' && self.state == 'Stop')",message="invalid state transition: cannot transition from Initialize to Stop"
// +kubebuilder:validation:XValidation:rule="!(has(oldSelf.state) && oldSelf.state == 'Run' && self.state == 'Initialize')",message="invalid state transition: cannot transition from Run to Initialize"
// +kubebuilder:validation:XValidation:rule="!(has(oldSelf.state) && oldSelf.state == 'Stop' && self.state == 'Initialize')",message="invalid state transition: cannot transition from Stop to Initialize"
type UpdateRunSpec struct {
// PlacementName is the name of placement that this update run is applied to.
// There can be multiple active update runs for each placement, but
Expand All @@ -200,12 +196,11 @@ type UpdateRunSpec struct {

// State indicates the desired state of the update run.
// Initialize: The update run should be initialized but execution should not start (default).
// Execute: The update run should execute or resume execution.
// Pause: The update run should pause execution.
// Abandon: The update run should be abandoned and terminated.
// Run: The update run should execute or resume execution.
// Stop: The update run should stop execution.
// +kubebuilder:validation:Optional
// +kubebuilder:default=Initialize
// +kubebuilder:validation:Enum=Initialize;Execute;Pause;Abandon
// +kubebuilder:validation:Enum=Initialize;Run;Stop
State State `json:"state,omitempty"`
}

Expand Down Expand Up @@ -426,7 +421,6 @@ const (
// Its condition status can be one of the following:
// - "True": The staged update run is initialized successfully.
// - "False": The staged update run encountered an error during initialization and aborted.
// - "Unknown": The staged update run initialization has started.
StagedUpdateRunConditionInitialized StagedUpdateRunConditionType = "Initialized"

// StagedUpdateRunConditionProgressing indicates whether the staged update run is making progress.
Expand Down Expand Up @@ -679,6 +673,7 @@ type ApprovalRequestObjList interface {
// - `TargetUpdateRun`: Points to the cluster staged update run that this approval request is for.
// - `TargetStage`: The name of the stage that this approval request is for.
// - `IsLatestUpdateRunApproval`: Indicates whether this approval request is the latest one related to this update run.
// - `TaskType`: Indicates whether this approval request is for the before or after stage task.
type ClusterApprovalRequest struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down Expand Up @@ -925,6 +920,7 @@ func (s *StagedUpdateStrategyList) GetUpdateStrategyObjs() []UpdateStrategyObj {
// - `TargetUpdateRun`: Points to the staged update run that this approval request is for.
// - `TargetStage`: The name of the stage that this approval request is for.
// - `IsLatestUpdateRunApproval`: Indicates whether this approval request is the latest one related to this update run.
// - `TaskType`: Indicates whether this approval request is for the before or after stage task.
type ApprovalRequest struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
4 changes: 4 additions & 0 deletions apis/placement/v1beta1/work_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ const (
// WorkConditionTypeDiffReported reports whether Fleet has successfully reported the
// configuration difference between the states in the hub cluster and a member cluster.
WorkConditionTypeDiffReported = "DiffReported"

// WorkConditionTypeStatusTrimmed reports whether the member agent has to trim
// the status data in the Work object due to size constraints.
WorkConditionTypeStatusTrimmed = "StatusTrimmed"
)

// This api is copied from https://github.com/kubernetes-sigs/work-api/blob/master/pkg/apis/v1alpha1/work_types.go.
Expand Down
8 changes: 5 additions & 3 deletions cmd/hubagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ func main() {

if opts.EnableWebhook {
whiteListedUsers := strings.Split(opts.WhiteListedUsers, ",")
if err := SetupWebhook(mgr, options.WebhookClientConnectionType(opts.WebhookClientConnectionType), opts.WebhookServiceName, whiteListedUsers, opts.EnableGuardRail, opts.EnableV1Beta1APIs, opts.DenyModifyMemberClusterLabels, opts.EnableWorkload); err != nil {
if err := SetupWebhook(mgr, options.WebhookClientConnectionType(opts.WebhookClientConnectionType), opts.WebhookServiceName, whiteListedUsers,
opts.EnableGuardRail, opts.EnableV1Beta1APIs, opts.DenyModifyMemberClusterLabels, opts.EnableWorkload, opts.NetworkingAgentsEnabled); err != nil {
klog.ErrorS(err, "unable to set up webhook")
exitWithErrorFunc()
}
Expand Down Expand Up @@ -201,7 +202,8 @@ func main() {
}

// SetupWebhook generates the webhook cert and then set up the webhook configurator.
func SetupWebhook(mgr manager.Manager, webhookClientConnectionType options.WebhookClientConnectionType, webhookServiceName string, whiteListedUsers []string, enableGuardRail, isFleetV1Beta1API bool, denyModifyMemberClusterLabels bool, enableWorkload bool) error {
func SetupWebhook(mgr manager.Manager, webhookClientConnectionType options.WebhookClientConnectionType, webhookServiceName string,
whiteListedUsers []string, enableGuardRail, isFleetV1Beta1API bool, denyModifyMemberClusterLabels bool, enableWorkload bool, networkingAgentsEnabled bool) error {
// Generate self-signed key and crt files in FleetWebhookCertDir for the webhook server to start.
w, err := webhook.NewWebhookConfig(mgr, webhookServiceName, FleetWebhookPort, &webhookClientConnectionType, FleetWebhookCertDir, enableGuardRail, denyModifyMemberClusterLabels, enableWorkload)
if err != nil {
Expand All @@ -212,7 +214,7 @@ func SetupWebhook(mgr manager.Manager, webhookClientConnectionType options.Webho
klog.ErrorS(err, "unable to add WebhookConfig")
return err
}
if err = webhook.AddToManager(mgr, whiteListedUsers, denyModifyMemberClusterLabels); err != nil {
if err = webhook.AddToManager(mgr, whiteListedUsers, denyModifyMemberClusterLabels, networkingAgentsEnabled); err != nil {
klog.ErrorS(err, "unable to register webhooks to the manager")
return err
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/hubagent/workload/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func SetupControllers(ctx context.Context, wg *sync.WaitGroup, mgr ctrl.Manager,
UncachedReader: mgr.GetAPIReader(),
ResourceSnapshotCreationMinimumInterval: opts.ResourceSnapshotCreationMinimumInterval,
ResourceChangesCollectionDuration: opts.ResourceChangesCollectionDuration,
EnableWorkload: opts.EnableWorkload,
}

rateLimiter := options.DefaultControllerRateLimiter(opts.RateLimiterOpts)
Expand Down Expand Up @@ -525,6 +526,7 @@ func SetupControllers(ctx context.Context, wg *sync.WaitGroup, mgr ctrl.Manager,
SkippedNamespaces: skippedNamespaces,
ConcurrentPlacementWorker: int(math.Ceil(float64(opts.MaxConcurrentClusterPlacement) / 10)),
ConcurrentResourceChangeWorker: opts.ConcurrentResourceChangeSyncs,
EnableWorkload: opts.EnableWorkload,
}

if err := mgr.Add(resourceChangeDetector); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ spec:
- `TargetUpdateRun`: Points to the staged update run that this approval request is for.
- `TargetStage`: The name of the stage that this approval request is for.
- `IsLatestUpdateRunApproval`: Indicates whether this approval request is the latest one related to this update run.
- `TaskType`: Indicates whether this approval request is for the before or after stage task.
properties:
apiVersion:
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ spec:
- `TargetUpdateRun`: Points to the cluster staged update run that this approval request is for.
- `TargetStage`: The name of the stage that this approval request is for.
- `IsLatestUpdateRunApproval`: Indicates whether this approval request is the latest one related to this update run.
- `TaskType`: Indicates whether this approval request is for the before or after stage task.
properties:
apiVersion:
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1189,36 +1189,28 @@ spec:
description: |-
State indicates the desired state of the update run.
Initialize: The update run should be initialized but execution should not start (default).
Execute: The update run should execute or resume execution.
Pause: The update run should pause execution.
Abandon: The update run should be abandoned and terminated.
Run: The update run should execute or resume execution.
Stop: The update run should stop execution.
enum:
- Initialize
- Execute
- Pause
- Abandon
- Run
- Stop
type: string
required:
- placementName
- stagedRolloutStrategyName
type: object
x-kubernetes-validations:
- message: 'invalid state transition: cannot transition from Initialize
to Pause'
to Stop'
rule: '!(has(oldSelf.state) && oldSelf.state == ''Initialize'' && self.state
== ''Pause'')'
- message: 'invalid state transition: cannot transition from Execute to
Initialize'
rule: '!(has(oldSelf.state) && oldSelf.state == ''Execute'' && self.state
== ''Stop'')'
- message: 'invalid state transition: cannot transition from Run to Initialize'
rule: '!(has(oldSelf.state) && oldSelf.state == ''Run'' && self.state
== ''Initialize'')'
- message: 'invalid state transition: cannot transition from Pause to
Initialize'
rule: '!(has(oldSelf.state) && oldSelf.state == ''Pause'' && self.state
- message: 'invalid state transition: cannot transition from Stop to Initialize'
rule: '!(has(oldSelf.state) && oldSelf.state == ''Stop'' && self.state
== ''Initialize'')'
- message: 'invalid state transition: Abandon is a terminal state and
cannot transition to any other state'
rule: '!has(oldSelf.state) || oldSelf.state != ''Abandon'' || self.state
== ''Abandon'''
status:
description: The observed status of ClusterStagedUpdateRun.
properties:
Expand Down
Loading
Loading