Skip to content

Rewrite/resource verification - #336

Open
Tanker2020 wants to merge 31 commits into
IBM:mainfrom
Tanker2020:rewrite/Resource_Verification
Open

Rewrite/resource verification#336
Tanker2020 wants to merge 31 commits into
IBM:mainfrom
Tanker2020:rewrite/Resource_Verification

Conversation

@Tanker2020

Copy link
Copy Markdown

Summary

Ports the Python oper8 resource verification layer to Go. Provides VerifyResource — the single entry point that fetches an object's current state and decides whether it is ready — along with built-in verifiers for the four standard Kubernetes workload kinds and a subsystem verifier for nested oper8-managed CRs.

Files changed:

  • rewrite/verify/verify.goVerifyFunc, VerifyOptions, VerifyResource, internal condition helpers
  • rewrite/verify/builtin.goVerifyPod, VerifyJob, VerifyDeployment, VerifyStatefulSet, VerifySubsystem
  • rewrite/verify/verify_test.go — 42 table-driven tests
  • .github/workflows/pr4-verify.yml — CI

Depends on: PR-2 (deploymanager/) for DeployManager.Get(), PR-3 (status/) for ConditionReady, ConditionUpdating, TimestampKey, GetVersion. This PR is stacked on the PR-3 branch but all four packages compile and test cleanly when merged in any order.


What was ported

Python Go equivalent
verify_resources.pyverify_resource() verify.VerifyResource(ctx, dm, apiVersion, kind, name, opts)
verify_resources.pyverify_pod() verify.VerifyPod(objectState)
verify_resources.pyverify_job() verify.VerifyJob(objectState)
verify_resources.pyverify_deployment() verify.VerifyDeployment(objectState)
verify_resources.pyverify_statefulset() verify.VerifyStatefulSet(objectState)
verify_resources.pyverify_subsystem() verify.VerifySubsystem(objectState, desiredVersion)
_resource_verifiers module dict kindVerifiers package map + Register()
_verify_condition internal verifyCondition()
_check_condition internal checkCondition()

Design decisions

session.get_object_current_state()dm.Get(ctx, ...)

Python's verify_resource took a session object and called session.get_object_current_state(kind, name, api_version, namespace). The session abstraction doesn't exist yet in the Go port (PR-5). VerifyResource takes a DeployManager directly and calls dm.Get() — it is context-aware and testable with DryRunDeployManager in isolation.

_SESSION_NAMESPACE sentinel → explicit Namespace field

Python used a _SESSION_NAMESPACE sentinel default to distinguish "use session namespace" from "non-namespaced resource (pass None)". Go replaces this with an explicit opts.Namespace string. Callers pass the namespace they want; the zero value ("") means cluster-scoped (non-namespaced).

_resource_verifiers module dict → Register() + init()

Python populated a module-level dict at import time. Go uses an explicit Register(kind, fn) function called from builtin.go's init(). This is safe under -race (init runs once before main), makes the registry extensible by callers without package modification, and avoids hidden global state mutation.

dateutil.parsertime.Parse(time.RFC3339)

Python used dateutil.parser.parse() for timestamp sorting, which accepts many formats. Go uses time.Parse(time.RFC3339) — the only format Kubernetes actually writes. Invalid or missing timestamps fall back to time.Unix(0, 0) (epoch), matching Python's datetime.fromtimestamp(0) fallback.

Bug fix: raw bool status values

Python's _check_condition handled three cases for the condition status field:

  1. String "True"/"False" (standard Kubernetes)
  2. Any other string — case-insensitive compare
  3. Raw boolbool(obj_status) == expected_status

The initial Go port did condition["status"].(string) which silently returns "" for a raw bool value, causing the function to incorrectly return false. Fixed with a type switch: case bool → direct compare, case stringstrings.EqualFold(v, "true") == expectedStatus.


Test coverage (42 tests)

Area Tests
VerifyResource integration (via DryRunDeployManager) not found, no verifier (present=verified), custom condition type true/false, per-call VerifyFunc, kind registry (Pod/Job/Deployment/StatefulSet), latest condition wins (timestamp sort), IsSubsystem flag
VerifyPod Ready=True, Ready=False, no conditions
VerifyJob Complete=True, Complete=False, no status
VerifyDeployment Available+Progressing(correct reason), wrong reason, only Available, no conditions
VerifyStatefulSet replicas==readyReplicas, partial ready, no replicas, nil status
VerifySubsystem version matches, version mismatch, version not yet set, Updating=True, Ready=False, no desiredVersion
Python-parity edge cases bool status=true, bool status=false, non-bool string ("NotABool"→false), missing status key

All tests run with -race.

- Node: name, optional NodeFunc, directed edges to upstream deps
- Edge: carries optional EdgeFunc to gate dependent start
- ResourceNode: embeds Node, adds Manifest/VerifyFunc/DeployMethod
- Graph: root-anchored container; AddNode, AddDependency, Topology
- Cycle detection on every AddChild call (DFS reachability)
- Topology() returns DFS post-order (dependency-first deploy order)

Files: rewrite/dag/node.go, rewrite/dag/graph.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
- CompletionState: Verified/Unverified/Failed/Unstarted node buckets
- DeployCompleted(), VerifyCompleted(), AnyFailed() predicates
- HaltError{Fatal bool}: returned by NodeFunc to signal runner halt
  Fatal=true  → node lands in Failed, downstreams become Unstarted
  Fatal=false → node lands in Unverified (deployed, not yet ready)

Files: rewrite/dag/completion_state.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Python used ThreadPoolExecutor + time.sleep(0.05) busy-poll loop.
Go port uses goroutines + buffered results channel; scheduler blocks
on select — zero CPU busy-polling.

- NewRunner(graph, opts...) with functional options
- WithConcurrency(0): serial topology walk, no goroutines (dry-run/test)
- WithConcurrency(n): semaphore-capped parallel execution
- WithVerifyUpstream(bool): gate dependent start on EdgeFunc result
- context.Context cancellation: drains in-flight, marks rest Unstarted
- Independent graph branches continue executing after sibling failure
  (matches Python oper8 intended behaviour; Python had a bug where the
  serial loop broke early on fatalErr)
- stateMap protected by sync.Mutex; scheduler is single writer

Files: rewrite/dag/runner.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
23 test cases covering:
  Graph/Node:  empty graph, duplicate node, empty name, cycle detection,
               self-loop, topology order, String()
  Runner serial: all succeed, empty graph, fatal halt (independent branch
               still runs), unverified halt, disabled node, execution order
  Runner concurrent: all succeed, fatal halt, independent nodes verified
               parallel via start-time spread, race detector stress test
               (20 nodes, atomic counter), context cancellation
  EdgeFunc:    blocks dependent when returns false, allows when true
  CompletionState: all predicate combinations
  ResourceNode: construction and field access

Concurrency test uses start-time recording rather than wall-clock
total elapsed — CI-safe on slow runners.

Files: rewrite/dag/runner_test.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
- Matrix: Go 1.22 and 1.23
- go test -race -count=1 -timeout=60s ./dag/...
- go build ./... and go vet ./dag/...
- golangci-lint on dag/ package
- Triggered on push to rewrite/DAG_Runner and PRs targeting main
- working-directory: rewrite (module root)

Files: ./.github/workflows/pr1-dag-runner.yml
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Defines the core abstraction all cluster interactions go through.

Python (bool, bool) return tuples → Go (changed bool, err error):
- success bool dropped; errors are returned as error values
- callers use idiomatic `if err != nil` instead of checking two booleans

watch_objects Python generator → Go channel:
- Watch() returns <-chan WatchEvent; caller ranges over it
- Cancelled via context.Context; channel is closed on cancel

New types vs Python:
- ListOptions struct (replaces positional label_selector/field_selector args)
- EventType string constants (ADDED/MODIFIED/DELETED)
- WatchEvent struct with Timestamp

Files: rewrite/deploymanager/deploymanager.go

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Ports deploy_manager/owner_references.py.

- OwnerRef(ownerCR) builds a single ownerReference map entry
- ApplyOwnerRef(owner, child) stamps the reference onto child.metadata
  - No-op when owner == child (same UID)
  - No-op for cross-namespace references (K8s does not support them)
  - Idempotent: will not add duplicate entries
- blockOwnerDeletion: true; controller field intentionally omitted
  (matches Python behaviour and StackOverflow rationale in source)

Files: rewrite/deploymanager/ownerref.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Ports deploy_manager/dry_run_deploy_manager.py.

Primary use: unit-testing controllers without a live cluster.

Key differences from Python:
- Python used nested defaultdict; Go uses typed clusterStore
  (map[ns][kind][apiVersion][name] → object)
- Python RLock on class level; Go sync.RWMutex per instance
- Python watch callbacks were registered functions; Go uses buffered
  channels — consumers range over the channel, cancel via context
- Watch channel is closed when ctx is cancelled (no explicit Unregister)
- deepCopy via JSON marshal/unmarshal (simple, correct for map[string]any)
- matchSelector implements = == != existence operators (sufficient for
  dry-run tests; full set-based selector is future work)

Extra test helpers (not in Python):
- GetStored(ns, kind, av, name) — direct store access for assertions
- ObjectCount() — total objects in store

Files: rewrite/deploymanager/dryrun.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
19 test cases covering:
  Deploy:     create, idempotent re-deploy, field update, owner ref stamping
  Get:        not found returns nil, found returns deep copy (mutation check)
  Delete:     existing object, non-existent no-op
  List:       all objects, label selector filtering
  SetStatus:  sets status, returns changed=true; error on missing object
  Watch:      receives ADDED on deploy, DELETED on delete, channel closes
              on context cancel (race-detector safe)
  OwnerRef:   stamps reference, idempotent, cross-namespace skipped

Files: rewrite/deploymanager/dryrun_test.go
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
- Matrix: Go 1.22 and 1.23
- go test -race -count=1 -timeout=60s ./deploymanager/...
- go build ./... and go vet ./deploymanager/...
- golangci-lint on deploymanager/ package
- Triggered on push to rewrite/Deploy_Manager and PRs targeting main

Files: .github/workflows/pr2-deploy-manager.yml
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
…licationStatus

Ports oper8 Python status.py to Go.

Reason types: ReadyReason, UpdatingReason, ServiceStatus string constants.

MakeApplicationStatus(Options) builds a complete status map:
- Ready + Updating conditions from reason/message pairs
- External conditions preserved alongside oper8-managed ones
- ComponentStatus block from dag.CompletionState (sorted node names)
- versions.reconciled / versions.available.versions (IBM CloudPak paths)
- <kind>Status field (e.g. customerStatus) when Kind is set

UpdateApplicationStatus merges new Options onto existing status,
carrying forward current reasons and external conditions when not overridden.

GetCondition, GetVersion, StatusChanged helper functions included.

Python translation notes:
- deepdiff library dropped; StatusChanged uses recursive JSON comparison
  after stripping lastTransactionTime keys — zero external dependencies
- **kwargs replaced by Options struct (compile-time field checking)
- aconfig nested_set/nested_get replaced by nestedSet/nestedGet dot-path helpers

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
MakeApplicationStatus: Ready/Updating condition status values for all
  reason combinations, empty options, external conditions, version fields,
  componentStatus deployed/verified counts and dependencyGraph, IBM CloudPak
  <kind>Status (Completed/Failed/InProgress/custom preserved)

UpdateApplicationStatus: preserves existing reasons when not overridden,
  overrides when provided, preserves external conditions and top-level fields

StatusChanged: same content + different timestamps not changed, different
  reason changed, nil inputs, added field

GetCondition, GetVersion: found/missing cases
UpdatingReason active/inactive matrix (all 6 reasons)
ComponentStatus node names sorted alphabetically

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Matrix Go 1.22 and 1.23, race detector, golangci-lint v1.64.8

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
…load config

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
…ondition

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
…rity tests

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
@Tanker2020
Tanker2020 force-pushed the rewrite/Resource_Verification branch from 56f1901 to f643b60 Compare August 11, 2026 08:11
…r, ReconcileManager

Ports oper8 Python session.py / component.py / controller.py /
rollout_manager.py / reconcile.py to Go.

New packages:
  rewrite/session/          per-reconcile context (CR, DAG, status fetch)
  rewrite/component/        Component interface — Name/Setup/Deploy/Verify
  rewrite/controller/       Controller interface + BaseController no-op embed
  rewrite/rolloutmanager/   4-phase loop: deploy→after_deploy→verify→after_verify
  rewrite/reconcilemanager/ top-level orchestrator: ID gen, session init,
                            preconditions, rollout, status writes, finalizers

dag/node.go: add Node.SetFunc / SetData / Data (no unused fields)
gofmt: dag/runner.go, dag/runner_test.go, deploymanager/dryrun.go

reconcilemanager tests (9 cases, -race clean):
  EmptyGraph, SingleComponentVerified, SetupError, DeployError,
  VerifyNotReady, Precondition, TwoComponentsOrdered, InvalidCR, Finalizer

CI: .github/workflows/pr5-reconcile.yml
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
…r, ReconcileManager

Ports oper8 Python session.py / component.py / controller.py /
rollout_manager.py / reconcile.py to Go.

New packages:
  rewrite/session/          per-reconcile context (CR, DAG, status fetch)
  rewrite/component/        Component interface — Name/Setup/Deploy/Verify
  rewrite/controller/       Controller interface + BaseController no-op embed
  rewrite/rolloutmanager/   4-phase loop: deploy→after_deploy→verify→after_verify
  rewrite/reconcilemanager/ top-level orchestrator: ID gen, session init,
                            preconditions, rollout, status writes, finalizers

dag/node.go: add Node.SetFunc / SetData / Data (no unused fields — fixes
             previous lint failure for unused nishanthk  ttys002                         Tue Aug 11 12:37 - 12:37  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:30 - 11:30  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:30 - 11:30  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:30 - 11:30  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:30 - 11:30  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:29 - 11:29  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:29 - 11:29  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:28 - 11:28  (00:00)
nishanthk  ttys002                         Thu Jul 30 11:23 - 11:23  (00:00)
nishanthk  ttys001                         Thu Jul 30 11:19   still logged in
nishanthk  ttys000                         Thu Jul 30 11:19   still logged in
nishanthk  console                         Thu Jul 30 11:19   still logged in
reboot time                                Thu Jul 30 11:00
shutdown time                              Thu Jul 30 10:59
nishanthk  ttys001                         Fri Jul 24 15:26 - 15:26  (00:00)
nishanthk  ttys000                         Fri Jul 24 15:26 - 15:26  (00:00)
nishanthk  console                         Fri Jul 24 15:26 - 10:59 (5+19:33)
reboot time                                Fri Jul 24 15:25
shutdown time                              Fri Jul 24 15:24
nishanthk  ttys001                         Wed Jul 22 00:37 - 00:37  (00:00)
nishanthk  ttys000                         Wed Jul 22 00:37 - 00:37  (00:00)
nishanthk  console                         Wed Jul 22 00:37 - 15:24 (2+14:47)
reboot time                                Wed Jul 22 00:35
shutdown time                              Wed Jul 22 00:31
root       console                         Wed Jul 22 00:30 - shutdown  (00:00)
nishanthk  ttys001                         Fri Jul 17 16:28 - 16:28  (00:00)
nishanthk  ttys001                         Thu Jul  9 13:25 - 13:25  (00:00)
nishanthk  ttys001                         Mon Jul  6 14:14 - 14:14  (00:00)
nishanthk  ttys005                         Mon Jul  6 14:14 - 14:14  (00:00)
nishanthk  ttys006                         Mon Jul  6 14:14 - 14:14  (00:00)
nishanthk  ttys003                         Mon Jun 29 14:47 - 14:47  (00:00)
nishanthk  ttys002                         Mon Jun 29 14:47 - 14:47  (00:00)
nishanthk  ttys001                         Mon Jun 29 14:47 - 14:47  (00:00)
nishanthk  ttys006                         Mon Jun 29 14:21 - 14:21  (00:00)
nishanthk  ttys006                         Mon Jun 29 14:21 - 14:21  (00:00)
nishanthk  ttys003                         Mon Jun 29 13:36 - 13:36  (00:00)
nishanthk  ttys005                         Mon Jun 22 02:32 - 02:32  (00:00)
nishanthk  ttys004                         Mon Jun 22 02:30 - 02:30  (00:00)
nishanthk  ttys003                         Mon Jun 22 01:16 - 01:16  (00:00)
nishanthk  ttys002                         Thu Jun 18 16:23 - 16:23  (00:00)
nishanthk  ttys001                         Thu Jun 18 16:23 - 16:23  (00:00)
nishanthk  ttys000                         Thu Jun 18 16:23 - 16:23  (00:00)
nishanthk  console                         Thu Jun 18 16:23 - 00:30 (33+08:07)
reboot time                                Thu Jun 18 16:23
nishanthk  ttys002                         Wed Jun 17 12:32 - crash (1+03:50)
nishanthk  ttys001                         Mon Jun 15 13:30 - crash (3+02:52)
nishanthk  ttys000                         Mon Jun 15 13:30 - crash (3+02:53)
nishanthk  ttys003                         Mon Jun 15 13:17 - 13:17  (00:00)
nishanthk  ttys003                         Mon Jun 15 13:17 - 13:17  (00:00)
nishanthk  ttys002                         Mon Jun 15 13:16 - 13:16  (00:00)
nishanthk  ttys003                         Mon Jun 15 13:14 - 13:14  (00:00)
nishanthk  ttys002                         Mon Jun 15 13:12 - 13:12  (00:00)
nishanthk  ttys002                         Mon Jun 15 13:11 - 13:11  (00:00)
nishanthk  ttys003                         Mon Jun 15 13:07 - 13:07  (00:00)
nishanthk  ttys002                         Fri Jun 12 13:02 - 13:02  (00:00)
nishanthk  ttys002                         Thu Jun 11 12:44 - 12:44  (00:00)
nishanthk  ttys004                         Mon Jun  8 13:56 - 13:56  (00:00)
nishanthk  ttys002                         Mon Jun  8 13:56 - 13:56  (00:00)
nishanthk  ttys003                         Mon Jun  8 13:56 - 13:56  (00:00)
nishanthk  ttys004                         Fri Jun  5 09:34 - 09:34  (00:00)
nishanthk  ttys002                         Fri Jun  5 09:34 - 09:34  (00:00)
nishanthk  ttys003                         Fri Jun  5 09:34 - 09:34  (00:00)
nishanthk  ttys020                         Thu Jun  4 11:20 - 11:20  (00:00)
nishanthk  ttys004                         Wed Jun  3 16:42 - 16:42  (00:00)
nishanthk  ttys003                         Wed Jun  3 00:06 - 00:06  (00:00)
nishanthk  ttys002                         Wed Jun  3 00:06 - 00:06  (00:00)
nishanthk  ttys001                         Wed Jun  3 00:06 - 00:06  (00:00)
nishanthk  ttys000                         Wed Jun  3 00:06 - 00:06  (00:00)
nishanthk  console                         Wed Jun  3 00:06 - crash (15+16:17)
reboot time                                Wed Jun  3 00:04
shutdown time                              Tue Jun  2 23:59
root       console                         Tue Jun  2 23:57 - shutdown  (00:02)
nishanthk  ttys003                         Mon Jun  1 21:50 - 21:50  (00:00)
nishanthk  ttys002                         Mon Jun  1 21:50 - 21:50  (00:00)
nishanthk  ttys001                         Mon Jun  1 21:50 - 21:50  (00:00)
nishanthk  ttys000                         Mon Jun  1 21:50 - 21:50  (00:00)
nishanthk  console                         Mon Jun  1 21:50 - 23:57 (1+02:07)
reboot time                                Mon Jun  1 21:49
shutdown time                              Mon Jun  1 21:49
root       console                         Mon Jun  1 21:49 - shutdown  (00:00)
nishanthk  ttys003                         Mon Jun  1 10:57 - 10:57  (00:00)
nishanthk  ttys009                         Mon Jun  1 10:21 - 10:21  (00:00)
nishanthk  ttys000                         Mon Jun  1 10:15 - 10:15  (00:00)
nishanthk  ttys004                         Fri May 29 15:11 - 15:11  (00:00)
nishanthk  ttys003                         Fri May 29 12:56 - 12:56  (00:00)
nishanthk  ttys002                         Wed May 27 16:07 - 16:07  (00:00)
nishanthk  ttys001                         Wed May 27 16:05 - 16:05  (00:00)
nishanthk  ttys001                         Wed May 27 11:31 - 11:32  (00:00)
nishanthk  ttys001                         Wed May 27 11:31 - 11:31  (00:00)
nishanthk  ttys002                         Tue May 26 17:36 - 17:36  (00:00)
nishanthk  ttys001                         Tue May 26 17:24 - 17:24  (00:00)
nishanthk  ttys001                         Tue May 26 15:48 - 15:48  (00:00)
nishanthk  ttys001                         Tue May 26 15:47 - 15:47  (00:00)
nishanthk  ttys000                         Tue May 26 15:46 - 15:46  (00:00)
nishanthk  ttys001                         Tue May 26 15:42 - 15:42  (00:00)
nishanthk  ttys001                         Tue May 26 15:31 - 15:31  (00:00)
nishanthk  ttys000                         Tue May 26 14:44 - 14:44  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys002                         Tue May 26 14:43 - 14:43  (00:00)
nishanthk  ttys001                         Tue May 26 14:42 - 14:42  (00:00)
nishanthk  ttys000                         Tue May 26 14:31 - 14:31  (00:00)
nishanthk  console                         Tue May 26 13:42 - 21:49 (6+08:07)
_mbsetupuser console                         Tue May 26 13:27 - 13:42  (00:14)
root       console                         Tue May 26 13:27 - 13:27  (00:00)
reboot time                                Tue May 26 13:26
shutdown time                              Thu May 21 02:12
reboot time                                Thu May 21 02:03
reboot time                                Tue Mar  3 22:23
reboot time                                Tue Mar  3 22:18

wtmp begins Tue Mar  3 22:18:14 CST 2026 field on Runner)
gofmt: dag/runner.go, dag/runner_test.go, deploymanager/dryrun.go

Tests (-race, all packages):
  session_test.go          20 cases: construction, CR validation, accessor
                           fields, current version, component DAG helpers,
                           scoped/truncate name, uniqueness
  controller_test.go       14 cases: GVK, HookResult, BaseController defaults,
                           override behaviour
  rolloutmanager_test.go   24 cases: happy path, setup/deploy errors, verify
                           incomplete, downstream blocking, after-deploy/verify
                           hooks (called/not-called/error), independent branches,
                           concurrent execution
  reconcilemanager_test.go 27 cases: basic reconcile, requeue control,
                           preconditions (fail/multi/pass), finalizer add/error/
                           stamped-on-object, invalid CR variants, multi-component
                           ordering, failed-blocks-dependent, status management
                           (stable/error/verify-wait), ReconcileResult defaults

CI: .github/workflows/pr5-reconcile.yml — go test -race ./... + golangci-lint
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
The struct field  on Runner was never read or written —
the concurrent scheduler uses a local  variable instead.
golangci-lint (unused linter) correctly flagged this on the PR-5 CI run.

Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
Signed-off-by: Nishanth Kolakalapudi <Nishanth.Kol@ibm.com>
@Tanker2020
Tanker2020 marked this pull request as ready for review August 13, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant