Skip to content
Draft
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
14 changes: 11 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
module github.com/openshift/osdctl

go 1.25.7
go 1.26.3

require (
cloud.google.com/go/compute v1.49.1
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Masterminds/semver/v3 v3.4.0
github.com/PagerDuty/go-pagerduty v1.8.0
github.com/andygrunwald/go-jira v1.17.0
github.com/aws/aws-sdk-go-v2 v1.41.7
github.com/aws/aws-sdk-go-v2 v1.41.12
github.com/aws/aws-sdk-go-v2/config v1.32.17
github.com/aws/aws-sdk-go-v2/credentials v1.19.16
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.47.4
Expand All @@ -23,7 +23,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/s3 v1.95.1
github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.1
github.com/aws/aws-sdk-go-v2/service/sts v1.42.1
github.com/aws/smithy-go v1.25.1
github.com/aws/smithy-go v1.27.1
github.com/brianvoe/gofakeit/v6 v6.24.0
github.com/cenkalti/backoff/v4 v4.3.0
github.com/coreos/go-semver v0.3.1
Expand All @@ -34,6 +34,8 @@ require (
github.com/google/go-github/v63 v63.0.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-plugin v1.8.0
github.com/hashicorp/hcl/v2 v2.23.0
github.com/manifoldco/promptui v0.9.0
github.com/modelcontextprotocol/go-sdk v1.6.0
Expand All @@ -54,6 +56,7 @@ require (
github.com/openshift/hypershift/api v0.0.0-20250208145556-2753dcc8cfb7
github.com/openshift/ocm-container v1.0.1-0.20260310005051-28d4fda21872
github.com/openshift/osd-network-verifier v1.7.0
github.com/petrkotas/srelib v0.0.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/shopspring/decimal v1.4.0
github.com/sirupsen/logrus v1.9.4
Expand Down Expand Up @@ -157,6 +160,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/glog v1.2.5 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
Expand All @@ -171,6 +175,7 @@ require (
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-version v1.8.0 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand Down Expand Up @@ -201,6 +206,7 @@ require (
github.com/oapi-codegen/runtime v1.1.2 // indirect
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/oklog/run v1.2.0 // indirect
github.com/openshift-online/ocm-api-model/clientapi v0.0.454 // indirect
github.com/openshift-online/ocm-api-model/model v0.0.454 // indirect
github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 // indirect
Expand Down Expand Up @@ -270,3 +276,5 @@ require (
)

replace github.com/observatorium/api v0.1.2 => github.com/observatorium/api v0.1.3-0.20260326145919-3032029d0fde

replace github.com/petrkotas/srelib => ../srelib

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Replace directives:"
rg -n '^replace\s+' go.mod

echo "srelib entries:"
rg -n 'github.com/petrkotas/srelib' go.mod

if [ -d ../srelib ]; then
  echo "Found ../srelib locally (still non-portable across CI/consumers)."
else
  echo "../srelib is absent; this replace will fail in clean environments."
fi

Repository: openshift/osdctl

Length of output: 425


Remove local replace directive; it blocks builds in any clean environment.

replace github.com/petrkotas/srelib => ../srelib will fail immediately on CI systems and consumer builds since ../srelib is absent from the repository. This is a build blocker, not just a reproducibility issue. Either remove the replace directive or reference a resolvable module version (published release, commit-based pseudo-version, or git branch).

Per supply chain security guidelines, all dependency references must be reproducible and pinnable. Local filesystem paths violate this requirement and must not reach production.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@go.mod` at line 280, The local filesystem replace directive for
github.com/petrkotas/srelib that points to ../srelib will cause build failures
in CI systems and clean environments where that relative path does not exist.
Remove this replace directive from go.mod entirely, or if the module is needed
as a dependency, replace it with a resolvable reference such as a published
version, a commit-based pseudo-version, or a git branch reference that can be
accessed reproducibly across all build environments.

Source: Coding guidelines

29 changes: 25 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmms
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8=
github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc=
github.com/aws/aws-sdk-go-v2 v1.41.12 h1:DIKX2c31ekm9RA2D9FBj1EWXx++9AdAqRw+e78Tq2Ck=
github.com/aws/aws-sdk-go-v2 v1.41.12/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4=
github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU=
Expand Down Expand Up @@ -114,8 +114,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg=
github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk=
github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio=
github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI=
github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/aws/smithy-go v1.27.1 h1:4T340VFndXtADGF52gYa1POyL7s9E4Z1OeZ1hCscIw8=
github.com/aws/smithy-go v1.27.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand All @@ -125,6 +125,8 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/brianvoe/gofakeit/v6 v6.24.0 h1:74yq7RRz/noddscZHRS2T84oHZisW9muwbb8sRnU52A=
github.com/brianvoe/gofakeit/v6 v6.24.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8=
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down Expand Up @@ -182,6 +184,7 @@ github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/X
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
Expand Down Expand Up @@ -331,12 +334,16 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-plugin v1.8.0 h1:ie8S6RRY8RvB2usYZv+AAZ/wBvx2AU5p5QeP5j/FORs=
github.com/hashicorp/go-plugin v1.8.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos=
github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
Expand All @@ -350,6 +357,8 @@ github.com/itchyny/timefmt-go v0.1.7 h1:xyftit9Tbw+Dc/huSSPJaEmX1TVL8lw5vxjJLK4G
github.com/itchyny/timefmt-go v0.1.7/go.mod h1:5E46Q+zj7vbTgWY8o5YkMeYb4I6GeWLFnetPy5oBrAI=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
Expand Down Expand Up @@ -391,10 +400,14 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
Expand Down Expand Up @@ -450,6 +463,8 @@ github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletI
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
github.com/observatorium/api v0.1.3-0.20260127104902-9709b1e9e333 h1:mI+T3B7s2xYGUzyoycDJGGbe785Efzj5+QLwNsC5ZeY=
github.com/observatorium/api v0.1.3-0.20260127104902-9709b1e9e333/go.mod h1:HKU7EOtFTNJZut37rU/f+VxPfGylPMRS/gEGzwbg93g=
github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E=
github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down Expand Up @@ -574,6 +589,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
Expand Down Expand Up @@ -698,6 +714,8 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -710,11 +728,14 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
23 changes: 23 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,28 @@ package main
import (
"fmt"
"os"
"path/filepath"

"github.com/openshift/osdctl/cmd"
"github.com/openshift/osdctl/pkg/osdctlConfig"
srelibpkg "github.com/openshift/osdctl/pkg/srelib"
"github.com/openshift/osdctl/pkg/utils"
"github.com/spf13/cobra"

"k8s.io/cli-runtime/pkg/genericclioptions"
)

func resolveSrelibPlugin() string {
if p := os.Getenv("SRELIB_PLUGIN_PATH"); p != "" {
return p
}
exe, err := os.Executable()
if err != nil {
return ""
}
return filepath.Join(filepath.Dir(exe), "srelib-plugin")
}

func main() {

err := osdctlConfig.EnsureConfigFile()
Expand All @@ -19,6 +33,15 @@ func main() {
return
}

pluginPath := resolveSrelibPlugin()
srelibClient, err := srelibpkg.NewClient(pluginPath)
if err != nil {
fmt.Fprintf(os.Stderr, "fatal: cannot start srelib plugin (%s): %v\n", pluginPath, err)
os.Exit(1)
}
defer srelibClient.Close()
utils.SetSrelibClient(srelibClient)

cobra.EnableTraverseRunHooks = true
command := cmd.NewCmdRoot(genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr})

Expand Down
55 changes: 55 additions & 0 deletions pkg/srelib/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package srelib

import (
"fmt"
"os/exec"

"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin"
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"

"github.com/petrkotas/srelib/sdk"
v1 "github.com/petrkotas/srelib/sdk/v1"
)

type Client struct {
inner v1.Client
killer *plugin.Client
}

func NewClient(pluginPath string) (*Client, error) {
pc := plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: sdk.HandshakeConfig,
VersionedPlugins: map[int]plugin.PluginSet{
1: {"srelib": &v1.Plugin{}},
},
Cmd: exec.Command(pluginPath),
Logger: hclog.New(&hclog.LoggerOptions{Name: "srelib", Level: hclog.Error}),
})

rpcClient, err := pc.Client()
if err != nil {
pc.Kill()
return nil, fmt.Errorf("srelib: connect to plugin: %w", err)
}

raw, err := rpcClient.Dispense("srelib")
if err != nil {
pc.Kill()
return nil, fmt.Errorf("srelib: dispense plugin: %w", err)
}

return &Client{inner: raw.(v1.Client), killer: pc}, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "client.go" | grep srelib

Repository: openshift/osdctl

Length of output: 83


🏁 Script executed:

head -60 pkg/srelib/client.go | cat -n

Repository: openshift/osdctl

Length of output: 1697


Unguarded type assertion from plugin dispense can panic.

raw.(v1.Client) will panic if the plugin returns a value that doesn't match the expected type. This can happen due to version mismatch, incorrect plugin configuration, or handshake issues. Guard the assertion and return an error instead:

Proposed fix
-	return &Client{inner: raw.(v1.Client), killer: pc}, nil
+	inner, ok := raw.(v1.Client)
+	if !ok {
+		pc.Kill()
+		return nil, fmt.Errorf("srelib: unexpected plugin client type %T", raw)
+	}
+	return &Client{inner: inner, killer: pc}, nil
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return &Client{inner: raw.(v1.Client), killer: pc}, nil
inner, ok := raw.(v1.Client)
if !ok {
pc.Kill()
return nil, fmt.Errorf("srelib: unexpected plugin client type %T", raw)
}
return &Client{inner: inner, killer: pc}, nil
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/srelib/client.go` at line 42, The type assertion `raw.(v1.Client)` in the
return statement is unguarded and will panic if the plugin dispense does not
return a value of the expected type. Guard the type assertion by using the
two-value form (value, ok := raw.(v1.Client)) to check if the assertion
succeeds. If the assertion fails, return nil and a descriptive error instead of
allowing the panic. Only create and return the Client struct if the type
assertion succeeds.

}

func (c *Client) GetClusters(ids []string) ([]*cmv1.Cluster, error) {
return c.inner.GetClusters(ids)
}

func (c *Client) GetClusterAnyStatus(id string) (*cmv1.Cluster, error) {
return c.inner.GetClusterAnyStatus(id)
}

func (c *Client) Close() {
c.killer.Kill()
}
32 changes: 9 additions & 23 deletions pkg/utils/ocm.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ import (

ocmConfig "github.com/openshift-online/ocm-common/pkg/ocm/config"
ocmConnBuilder "github.com/openshift-online/ocm-common/pkg/ocm/connection-builder"
srelibpkg "github.com/openshift/osdctl/pkg/srelib"
)

var activeSrelibClient *srelibpkg.Client

func SetSrelibClient(c *srelibpkg.Client) { activeSrelibClient = c }

const ClusterServiceClusterSearch = "id = '%s' or name = '%s' or external_id = '%s'"

const (
Expand Down Expand Up @@ -59,36 +64,17 @@ var urlAliases = map[string]string{
stagingGovURL: stagingGovURL,
}

// GetClusterAnyStatus returns an OCM cluster object given an OCM connection and cluster id
// GetClusterAnyStatus returns an OCM cluster object given a cluster id
// (internal id, external id, and name all supported).
func GetClusterAnyStatus(conn *sdk.Connection, clusterId string) (*cmv1.Cluster, error) {
// identifier in the accounts management service. To find those clusters we need to check
// directly in the clusters management service.
clustersSearch := fmt.Sprintf(ClusterServiceClusterSearch, clusterId, clusterId, clusterId)
clustersListResponse, err := conn.ClustersMgmt().V1().Clusters().List().Search(clustersSearch).Size(1).Send()
if err != nil {
return nil, fmt.Errorf("can't retrieve clusters for clusterId '%s': %w", clusterId, err)
}

// If there is exactly one cluster matching then return it:
clustersTotal := clustersListResponse.Total()
if clustersTotal == 1 {
return clustersListResponse.Items().Slice()[0], nil
}

return nil, fmt.Errorf("there are %d clusters with identifier or name '%s', expected 1", clustersTotal, clusterId)
return activeSrelibClient.GetClusterAnyStatus(clusterId)
}

func GetClusters(ocmClient *sdk.Connection, clusterIds []string) []*cmv1.Cluster {
for i, id := range clusterIds {
clusterIds[i] = GenerateQuery(id)
}

clusters, err := ApplyFilters(ocmClient, []string{strings.Join(clusterIds, " or ")})
clusters, err := activeSrelibClient.GetClusters(clusterIds)
if err != nil {
log.Fatalf("error while retrieving cluster(s) from ocm: %[1]s", err)
log.Fatalf("error retrieving cluster(s) via srelib: %s", err)
}
Comment on lines 69 to 77

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n pkg/utils/ocm.go | head -100

Repository: openshift/osdctl

Length of output: 4078


🏁 Script executed:

# Search for activeSrelibClient initialization and usage
rg "activeSrelibClient" -B 2 -A 2

Repository: openshift/osdctl

Length of output: 966


🏁 Script executed:

# Check for SetSrelibClient function definition
rg "SetSrelibClient" -B 3 -A 3

Repository: openshift/osdctl

Length of output: 661


🏁 Script executed:

# Look for all calls to GetClusters to understand usage patterns
rg "GetClusters" -B 2 -A 2

Repository: openshift/osdctl

Length of output: 2532


🏁 Script executed:

# Check for error handling in callers of GetClusters
rg "GetClusters|GetClusterAnyStatus" --type go -A 5 | head -50

Repository: openshift/osdctl

Length of output: 2319


🏁 Script executed:

# Find test files
fd -e _test.go | head -20

Repository: openshift/osdctl

Length of output: 42


🏁 Script executed:

# Search for calls to GetClusters and GetClusterAnyStatus in tests
rg "GetClusters|GetClusterAnyStatus" --type go -B 3 -A 3 | grep -E "(_test\.go|test_|Test)" -A 5 | head -40

Repository: openshift/osdctl

Length of output: 42


🏁 Script executed:

# Check if tests initialize the client
rg "SetSrelibClient" --type go

Repository: openshift/osdctl

Length of output: 191


🏁 Script executed:

# Look for alternative entrypoints or main functions
rg "func main" --type go

Repository: openshift/osdctl

Length of output: 178


🏁 Script executed:

# Check docgen/main.go for potential usage
cat -n utils/docgen/main.go | head -80

Repository: openshift/osdctl

Length of output: 222


🏁 Script executed:

# Check for any other imports or usage of GetClusters/GetClusterAnyStatus in tools
rg "GetClusters|GetClusterAnyStatus" utils/docgen/ 2>/dev/null || echo "No usage in docgen"

Repository: openshift/osdctl

Length of output: 79


🏁 Script executed:

# Check if there are any test directories at all
find . -type d -name "*test*" 2>/dev/null | head -10

Repository: openshift/osdctl

Length of output: 131


🏁 Script executed:

# Look for go.sum or go.mod to understand if there's a testing framework
ls -la | grep -E "go\.(mod|sum)|Makefile|\.github"

Repository: openshift/osdctl

Length of output: 295


🏁 Script executed:

# Check callers of GetClusters and GetClusterAnyStatus to understand usage patterns
rg "GetClusters|GetClusterAnyStatus" --type go -B 2 -A 5 | grep -E "(cmd|pkg)/[^/]+\.(go|ts)" | head -50

Repository: openshift/osdctl

Length of output: 42


🏁 Script executed:

# Verify the exact error handling expectations from callers
rg "GetClusters\(" -A 3 --type go | head -50

Repository: openshift/osdctl

Length of output: 2191


Guard global client access and stop terminating process from utility helpers.

These helpers directly dereference the uninitialized activeSrelibClient global without nil checks, causing panic if invoked outside the main entrypoint (e.g., from docgen or tests). Additionally, log.Fatalf in GetClusters hard-exits on recoverable RPC failures, making lookup failures non-recoverable and breaking the error handling contract expected by callers.

Suggested fix
 func GetClusterAnyStatus(conn *sdk.Connection, clusterId string) (*cmv1.Cluster, error) {
-	return activeSrelibClient.GetClusterAnyStatus(clusterId)
+	if activeSrelibClient == nil {
+		return nil, fmt.Errorf("srelib client is not initialized")
+	}
+	return activeSrelibClient.GetClusterAnyStatus(clusterId)
 }
 
-func GetClusters(ocmClient *sdk.Connection, clusterIds []string) []*cmv1.Cluster {
-	clusters, err := activeSrelibClient.GetClusters(clusterIds)
-	if err != nil {
-		log.Fatalf("error retrieving cluster(s) via srelib: %s", err)
-	}
-	return clusters
+func GetClusters(ocmClient *sdk.Connection, clusterIds []string) ([]*cmv1.Cluster, error) {
+	if activeSrelibClient == nil {
+		return nil, fmt.Errorf("srelib client is not initialized")
+	}
+	return activeSrelibClient.GetClusters(clusterIds)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/utils/ocm.go` around lines 69 - 77, The GetClusterAnyStatus and
GetClusters functions must guard access to the global activeSrelibClient with
nil checks to prevent panics when called outside the main entrypoint (such as
from docgen or tests), and the GetClusters function must remove the log.Fatalf
call that terminates the process on error, instead returning the error to the
caller so they can handle the failure appropriately according to their error
handling expectations.


return clusters
}

Expand Down