diff --git a/internal/cli/root.go b/internal/cli/root.go index 4c7a4569..8020537e 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -164,6 +164,7 @@ func (c *Client) Format() outputPkg.Format { break case outputPkg.FormatTable, outputPkg.FormatTerraform, + outputPkg.FormatCrossplane, outputPkg.FormatJSON, outputPkg.FormatYAML: format = f diff --git a/internal/outputs/crossplane/format.go b/internal/outputs/crossplane/format.go new file mode 100644 index 00000000..5bb553b1 --- /dev/null +++ b/internal/outputs/crossplane/format.go @@ -0,0 +1,67 @@ +package crossplane + +import ( + "bytes" + "html/template" + + "github.com/packethost/packngo" +) + +const ( + deviceFormat = ` +--- +apiVersion: server.metal.equinix.com/v1alpha2 +kind: Device +metadata: + name: {{.Hostname}} + annotations: + crossplane.io/external-name: {{.ID}} +spec: + ## Late-Initialization will provide the current values + ## so we don't specify them here. + forProvider: + # hostname: {{.Hostname}} + # plan: {{.Plan.Slug}} + # metro: {{.Metro.Code}} + # operatingSystem: {{.OS.Slug}} + # billingCycle: {{.BillingCycle}} + # locked: {{.Locked}} + # tags: {{.Tags}} + + ## The "default" provider will be used unless named here. + # providerConfigRef: + # name: equinix-metal-provider + + ## EM devices do not persist passwords in the API long. This + ## optional secret will not get the root pass for devices > 24h + # writeConnectionSecretToRef: + # name: crossplane-example + # namespace: crossplane-system + + ## Do not delete devices that have been imported. + reclaimPolicy: Retain +` +) + +func many(s string) string { + return `{{range .}}` + s + `{{end}}` +} +func Marshal(i interface{}) ([]byte, error) { + var f = "" + switch i.(type) { + case *packngo.Device: + f = deviceFormat + case []packngo.Device: + f = many(deviceFormat) + } + tmpl, err := template.New("crossplane").Parse(f) + if err != nil { + return nil, err + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, i) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/internal/outputs/outputs.go b/internal/outputs/outputs.go index e5c18fe7..48e1842d 100644 --- a/internal/outputs/outputs.go +++ b/internal/outputs/outputs.go @@ -8,16 +8,18 @@ import ( "github.com/olekukonko/tablewriter" "sigs.k8s.io/yaml" + "github.com/equinix/metal-cli/internal/outputs/crossplane" "github.com/equinix/metal-cli/internal/outputs/terraform" ) type Format string const ( - FormatTable Format = "table" - FormatJSON Format = "json" - FormatYAML Format = "yaml" - FormatTerraform Format = "tf" + FormatTable Format = "table" + FormatJSON Format = "json" + FormatYAML Format = "yaml" + FormatTerraform Format = "tf" + FormatCrossplane Format = "crossplane" ) type Outputer interface { @@ -29,6 +31,15 @@ type Standard struct { Format Format } +func outputCrossplane(in interface{}) error { + output, err := crossplane.Marshal(in) + if err != nil { + return err + } + fmt.Println(string(output)) + return nil +} + func outputTerraform(in interface{}) error { output, err := terraform.Marshal(in) if err != nil { @@ -63,6 +74,8 @@ func (o *Standard) Output(in interface{}, header []string, data *[][]string) err return outputYAML(in) } else if o.Format == FormatTerraform { return outputTerraform(in) + } else if o.Format == FormatCrossplane { + return outputCrossplane(in) } else { table := tablewriter.NewWriter(os.Stdout) table.SetAutoWrapText(false)