Skip to content
Merged
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
37 changes: 25 additions & 12 deletions cmd/xprin-helpers/claimtoxr/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ type Cmd struct {
InputFile string `arg:"" default:"-" help:"The Claim YAML file to be converted. If not specified or '-', stdin will be used." optional:"" predictor:"file" type:"path"`

// Flags.
OutputFile string `help:"The file to write the generated XR YAML to. If not specified, stdout will be used." placeholder:"PATH" predictor:"file" short:"o" type:"path"`
Kind string `help:"The kind to use for the XR. If not specified, 'X' will be prepended to the Claim's kind (e.g. Infra -> XInfra)." placeholder:"KIND" type:"string"`
Direct bool `help:"Create a direct XR without Claim references and suffix." name:"direct" negatable:""`
OutputFile string `help:"The file to write the generated XR YAML to. If not specified, stdout will be used." placeholder:"PATH" predictor:"file" short:"o" type:"path"`
Name string `help:"The name to use for the XR. If empty, defaults to the Claim's name (direct mode) or the Claim's name with a random suffix (non-direct)." placeholder:"NAME" type:"string"`
Kind string `help:"The kind to use for the XR. If not specified, 'X' will be prepended to the Claim's kind (e.g. Infra -> XInfra)." placeholder:"KIND" type:"string"`
Direct bool `help:"Create a direct XR without Claim references and suffix." name:"direct" negatable:""`
GenUID bool `help:"Set a fresh random metadata.uid on the generated XR." name:"gen-uid"`

fs afero.Fs
}
Expand All @@ -50,26 +52,32 @@ func (c *Cmd) Help() string {
Convert a Crossplane Claim YAML file to a Crossplane Composite Resource (XR) format.

This command will:
- Read the Claim from the provided YAML file
- Create an XR with the same spec as the Claim
- Set appropriate API version and kind for the XR
- Set up the Claim reference in the XR (unless --direct is used)
- Copy any composition selector
- Read the Claim from the provided YAML file
- Create an XR with the same spec as the Claim
- Set appropriate API version and kind for the XR
- Set up the Claim reference in the XR (unless --direct is used)
- Copy any composition selector

Examples:

# Convert claim.yaml to XR format and write to stdout (kind will be 'X' + Claim's kind)
xprin-helpers convert-claim-to-xr claim.yaml

# Convert claim.yaml to XR format with a specific kind
xprin-helpers convert-claim-to-xr claim.yaml --kind MyCompositeResource

# Convert claim.yaml to XR format and write to xr.yaml
xprin-helpers convert-claim-to-xr claim.yaml -o xr.yaml

# Convert claim.yaml using an explicit XR name (overrides the default suffix or claim name)
xprin-helpers convert-claim-to-xr claim.yaml --name my-xr

# Convert claim.yaml to XR format with a specific kind
xprin-helpers convert-claim-to-xr claim.yaml --kind MyCompositeResource

# Convert claim.yaml to a directly created XR (no Claim references, no name suffix)
xprin-helpers convert-claim-to-xr claim.yaml --direct

# Convert claim.yaml and assign a fresh random metadata.uid to the XR
xprin-helpers convert-claim-to-xr claim.yaml --gen-uid

# Convert Claim from stdin to XR format
cat claim.yaml | xprin-helpers convert-claim-to-xr -
`
Expand All @@ -94,7 +102,12 @@ func (c *Cmd) Run(k *kong.Context) error {
}

// Convert to XR
xr, err := ConvertClaimToXR(claim, c.Kind, c.Direct)
xr, err := ConvertClaimToXR(claim, Options{
Name: c.Name,
Kind: c.Kind,
Direct: c.Direct,
GenerateUID: c.GenUID,
})
if err != nil {
return errors.Wrap(err, "failed to convert Claim to XR")
}
Expand Down
40 changes: 35 additions & 5 deletions cmd/xprin-helpers/claimtoxr/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package claimtoxr
import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apiserver/pkg/storage/names"

"github.com/crossplane/crossplane-runtime/v2/pkg/errors"
Expand All @@ -41,8 +42,28 @@ const (
labelComposite = "crossplane.io/composite"
)

// Options configures ConvertClaimToXR.
type Options struct {
// Name is the XR name. Empty falls back to:
// - claim.Name when Direct is true
// - claim.Name with a random suffix when Direct is false
// A non-empty Name overrides both fallbacks.
Name string

// Kind is the XR kind. Empty defaults to "X" + claim.Kind.
Kind string

// Direct controls XR linkage to the claim:
// - true: no spec.claimRef; no claim-name/claim-namespace labels
// - false: spec.claimRef is set; claim-name/claim-namespace labels added
Direct bool

// GenerateUID, when true, sets metadata.uid to a fresh random UUID.
GenerateUID bool
}

// ConvertClaimToXR converts a Crossplane Claim to a Composite Resource (XR).
func ConvertClaimToXR(claim *unstructured.Unstructured, kind string, direct bool) (*unstructured.Unstructured, error) {
func ConvertClaimToXR(claim *unstructured.Unstructured, opts Options) (*composite.Unstructured, error) {
if claim == nil {
return nil, errors.New(errNilInput)
}
Expand Down Expand Up @@ -92,7 +113,8 @@ func ConvertClaimToXR(claim *unstructured.Unstructured, kind string, direct bool
return nil, errors.Wrap(err, "failed to set apiVersion")
}

// Set XR kind - either from flag or by prepending X to Claim's kind
// Set XR kind - either from opts or by prepending X to Claim's kind
kind := opts.Kind
if kind == "" {
kind = "X" + claimKind
}
Expand All @@ -113,7 +135,7 @@ func ConvertClaimToXR(claim *unstructured.Unstructured, kind string, direct bool

xrName := claimName

if !direct {
if !opts.Direct {
xrName = names.SimpleNameGenerator.GenerateName(claimName + "-")
labels[labelClaimName] = claim.GetName()

Expand All @@ -128,6 +150,11 @@ func ConvertClaimToXR(claim *unstructured.Unstructured, kind string, direct bool
}
}

// Explicit Name overrides both Direct's claim-name default and the generated suffix.
if opts.Name != "" {
xrName = opts.Name
}

if err := xrPaved.SetString("metadata.name", xrName); err != nil {
return nil, errors.Wrap(err, "failed to set name")
}
Expand All @@ -140,6 +167,9 @@ func ConvertClaimToXR(claim *unstructured.Unstructured, kind string, direct bool
}
}

// Convert from composite.Unstructured to unstructured.Unstructured
return &unstructured.Unstructured{Object: xr.UnstructuredContent()}, nil
if opts.GenerateUID {
xr.SetUID(uuid.NewUUID())
}

return xr, nil
}
Loading
Loading