From 6a274cebed53c08671a7f044b49308e15716b7bd Mon Sep 17 00:00:00 2001 From: Paul Jolly Date: Wed, 21 Aug 2024 14:03:56 +0100 Subject: [PATCH] docs/howto: place data using the Go API This adds a guide demonstrating how to replicate the effect of the cue command's --path flag using the Go API. Preview-Path: /docs/howto/place-data-go-api/ Signed-off-by: Paul Jolly Change-Id: I0e5618207da2bc78cff9df715b1a4827503142dd Dispatch-Trailer: {"type":"trybot","CL":1199814,"patchset":3,"ref":"refs/changes/14/1199814/3","targetBranch":"master"} --- content/docs/howto/place-data-go-api/en.md | 142 ++++++++++++++++++ .../howto/place-data-go-api/gen_cache.cue | 81 ++++++++++ content/docs/howto/place-data-go-api/page.cue | 3 + .../en/docs/howto/place-data-go-api/index.md | 139 +++++++++++++++++ 4 files changed, 365 insertions(+) create mode 100644 content/docs/howto/place-data-go-api/en.md create mode 100644 content/docs/howto/place-data-go-api/gen_cache.cue create mode 100644 content/docs/howto/place-data-go-api/page.cue create mode 100644 hugo/content/en/docs/howto/place-data-go-api/index.md diff --git a/content/docs/howto/place-data-go-api/en.md b/content/docs/howto/place-data-go-api/en.md new file mode 100644 index 000000000..e6b22720f --- /dev/null +++ b/content/docs/howto/place-data-go-api/en.md @@ -0,0 +1,142 @@ +--- +title: Placing data using the Go API +tags: [go api] +authors: [myitcv,jpluscplusm] +toc_hide: true +--- + +{{{with _script_ "en" "set caches to speed up re-running"}}} +export GOMODCACHE=/caches/gomodcache +export GOCACHE=/caches/gobuild +{{{end}}} + +The `cue` command allows non-CUE data to be "placed" at a specific location in +its evaluation with the `--path`/`-l` flag. +This guide demonstrates how to achieve the same result using the Go API. + +## Set up the environment + +{{{with step}}} +If you don't already have CUE or Go modules, initialize them: + +{{{with script "en" "start modules"}}} +cue mod init cue.example +#ellipsis 0 +go mod init go.example +{{{end}}} +{{{end}}} + +## Create some data files + +{{{with step}}} +Write some CUE code and JSON data +(if you don't already have some code that you want to update and use): + +{{{with upload "en" "initial cue code"}}} +#location left right +-- some.cue -- +package example + +// The data will be placed at this location. +input: { + name!: string + location: *"your part of the world" | string +} + +output: """ + Hello, \(input.name)! + How's the weather in \(input.location)? + """ +-- input.json -- +{ + "name": "Charlie" +} +{{{end}}} +{{{end}}} + +{{{with step}}} +Check that the data file can be combined successfully with the CUE: + +{{{with script "en" "test cue"}}} +cue export . input.json --path input: -e output --out text +{{{end}}} +{{{end}}} + +## Write some Go + +{{{with step}}} +Write a Go program that places the data in the `input.json` file at a specific +location within its CUE evaluation +(or adapt your existing code to do the same): + +{{{with upload "en" "go program"}}} +#location top-left +-- main.go -- +package main + +import ( + "fmt" + "log" + "os" + + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" + "cuelang.org/go/cue/load" + "cuelang.org/go/encoding/json" +) + +func main() { + ctx := cuecontext.New() + // Load the package in the current directory. + bis := load.Instances([]string{"."}, nil) + v := ctx.BuildInstance(bis[0]) + + // Load the input data. + jsonBytes, err := os.ReadFile("input.json") + if err != nil { + log.Fatal(err) + } + + // Parse the input data to a CUE expression. + jsonData, err := json.Extract("input.json", jsonBytes) + if err != nil { + log.Fatal(err) + } + + // Place the parsed data as the value of the "input" field. + complete := v.FillPath(cue.ParsePath("input"), jsonData) + + // Extract the string value of the "output" field and print it. + output := complete.LookupPath(cue.ParsePath("output")) + msg, _ := output.String() // We know that "output" is a string type. + fmt.Printf("%v\n", msg) +} +{{{end}}} +{{{end}}} + +## Run the program + +{{{with step}}} +Add a dependency on `cuelang.org/go` and ensure the Go module is tidy: + +{{{with script "en" "go test"}}} +#ellipsis 0 +go get cuelang.org/go@$CUELANG_CUE_LATEST +#ellipsis 0 +go mod tidy +{{{end}}} +{{{end}}} + +{{{with step}}} +Run the program, +printing the same multi-line string value that `cue` produced earlier: + +{{{with script "en" "go run"}}} +go run . +{{{end}}} +{{{end}}} + +## Related content + +- {{< linkto/related/concept "how-cue-works-with-go" >}} +- All pages tagged with {{< tag "go api" >}} diff --git a/content/docs/howto/place-data-go-api/gen_cache.cue b/content/docs/howto/place-data-go-api/gen_cache.cue new file mode 100644 index 000000000..aae2ea2f5 --- /dev/null +++ b/content/docs/howto/place-data-go-api/gen_cache.cue @@ -0,0 +1,81 @@ +package site +{ + content: { + docs: { + howto: { + "place-data-go-api": { + page: { + cache: { + upload: { + "initial cue code": "cCDR5sNYSrEu2VXlWD62h3u6GdC/q2rCqvM8RQbYLl8=" + "go program": "Gzyh+JVAzI2GEWyf7DIg6z9AwsBNbpQwZIkHwJ3lyMM=" + } + multi_step: { + hash: "EU18HI7QMRIP19IS6GQ5IVJ8OIHKKKHASQ9BAP8DIUJCAE6864L0====" + scriptHash: "B2ACPKB2I7S9HP09ENHJFI1UHG1SO348DOOJ6DIDMB2U9GAQLNBG====" + steps: [{ + doc: "" + cmd: "export GOMODCACHE=/caches/gomodcache" + exitCode: 0 + output: "" + }, { + doc: "" + cmd: "export GOCACHE=/caches/gobuild" + exitCode: 0 + output: "" + }, { + doc: "" + cmd: "cue mod init cue.example" + exitCode: 0 + output: "" + }, { + doc: "#ellipsis 0" + cmd: "go mod init go.example" + exitCode: 0 + output: """ + ... + + """ + }, { + doc: "" + cmd: "cue export . input.json --path input: -e output --out text" + exitCode: 0 + output: """ + Hello, Charlie! + How's the weather in your part of the world? + + """ + }, { + doc: "#ellipsis 0" + cmd: "go get cuelang.org/go@v0.10.0" + exitCode: 0 + output: """ + ... + + """ + }, { + doc: "#ellipsis 0" + cmd: "go mod tidy" + exitCode: 0 + output: """ + ... + + """ + }, { + doc: "" + cmd: "go run ." + exitCode: 0 + output: """ + Hello, Charlie! + How's the weather in your part of the world? + + """ + }] + } + } + } + } + } + } + } +} diff --git a/content/docs/howto/place-data-go-api/page.cue b/content/docs/howto/place-data-go-api/page.cue new file mode 100644 index 000000000..46a7d47de --- /dev/null +++ b/content/docs/howto/place-data-go-api/page.cue @@ -0,0 +1,3 @@ +package site + +content: docs: howto: "place-data-go-api": page: _ diff --git a/hugo/content/en/docs/howto/place-data-go-api/index.md b/hugo/content/en/docs/howto/place-data-go-api/index.md new file mode 100644 index 000000000..df8a77fa1 --- /dev/null +++ b/hugo/content/en/docs/howto/place-data-go-api/index.md @@ -0,0 +1,139 @@ +--- +title: Placing data using the Go API +tags: [go api] +authors: [myitcv,jpluscplusm] +toc_hide: true +--- + +The `cue` command allows non-CUE data to be "placed" at a specific location in +its evaluation with the `--path`/`-l` flag. +This guide demonstrates how to achieve the same result using the Go API. + +## Set up the environment + +{{< step stepNumber="1" >}} +If you don't already have CUE or Go modules, initialize them: + +```text { title="TERMINAL" type="terminal" codeToCopy="Y3VlIG1vZCBpbml0IGN1ZS5leGFtcGxlCmdvIG1vZCBpbml0IGdvLmV4YW1wbGU=" } +$ cue mod init cue.example +$ go mod init go.example +... +``` +{{< /step >}} + +## Create some data files + +{{< step stepNumber="2" >}} +Write some CUE code and JSON data +(if you don't already have some code that you want to update and use): + +{{< code-tabs >}} +{{< code-tab name="some.cue" language="cue" area="left" >}} +package example + +// The data will be placed at this location. +input: { + name!: string + location: *"your part of the world" | string +} + +output: """ + Hello, \(input.name)! + How's the weather in \(input.location)? + """ +{{< /code-tab >}}{{< code-tab name="input.json" language="json" area="right" >}} +{ + "name": "Charlie" +} +{{< /code-tab >}}{{< /code-tabs >}} +{{< /step >}} + +{{< step stepNumber="3" >}} +Check that the data file can be combined successfully with the CUE: + +```text { title="TERMINAL" type="terminal" codeToCopy="Y3VlIGV4cG9ydCAuIGlucHV0Lmpzb24gLS1wYXRoIGlucHV0OiAtZSBvdXRwdXQgLS1vdXQgdGV4dA==" } +$ cue export . input.json --path input: -e output --out text +Hello, Charlie! +How's the weather in your part of the world? +``` +{{< /step >}} + +## Write some Go + +{{< step stepNumber="4" >}} +Write a Go program that places the data in the `input.json` file at a specific +location within its CUE evaluation +(or adapt your existing code to do the same): + +{{< code-tabs >}} +{{< code-tab name="main.go" language="go" area="top-left" >}} +package main + +import ( + "fmt" + "log" + "os" + + "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" + "cuelang.org/go/cue/load" + "cuelang.org/go/encoding/json" +) + +func main() { + ctx := cuecontext.New() + // Load the package in the current directory. + bis := load.Instances([]string{"."}, nil) + v := ctx.BuildInstance(bis[0]) + + // Load the input data. + jsonBytes, err := os.ReadFile("input.json") + if err != nil { + log.Fatal(err) + } + + // Parse the input data to a CUE expression. + jsonData, err := json.Extract("input.json", jsonBytes) + if err != nil { + log.Fatal(err) + } + + // Place the parsed data as the value of the "input" field. + complete := v.FillPath(cue.ParsePath("input"), jsonData) + + // Extract the string value of the "output" field and print it. + output := complete.LookupPath(cue.ParsePath("output")) + msg, _ := output.String() // We know that "output" is a string type. + fmt.Printf("%v\n", msg) +} +{{< /code-tab >}}{{< /code-tabs >}} +{{< /step >}} + +## Run the program + +{{< step stepNumber="5" >}} +Add a dependency on `cuelang.org/go` and ensure the Go module is tidy: + +```text { title="TERMINAL" type="terminal" codeToCopy="Z28gZ2V0IGN1ZWxhbmcub3JnL2dvQHYwLjEwLjAKZ28gbW9kIHRpZHk=" } +$ go get cuelang.org/go@v0.10.0 +... +$ go mod tidy +... +``` +{{< /step >}} + +{{< step stepNumber="6" >}} +Run the program, +printing the same multi-line string value that `cue` produced earlier: + +```text { title="TERMINAL" type="terminal" codeToCopy="Z28gcnVuIC4=" } +$ go run . +Hello, Charlie! +How's the weather in your part of the world? +``` +{{< /step >}} + +## Related content + +- {{< linkto/related/concept "how-cue-works-with-go" >}} +- All pages tagged with {{< tag "go api" >}}