From 55ea20996f228d706e6bcb401f88b3f503e8172d Mon Sep 17 00:00:00 2001 From: "red-hat-konflux[bot]" <126015336+red-hat-konflux[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 20:12:38 +0000 Subject: [PATCH] NO-ISSUE: Update github.com/openshift/assisted-service/api digest to ed1e534 Signed-off-by: red-hat-konflux <126015336+red-hat-konflux[bot]@users.noreply.github.com> --- go.mod | 10 +- go.sum | 22 +- vendor/github.com/itchyny/gojq/.dockerignore | 9 + vendor/github.com/itchyny/gojq/.gitattributes | 2 + vendor/github.com/itchyny/gojq/.gitignore | 8 + vendor/github.com/itchyny/gojq/CHANGELOG.md | 314 +++ vendor/github.com/itchyny/gojq/Dockerfile | 12 + vendor/github.com/itchyny/gojq/LICENSE | 21 + vendor/github.com/itchyny/gojq/Makefile | 115 + vendor/github.com/itchyny/gojq/README.md | 152 ++ vendor/github.com/itchyny/gojq/_gojq | 32 + vendor/github.com/itchyny/gojq/builtin.go | 70 + vendor/github.com/itchyny/gojq/builtin.jq | 164 ++ vendor/github.com/itchyny/gojq/code.go | 108 + vendor/github.com/itchyny/gojq/compare.go | 104 + vendor/github.com/itchyny/gojq/compiler.go | 1506 +++++++++++++ vendor/github.com/itchyny/gojq/debug.go | 210 ++ vendor/github.com/itchyny/gojq/encoder.go | 193 ++ vendor/github.com/itchyny/gojq/env.go | 48 + vendor/github.com/itchyny/gojq/error.go | 340 +++ vendor/github.com/itchyny/gojq/execute.go | 453 ++++ vendor/github.com/itchyny/gojq/func.go | 1975 +++++++++++++++++ vendor/github.com/itchyny/gojq/go.dev.mod | 8 + vendor/github.com/itchyny/gojq/go.dev.sum | 4 + vendor/github.com/itchyny/gojq/gojq.go | 5 + vendor/github.com/itchyny/gojq/iter.go | 49 + vendor/github.com/itchyny/gojq/lexer.go | 573 +++++ vendor/github.com/itchyny/gojq/math.go | 8 + .../github.com/itchyny/gojq/module_loader.go | 190 ++ vendor/github.com/itchyny/gojq/normalize.go | 84 + vendor/github.com/itchyny/gojq/operator.go | 555 +++++ vendor/github.com/itchyny/gojq/option.go | 99 + vendor/github.com/itchyny/gojq/parser.go | 1739 +++++++++++++++ vendor/github.com/itchyny/gojq/parser.go.y | 693 ++++++ vendor/github.com/itchyny/gojq/preview.go | 77 + vendor/github.com/itchyny/gojq/query.go | 1170 ++++++++++ vendor/github.com/itchyny/gojq/release.go | 16 + vendor/github.com/itchyny/gojq/scope_stack.go | 52 + vendor/github.com/itchyny/gojq/stack.go | 56 + vendor/github.com/itchyny/gojq/term_type.go | 77 + vendor/github.com/itchyny/gojq/type.go | 30 + .../itchyny/timefmt-go/CHANGELOG.md | 14 + vendor/github.com/itchyny/timefmt-go/LICENSE | 21 + vendor/github.com/itchyny/timefmt-go/Makefile | 21 + .../github.com/itchyny/timefmt-go/README.md | 68 + .../github.com/itchyny/timefmt-go/format.go | 537 +++++ vendor/github.com/itchyny/timefmt-go/parse.go | 392 ++++ .../api/common/zz_generated.deepcopy.go | 4 +- .../v1beta1/agentclusterinstall_types.go | 99 +- .../v1beta1/zz_generated.deepcopy.go | 49 +- .../api/v1beta1/agent_types.go | 45 + .../api/v1beta1/agent_webhook.go | 88 + .../v1beta1/agentclassification_webhook.go | 98 + .../api/v1beta1/agentserviceconfig_types.go | 45 +- .../api/v1beta1/infraenv_types.go | 36 +- .../api/v1beta1/infraenv_webhook.go | 73 + .../api/v1beta1/zz_generated.deepcopy.go | 104 +- .../conditions/v1/conditions.go | 46 +- .../hive/apis/hive/v1/alibabacloud/doc.go | 4 + .../apis/hive/v1/alibabacloud/machinepool.go | 41 + .../apis/hive/v1/alibabacloud/platform.go | 16 + .../v1/alibabacloud/zz_generated.deepcopy.go | 44 + .../hive/apis/hive/v1/aws/machinepool.go | 37 +- .../hive/apis/hive/v1/aws/metadata.go | 8 + .../hive/apis/hive/v1/aws/platform.go | 16 + .../apis/hive/v1/aws/zz_generated.deepcopy.go | 76 +- .../openshift/hive/apis/hive/v1/azure/disk.go | 48 + .../hive/apis/hive/v1/azure/machinepool.go | 35 +- .../hive/apis/hive/v1/azure/metadata.go | 3 +- .../hive/apis/hive/v1/azure/platform.go | 2 +- .../hive/v1/azure/zz_generated.deepcopy.go | 49 +- .../hive/apis/hive/v1/clusterclaim_types.go | 10 + .../apis/hive/v1/clusterdeployment_types.go | 91 +- .../clusterdeploymentcustomization_types.go | 99 + .../apis/hive/v1/clusterdeprovision_types.go | 51 +- .../apis/hive/v1/clusterinstall_conditions.go | 22 +- .../hive/apis/hive/v1/clusterpool_types.go | 45 + .../apis/hive/v1/clusterprovision_types.go | 18 + .../openshift/hive/apis/hive/v1/conditions.go | 11 + .../hive/apis/hive/v1/dnszone_types.go | 10 + .../hive/apis/hive/v1/gcp/machinepools.go | 12 + .../hive/apis/hive/v1/gcp/metadata.go | 5 +- .../apis/hive/v1/gcp/zz_generated.deepcopy.go | 5 + .../hive/apis/hive/v1/hiveconfig_types.go | 43 +- .../hive/apis/hive/v1/ibmcloud/platform.go | 15 +- .../hive/apis/hive/v1/machinepool_types.go | 38 +- .../hive/apis/hive/v1/metricsconfig/doc.go | 4 + .../hive/v1/metricsconfig/duration_metrics.go | 41 + .../hive/v1/metricsconfig/metrics_config.go | 20 + .../v1/metricsconfig/zz_generated.deepcopy.go | 65 + .../openshift/hive/apis/hive/v1/none/doc.go | 4 + .../hive/apis/hive/v1/none/platform.go | 6 + .../hive/v1/none/zz_generated.deepcopy.go | 22 + .../hive/apis/hive/v1/syncset_types.go | 10 + .../hive/apis/hive/v1/vsphere/machinepools.go | 5 + .../apis/hive/v1/zz_generated.deepcopy.go | 327 +++ .../openshift/hive/apis/scheme/scheme.go | 45 +- vendor/modules.txt | 21 +- 98 files changed, 14358 insertions(+), 159 deletions(-) create mode 100644 vendor/github.com/itchyny/gojq/.dockerignore create mode 100644 vendor/github.com/itchyny/gojq/.gitattributes create mode 100644 vendor/github.com/itchyny/gojq/.gitignore create mode 100644 vendor/github.com/itchyny/gojq/CHANGELOG.md create mode 100644 vendor/github.com/itchyny/gojq/Dockerfile create mode 100644 vendor/github.com/itchyny/gojq/LICENSE create mode 100644 vendor/github.com/itchyny/gojq/Makefile create mode 100644 vendor/github.com/itchyny/gojq/README.md create mode 100644 vendor/github.com/itchyny/gojq/_gojq create mode 100644 vendor/github.com/itchyny/gojq/builtin.go create mode 100644 vendor/github.com/itchyny/gojq/builtin.jq create mode 100644 vendor/github.com/itchyny/gojq/code.go create mode 100644 vendor/github.com/itchyny/gojq/compare.go create mode 100644 vendor/github.com/itchyny/gojq/compiler.go create mode 100644 vendor/github.com/itchyny/gojq/debug.go create mode 100644 vendor/github.com/itchyny/gojq/encoder.go create mode 100644 vendor/github.com/itchyny/gojq/env.go create mode 100644 vendor/github.com/itchyny/gojq/error.go create mode 100644 vendor/github.com/itchyny/gojq/execute.go create mode 100644 vendor/github.com/itchyny/gojq/func.go create mode 100644 vendor/github.com/itchyny/gojq/go.dev.mod create mode 100644 vendor/github.com/itchyny/gojq/go.dev.sum create mode 100644 vendor/github.com/itchyny/gojq/gojq.go create mode 100644 vendor/github.com/itchyny/gojq/iter.go create mode 100644 vendor/github.com/itchyny/gojq/lexer.go create mode 100644 vendor/github.com/itchyny/gojq/math.go create mode 100644 vendor/github.com/itchyny/gojq/module_loader.go create mode 100644 vendor/github.com/itchyny/gojq/normalize.go create mode 100644 vendor/github.com/itchyny/gojq/operator.go create mode 100644 vendor/github.com/itchyny/gojq/option.go create mode 100644 vendor/github.com/itchyny/gojq/parser.go create mode 100644 vendor/github.com/itchyny/gojq/parser.go.y create mode 100644 vendor/github.com/itchyny/gojq/preview.go create mode 100644 vendor/github.com/itchyny/gojq/query.go create mode 100644 vendor/github.com/itchyny/gojq/release.go create mode 100644 vendor/github.com/itchyny/gojq/scope_stack.go create mode 100644 vendor/github.com/itchyny/gojq/stack.go create mode 100644 vendor/github.com/itchyny/gojq/term_type.go create mode 100644 vendor/github.com/itchyny/gojq/type.go create mode 100644 vendor/github.com/itchyny/timefmt-go/CHANGELOG.md create mode 100644 vendor/github.com/itchyny/timefmt-go/LICENSE create mode 100644 vendor/github.com/itchyny/timefmt-go/Makefile create mode 100644 vendor/github.com/itchyny/timefmt-go/README.md create mode 100644 vendor/github.com/itchyny/timefmt-go/format.go create mode 100644 vendor/github.com/itchyny/timefmt-go/parse.go create mode 100644 vendor/github.com/openshift/assisted-service/api/v1beta1/agent_webhook.go create mode 100644 vendor/github.com/openshift/assisted-service/api/v1beta1/agentclassification_webhook.go create mode 100644 vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_webhook.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/doc.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/machinepool.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/platform.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/zz_generated.deepcopy.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/azure/disk.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/conditions.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/duration_metrics.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/metrics_config.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/zz_generated.deepcopy.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/none/platform.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/none/zz_generated.deepcopy.go diff --git a/go.mod b/go.mod index a91ba313..cc57764d 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,8 @@ require ( github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.32.0 github.com/openshift/cluster-api-provider-agent/api v0.0.0-20240923230441-a40d69bd76be - github.com/openshift/custom-resource-status v1.1.2 - github.com/openshift/hive/apis v0.0.0-20220222213051-def9088fdb5a + github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 + github.com/openshift/hive/apis v0.0.0-20231220215202-ad99b9e52d27 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/thoas/go-funk v0.9.3 @@ -64,6 +64,8 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/imdario/mergo v0.3.16 // indirect + github.com/itchyny/gojq v0.12.8 // indirect + github.com/itchyny/timefmt-go v0.1.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -112,10 +114,10 @@ require ( ) replace ( - github.com/openshift/assisted-service/api => github.com/openshift/assisted-service/api v0.0.0-20240506174859-4577ef6f4cf1 + github.com/openshift/assisted-service/api => github.com/openshift/assisted-service/api v0.0.0-20251008122257-ed1e53465867 github.com/openshift/assisted-service/models => github.com/openshift/assisted-service/models v0.0.0-20240506174859-4577ef6f4cf1 github.com/openshift/cluster-api-provider-agent/api => ./api - + // CVE-2025-22868 // This is from tag v0.26.openshift.1 golang.org/x/oauth2 => github.com/openshift/golang-oauth2 v0.26.1-0.20250310184649-06a918c6239d diff --git a/go.sum b/go.sum index 04fd12fa..e7fb673a 100644 --- a/go.sum +++ b/go.sum @@ -234,6 +234,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -274,6 +275,10 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/itchyny/gojq v0.12.8 h1:Zxcwq8w4IeR8JJYEtoG2MWJZUv0RGY6QqJcO1cqV8+A= +github.com/itchyny/gojq v0.12.8/go.mod h1:gE2kZ9fVRU0+JAksaTzjIlgnCa2akU+a1V0WXgJQN5c= +github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU= +github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= @@ -312,6 +317,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -364,16 +371,16 @@ github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 h1:J1wuGhVxpsHykZBa6 github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= github.com/openshift/assisted-service v1.0.10-0.20240506174859-4577ef6f4cf1 h1:aIzWCog7xMizJF6zpvI48jbJ6/oxewayQYrhOeucbgc= github.com/openshift/assisted-service v1.0.10-0.20240506174859-4577ef6f4cf1/go.mod h1:6HPEu9ojkGtKZQtkR9Uk8GTGm9OxryQjrUYYpln1FSY= -github.com/openshift/assisted-service/api v0.0.0-20240506174859-4577ef6f4cf1 h1:dhuAkkV6V53w2TwX8bqPW0aEmYVM0roiAKTiv1mUk88= -github.com/openshift/assisted-service/api v0.0.0-20240506174859-4577ef6f4cf1/go.mod h1:PbxcQ9Cwxvp/l7hVEIkG5flQnfWSn4QEw6DmaTIqpM8= +github.com/openshift/assisted-service/api v0.0.0-20251008122257-ed1e53465867 h1:jPKkB5YRx7jO2SeXAw3yZXeNe680NrO+YVkQL7a7biU= +github.com/openshift/assisted-service/api v0.0.0-20251008122257-ed1e53465867/go.mod h1:wA7MaLcf/KoUl7fhB1bHBdhRBLjWPih90sHpxOV6ZLE= github.com/openshift/assisted-service/models v0.0.0-20240506174859-4577ef6f4cf1 h1:cfoG6S4uAwcWqgR8CCfK1H1u8j7iqRqgfZkryBwXp54= github.com/openshift/assisted-service/models v0.0.0-20240506174859-4577ef6f4cf1/go.mod h1:xd9WEj3m/k1cwZRyBTDa61BfDsHucQuArDsFgEFvv2s= -github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= -github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= +github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 h1:cHyxR+Y8rAMT6m1jQCaYGRwikqahI0OjjUDhFNf3ySQ= +github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= github.com/openshift/golang-oauth2 v0.26.1-0.20250310184649-06a918c6239d h1:iQfTKBmMcwFTxxVWV7U/C6GqgIIWTKD8l5HXslvn53s= github.com/openshift/golang-oauth2 v0.26.1-0.20250310184649-06a918c6239d/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -github.com/openshift/hive/apis v0.0.0-20220222213051-def9088fdb5a h1:E+XPJs/aVvYsrlJzo2ED38ZTR2RTNUlFMmOaFAAdMZg= -github.com/openshift/hive/apis v0.0.0-20220222213051-def9088fdb5a/go.mod h1:E1bgquRiwfugdArdecPbpYIrAdve5kTzMaJb0+8jMXI= +github.com/openshift/hive/apis v0.0.0-20231220215202-ad99b9e52d27 h1:9C86viyQl7HE9yg7Gctgx803Oq6DbrCUAberyMVcWDE= +github.com/openshift/hive/apis v0.0.0-20231220215202-ad99b9e52d27/go.mod h1:RRH8lt09SAiPECNdsbh7Gun0lkcRWi1nYKq6tDp5WxQ= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pin/tftp v2.1.0+incompatible/go.mod h1:xVpZOMCXTy+A5QMjEVN0Glwa1sUvaJhFXbr/aAxuxGY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -391,6 +398,7 @@ github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lne github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -597,11 +605,13 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-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-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-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.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/vendor/github.com/itchyny/gojq/.dockerignore b/vendor/github.com/itchyny/gojq/.dockerignore new file mode 100644 index 00000000..c8e02dc8 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/.dockerignore @@ -0,0 +1,9 @@ +/gojq +/goxz +/CREDITS +/._* +/y.output +*.exe +*.test +*.out +/.github/ diff --git a/vendor/github.com/itchyny/gojq/.gitattributes b/vendor/github.com/itchyny/gojq/.gitattributes new file mode 100644 index 00000000..9c2075be --- /dev/null +++ b/vendor/github.com/itchyny/gojq/.gitattributes @@ -0,0 +1,2 @@ +**/testdata/** binary +/builtin.go eol=lf diff --git a/vendor/github.com/itchyny/gojq/.gitignore b/vendor/github.com/itchyny/gojq/.gitignore new file mode 100644 index 00000000..e350f930 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/.gitignore @@ -0,0 +1,8 @@ +/gojq +/goxz +/CREDITS +/._* +/y.output +*.exe +*.test +*.out diff --git a/vendor/github.com/itchyny/gojq/CHANGELOG.md b/vendor/github.com/itchyny/gojq/CHANGELOG.md new file mode 100644 index 00000000..c9ad1d7e --- /dev/null +++ b/vendor/github.com/itchyny/gojq/CHANGELOG.md @@ -0,0 +1,314 @@ +# Changelog +## [v0.12.8](https://github.com/itchyny/gojq/compare/v0.12.7..v0.12.8) (2022-06-01) +* implement `gojq.Compare` for comparing values in custom internal functions +* implement `gojq.TypeOf` for obtaining type name of values in custom internal functions +* implement `gojq.Preview` for previewing values for error messages of custom internal functions +* fix query lexer to parse string literals as JSON to support surrogate pairs (`"\ud83d\ude04"`) +* fix priority bug of declared and builtin functions (`def empty: .; null | select(.)`) +* fix string indexing by index out of bounds to emit `null` (`"abc" | .[3]`) +* fix array binding pattern not to match against strings (`"abc" as [$a] ?// $a | $a`) +* fix `sub` and `gsub` functions to emit results in the same order of jq +* fix `fromjson` to keep integer precision (`"10000000000000000" | fromjson + 1`) +* fix stream option to raise error against incomplete JSON input +* improve array updating index and string repetition to increase limitations +* improve `mktime` to support nanoseconds, just like `gmtime` and `now` +* improve query lexer to report unterminated string literals +* improve performance of string indexing and slicing by reducing allocations +* improve performance of object and array indexing, slicing, and iteration, + by validating path values by comparing data addresses. This change improves jq + compatibility of path value validation (`{} | {}.x = 0`, `[0] | [.[]][] = 1`). + Also optimize constant indexing and slicing by specialized instruction +* improve performance of `add` (on array of strings), `flatten`, `min`, `max`, + `sort`, `unique`, `join`, `to_entries`, `from_entries`, `indices`, `index`, + `rindex`, `startswith`, `endswith`, `ltrimstr`, `rtrimstr`, `explode`, + `capture`, `sub`, and `gsub` functions + +## [v0.12.7](https://github.com/itchyny/gojq/compare/v0.12.6..v0.12.7) (2022-03-01) +* fix precedence of try expression against operators (`try 0 * error(0)`) +* fix iterator suffix with optional operator (`0 | .x[]?`) +* fix stream option with slurp option or `input`, `inputs` functions +* fix the command flag parser to support equal sign in short options with argument +* fix string conversion of query including empty strings in module and import metadata +* improve performance of `isempty` function + +## [v0.12.6](https://github.com/itchyny/gojq/compare/v0.12.5..v0.12.6) (2021-12-01) +* implement options for consuming remaining arguments (`--args`, `--jsonargs`, `$ARGS.positional`) +* fix `delpaths` function with overlapped paths +* fix `--exit-status` flag with `halt`, `halt_error` functions +* fix `input_filename` function with null input option +* fix path value validation for `nan` +* fix crash on branch optimization (`if 0 then . else 0|0 end`) +* add validation on regular expression flags to reject unsupported ones +* improve performance of `range`, `join`, `flatten` functions +* improve constant value optimization for object with quoted keys +* remove dependency on forked `go-flags` package + +## [v0.12.5](https://github.com/itchyny/gojq/compare/v0.12.4..v0.12.5) (2021-09-01) +* implement `input_filename` function for the command +* fix priority bug of declared functions and arguments (`def g: 1; def f(g): g; f(2)`) +* fix label handling to catch the correct break error (`first((0, 0) | first(0))`) +* fix `null|error` and `error(null)` to behave like `empty` (`null | [0, error, error(null), 1]`) +* fix integer division to keep precision when divisible (`1 / 1 * 1000000000000000000000`) +* fix modulo operator on negative number and large number (`(-1) % 10000000000`) +* fix combination of slurp (`--slurp`) and raw input option (`--raw-input`) to keep newlines +* change the default module paths to `~/.jq`, `$ORIGIN/../lib/gojq`, `$ORIGIN/lib` + where `$ORIGIN` is the directory where the executable is located in +* improve command argument parser to recognize query with leading hyphen, + allow hyphen for standard input, and force posix style on Windows +* improve `@base64d` to allow input without padding characters +* improve `fromdate`, `fromdateiso8601` to parse date time strings with timezone offset +* improve `halt_error` to print error values without prefix +* improve `sub`, `gsub` to allow the replacement string emitting multiple values +* improve encoding `\b` and `\f` in strings +* improve module loader for search path in query, and absolute path +* improve query lexer to support string literal including newlines +* improve performance of `index`, `rindex`, `indices`, `transpose`, and `walk` functions +* improve performance of value preview in errors and debug mode +* improve runtime performance including tail call optimization +* switch Docker base image to `distroless/static:debug` + +## [v0.12.4](https://github.com/itchyny/gojq/compare/v0.12.3..v0.12.4) (2021-06-01) +* fix numeric conversion of large floating-point numbers in modulo operator +* implement a compiler option for adding custom iterator functions +* implement `gojq.NewIter` function for creating a new iterator from values +* implement `$ARGS.named` for listing command line variables +* remove `debug` and `stderr` functions from the library +* stop printing newlines on `stderr` function for jq compatibility + +## [v0.12.3](https://github.com/itchyny/gojq/compare/v0.12.2..v0.12.3) (2021-04-01) +* fix array slicing with infinities and large numbers (`[0][-infinite:infinite], [0][:1e20]`) +* fix multiplying strings and modulo by infinities on MIPS 64 architecture +* fix git revision information in Docker images +* release multi-platform Docker images for ARM 64 +* switch to `distroless` image for Docker base image + +## [v0.12.2](https://github.com/itchyny/gojq/compare/v0.12.1..v0.12.2) (2021-03-01) +* implement `GOJQ_COLORS` environment variable to configure individual colors +* respect `--color-output` (`-C`) option even if `NO_COLOR` is set +* implement `gojq.ValueError` interface for custom internal functions +* fix crash on timestamps in YAML input +* fix calculation on `infinite` (`infinite-infinite | isnan`) +* fix comparison on `nan` (`nan < nan`) +* fix validation of `implode` (`[-1] | implode`) +* fix number normalization for custom JSON module loader +* print error line numbers on invalid JSON and YAML +* improve `strftime`, `strptime` for time zone offsets +* improve performance on reading a large JSON file given by command line argument +* improve performance and reduce memory allocation of the lexer, compiler and executor + +## [v0.12.1](https://github.com/itchyny/gojq/compare/v0.12.0..v0.12.1) (2021-01-17) +* skip adding `$HOME/.jq` to module paths when `$HOME` is unset +* fix optional operator followed by division operator (`1?/1`) +* fix undefined format followed by optional operator (`@foo?`) +* fix parsing invalid consecutive dots while scanning a number (`0..[empty]`) +* fix panic on printing a query with `%#v` +* improve performance and reduce memory allocation of `query.String()` +* change all methods of `ModuleLoader` optional + +## [v0.12.0](https://github.com/itchyny/gojq/compare/v0.11.2..v0.12.0) (2020-12-24) +* implement tab indentation option (`--tab`) +* implement a compiler option for adding custom internal functions +* implement `gojq.Marshal` function for jq-flavored encoding +* fix slurp option with JSON file arguments +* fix escaping characters in object keys +* fix normalizing negative `int64` to `int` on 32-bit architecture +* fix crash on continuing iteration after emitting an error +* `iter.Next()` does not normalize `NaN` and infinities anymore. Library users + should take care of them. To handle them for encoding as JSON bytes, use + `gojq.Marshal`. Also, `iter.Next()` does not clone values deeply anymore for + performance reason. Users must not update the elements of the returned arrays + and objects +* improve performance of outputting JSON values by about 3.5 times + +## [v0.11.2](https://github.com/itchyny/gojq/compare/v0.11.1..v0.11.2) (2020-10-01) +* fix build for 32bit architecture +* release to [GitHub Container Registry](https://github.com/users/itchyny/packages/container/package/gojq) + +## [v0.11.1](https://github.com/itchyny/gojq/compare/v0.11.0..v0.11.1) (2020-08-22) +* improve compatibility of `strftime`, `strptime` functions with jq +* fix YAML input with numbers in keys +* fix crash on multiplying a large number or `infinite` to a string +* fix crash on error while slicing a string (`""[:{}]`) +* fix crash on modulo by a number near 0.0 (`1 % 0.1`) +* include `CREDITS` file in artifacts + +## [v0.11.0](https://github.com/itchyny/gojq/compare/v0.10.4..v0.11.0) (2020-07-08) +* improve parsing performance significantly +* rewrite the parser from `participle` library to `goyacc` generated parser +* release to [itchyny/gojq - Docker Hub](https://hub.docker.com/r/itchyny/gojq) +* support string interpolation for object pattern key + +## [v0.10.4](https://github.com/itchyny/gojq/compare/v0.10.3..v0.10.4) (2020-06-30) +* implement variable in object key (`. as $x | { $x: 1 }`) +* fix modify operator (`|=`) with `try` `catch` expression +* fix optional operator (`?`) with alternative operator (`//`) in `map_values` function +* fix normalizing numeric types for library users +* export `gojq.NewModuleLoader` function for library users + +## [v0.10.3](https://github.com/itchyny/gojq/compare/v0.10.2..v0.10.3) (2020-06-06) +* implement `add`, `unique_by`, `max_by`, `min_by`, `reverse` by internal + functions for performance and reducing the binary size +* improve performance of `setpath`, `delpaths` functions +* fix assignment against nested slicing (`[1,2,3] | .[1:][:1] = [5]`) +* limit the array index of assignment operator +* optimize constant arrays and objects + +## [v0.10.2](https://github.com/itchyny/gojq/compare/v0.10.1..v0.10.2) (2020-05-24) +* implement `sort_by`, `group_by`, `bsearch` by internal functions for performance + and reducing the binary size +* fix object construction and constant object to allow trailing commas +* fix `tonumber` function to allow leading zeros +* minify the builtin functions to reduce the binary size + +## [v0.10.1](https://github.com/itchyny/gojq/compare/v0.10.0..v0.10.1) (2020-04-24) +* fix array addition not to modify the left hand side + +## [v0.10.0](https://github.com/itchyny/gojq/compare/v0.9.0..v0.10.0) (2020-04-02) +* implement various functions (`format`, `significand`, `modulemeta`, `halt_error`) +* implement `input`, `inputs` functions +* implement stream option (`--stream`) +* implement slicing with object (`.[{"start": 1, "end": 2}]`) +* implement `NO_COLOR` environment variable support +* implement `nul` output option (`-0`, `--nul-output`) +* implement exit status option (`-e`, `--exit-status`) +* implement `search` field of module meta object +* implement combination of `--yaml-input` and `--slurp` +* improve string token lexer and support nested string interpolation +* improve the exit code for jq compatibility +* improve default module search paths for jq compatibility +* improve documentation for the usage as a library +* change methods of `ModuleLoader` optional, implement `LoadModuleWithMeta` and `LoadJSONWithMeta` +* fix number normalization for JSON arguments (`--argjson`, `--slurpfile`) +* fix `0/0` and `infinite/infinite` +* fix `error` function against `null` + +## [v0.9.0](https://github.com/itchyny/gojq/compare/v0.8.0..v0.9.0) (2020-03-15) +* implement various functions (`infinite`, `isfinite`, `isinfinite`, `finites`, `isnormal`, `normals`) +* implement environment variables loader as a compiler option +* implement `$NAME::NAME` syntax for imported JSON variable +* fix modify operator with empty against array (`[range(9)] | (.[] | select(. % 2 > 0)) |= empty`) +* fix variable and function scopes (`{ x: 1 } | . as $x | (.x as $x | $x) | ., $x`) +* fix path analyzer +* fix type check in `startswith` and `endswith` +* ignore type error of `ltrimstr` and `rtrimstr` +* remove nano seconds from `mktime` output +* trim newline at the end of error messages +* improve documents and examples + +## [v0.8.0](https://github.com/itchyny/gojq/compare/v0.7.0..v0.8.0) (2020-03-02) +* implement format strings (`@text`, `@json`, `@html`, `@uri`, `@csv`, `@tsv`, + `@sh`, `@base64`, `@base64d`) +* implement modules feature (`-L` option for directory to search modules from) +* implement options for binding variables from arguments (`--arg`, `--argjson`) +* implement options for binding variables from files (`--slurpfile`, `--rawfile`) +* implement an option for indentation count (`--indent`) +* fix `isnan` for `null` +* fix path analyzer +* fix error after optional operator (`1? | .x`) +* add `$ENV` variable +* add zsh completion file + +## [v0.7.0](https://github.com/itchyny/gojq/compare/v0.6.0..v0.7.0) (2019-12-22) +* implement YAML input (`--yaml-input`) and output (`--yaml-output`) +* fix pipe in object value +* fix precedence of if, try, reduce and foreach expressions +* release from GitHub Actions + +## [v0.6.0](https://github.com/itchyny/gojq/compare/v0.5.0..v0.6.0) (2019-08-26) +* implement arbitrary-precision integer calculation +* implement various functions (`repeat`, `pow10`, `nan`, `isnan`, `nearbyint`, + `halt`, `INDEX`, `JOIN`, `IN`) +* implement long options (`--compact-output`, `--raw-output`, `--join-output`, + `--color-output`, `--monochrome-output`, `--null-input`, `--raw-input`, + `--slurp`, `--from-file`, `--version`) +* implement join output options (`-j`, `--join-output`) +* implement color/monochrome output options (`-C`, `--color-output`, + `-M`, `--monochrome-output`) +* refactor builtin functions + +## [v0.5.0](https://github.com/itchyny/gojq/compare/v0.4.0..v0.5.0) (2019-08-03) +* implement various functions (`with_entries`, `from_entries`, `leaf_paths`, + `contains`, `inside`, `split`, `stream`, `fromstream`, `truncate_stream`, + `bsearch`, `path`, `paths`, `map_values`, `del`, `delpaths`, `getpath`, + `gmtime`, `localtime`, `mktime`, `strftime`, `strflocaltime`, `strptime`, + `todate`, `fromdate`, `now`, `match`, `test`, `capture`, `scan`, `splits`, + `sub`, `gsub`, `debug`, `stderr`) +* implement assignment operator (`=`) +* implement modify operator (`|=`) +* implement update operators (`+=`, `-=`, `*=`, `/=`, `%=`, `//=`) +* implement destructuring alternative operator (`?//`) +* allow function declaration inside query +* implement `-f` flag for loading query from file +* improve error message for parsing multiple line query + +## [v0.4.0](https://github.com/itchyny/gojq/compare/v0.3.0..v0.4.0) (2019-07-20) +* improve performance significantly +* rewrite from recursive interpreter to stack machine based interpreter +* allow debugging with `make install-debug` and `export GOJQ_DEBUG=1` +* parse built-in functions and generate syntax trees before compilation +* optimize tail recursion +* fix behavior of optional operator +* fix scopes of arguments of recursive function call +* fix duplicate function argument names +* implement `setpath` function + +## [v0.3.0](https://github.com/itchyny/gojq/compare/v0.2.0..v0.3.0) (2019-06-05) +* implement `reduce`, `foreach`, `label`, `break` syntax +* improve binding variable syntax to bind to an object or an array +* implement string interpolation +* implement object index by string (`."example"`) +* implement various functions (`add`, `flatten`, `min`, `min_by`, `max`, + `max_by`, `sort`, `sort_by`, `group_by`, `unique`, `unique_by`, `tostring`, + `indices`, `index`, `rindex`, `walk`, `transpose`, `first`, `last`, `nth`, + `limit`, `all`, `any`, `isempty`, `error`, `builtins`, `env`) +* implement math functions (`sin`, `cos`, `tan`, `asin`, `acos`, `atan`, + `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `floor`, `round`, + `rint`, `ceil`, `trunc`, `fabs`, `sqrt`, `cbrt`, `exp`, `exp10`, `exp2`, + `expm1`, `frexp`, `modf`, `log`, `log10`, `log1p`, `log2`, `logb`, + `gamma`, `tgamma`, `lgamma`, `erf`, `erfc`, `j0`, `j1`, `y0`, `y1`, + `atan2/2`, `copysign/2`, `drem/2`, `fdim/2`, `fmax/2`, `fmin/2`, `fmod/2`, + `hypot/2`, `jn/2`, `ldexp/2`, `nextafter/2`, `nexttoward/2`, `remainder/2`, + `scalb/2`, `scalbln/2`, `pow/2`, `yn/2`, `fma/3`) +* support object construction with variables +* support indexing against strings +* fix function evaluation for recursive call +* fix error handling of `//` operator +* fix string representation of NaN and Inf +* implement `-R` flag for reading input as raw strings +* implement `-c` flag for compact output +* implement `-n` flag for using null as input value +* implement `-r` flag for outputting raw string +* implement `-s` flag for reading all inputs into an array + +## [v0.2.0](https://github.com/itchyny/gojq/compare/v0.1.0..v0.2.0) (2019-05-06) +* implement binding variable syntax (`... as $var`) +* implement `try` `catch` syntax +* implement alternative operator (`//`) +* implement various functions (`in`, `to_entries`, `startswith`, `endswith`, + `ltrimstr`, `rtrimstr`, `combinations`, `ascii_downcase`, `ascii_upcase`, + `tojson`, `fromjson`) +* support query for object indexing +* support object construction with variables +* support indexing against strings + +## [v0.1.0](https://github.com/itchyny/gojq/compare/v0.0.1..v0.1.0) (2019-05-02) +* implement binary operators (`+`, `-`, `*`, `/`, `%`, `==`, `!=`, `>`, `<`, + `>=`, `<=`, `and`, `or`) +* implement unary operators (`+`, `-`) +* implement booleans (`false`, `true`), `null`, number and string constant + values +* implement `empty` value +* implement conditional syntax (`if` `then` `elif` `else` `end`) +* implement various functions (`length`, `utf8bytelength`, `not`, `keys`, + `has`, `map`, `select`, `recurse`, `while`, `until`, `range`, `tonumber`, + `type`, `arrays`, `objects`, `iterables`, `booleans`, `numbers`, `strings`, + `nulls`, `values`, `scalars`, `reverse`, `explode`, `implode`, `join`) +* support function declaration +* support iterators in object keys +* support object construction shortcut +* support query in array indices +* support negative number indexing against arrays +* support json file name arguments + +## [v0.0.1](https://github.com/itchyny/gojq/compare/0fa3241..v0.0.1) (2019-04-14) +* initial implementation diff --git a/vendor/github.com/itchyny/gojq/Dockerfile b/vendor/github.com/itchyny/gojq/Dockerfile new file mode 100644 index 00000000..dfe416b1 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.18 AS builder + +WORKDIR /app +COPY . . +ENV CGO_ENABLED 0 +RUN make build + +FROM gcr.io/distroless/static:debug + +COPY --from=builder /app/gojq / +ENTRYPOINT ["/gojq"] +CMD ["--help"] diff --git a/vendor/github.com/itchyny/gojq/LICENSE b/vendor/github.com/itchyny/gojq/LICENSE new file mode 100644 index 00000000..e3fc027c --- /dev/null +++ b/vendor/github.com/itchyny/gojq/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2022 itchyny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/itchyny/gojq/Makefile b/vendor/github.com/itchyny/gojq/Makefile new file mode 100644 index 00000000..b8e0de77 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/Makefile @@ -0,0 +1,115 @@ +BIN := gojq +VERSION := $$(make -s show-version) +VERSION_PATH := cli +CURRENT_REVISION := $(shell git rev-parse --short HEAD) +BUILD_LDFLAGS := "-s -w -X github.com/itchyny/$(BIN)/cli.revision=$(CURRENT_REVISION)" +GOBIN ?= $(shell go env GOPATH)/bin +SHELL := /bin/bash + +.PHONY: all +all: build + +.PHONY: build +build: + go build -ldflags=$(BUILD_LDFLAGS) -o $(BIN) ./cmd/$(BIN) + +.PHONY: build-dev +build-dev: parser.go builtin.go + go build -ldflags=$(BUILD_LDFLAGS) -o $(BIN) ./cmd/$(BIN) + +.PHONY: build-debug +build-debug: parser.go builtin.go + go build -tags gojq_debug -ldflags=$(BUILD_LDFLAGS) -o $(BIN) ./cmd/$(BIN) + +builtin.go: builtin.jq parser.go.y parser.go query.go operator.go _tools/* + GOOS= GOARCH= go generate + +.SUFFIXES: +parser.go: parser.go.y $(GOBIN)/goyacc + goyacc -o $@ $< + +$(GOBIN)/goyacc: + @go install golang.org/x/tools/cmd/goyacc@latest + +.PHONY: install +install: + go install -ldflags=$(BUILD_LDFLAGS) ./... + +.PHONY: install-dev +install-dev: parser.go builtin.go + go install -ldflags=$(BUILD_LDFLAGS) ./... + +.PHONY: install-debug +install-debug: parser.go builtin.go + go install -tags gojq_debug -ldflags=$(BUILD_LDFLAGS) ./... + +.PHONY: show-version +show-version: $(GOBIN)/gobump + @gobump show -r $(VERSION_PATH) + +$(GOBIN)/gobump: + @go install github.com/x-motemen/gobump/cmd/gobump@latest + +.PHONY: cross +cross: $(GOBIN)/goxz CREDITS + goxz -n $(BIN) -pv=v$(VERSION) -include _$(BIN) \ + -build-ldflags=$(BUILD_LDFLAGS) ./cmd/$(BIN) + +$(GOBIN)/goxz: + go install github.com/Songmu/goxz/cmd/goxz@latest + +CREDITS: $(GOBIN)/gocredits go.sum + go mod tidy + gocredits -w . + +$(GOBIN)/gocredits: + go install github.com/Songmu/gocredits/cmd/gocredits@latest + +.PHONY: test +test: build + go test -v -race ./... + +.PHONY: lint +lint: $(GOBIN)/staticcheck + go vet ./... + staticcheck -checks all,-ST1000 -tags gojq_debug ./... + +$(GOBIN)/staticcheck: + go install honnef.co/go/tools/cmd/staticcheck@latest + +.PHONY: check-tools +check-tools: + go run _tools/print_builtin.go + +.PHONY: clean +clean: + rm -rf $(BIN) goxz CREDITS + go clean + +.PHONY: update +update: export GOPROXY=direct +update: + go get -u -d ./... && go mod tidy + go mod edit -modfile=go.dev.mod -droprequire=github.com/itchyny/{astgen,timefmt}-go + go get -u -d -modfile=go.dev.mod github.com/itchyny/{astgen,timefmt}-go && go generate + +.PHONY: bump +bump: $(GOBIN)/gobump +ifneq ($(shell git status --porcelain),) + $(error git workspace is dirty) +endif +ifneq ($(shell git rev-parse --abbrev-ref HEAD),main) + $(error current branch is not main) +endif + @gobump up -w "$(VERSION_PATH)" + git commit -am "bump up version to $(VERSION)" + git tag "v$(VERSION)" + git push origin main + git push origin "refs/tags/v$(VERSION)" + +.PHONY: upload +upload: $(GOBIN)/ghr + ghr "v$(VERSION)" goxz + +$(GOBIN)/ghr: + go install github.com/tcnksm/ghr@latest diff --git a/vendor/github.com/itchyny/gojq/README.md b/vendor/github.com/itchyny/gojq/README.md new file mode 100644 index 00000000..4037b868 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/README.md @@ -0,0 +1,152 @@ +# gojq +[![CI Status](https://github.com/itchyny/gojq/workflows/CI/badge.svg)](https://github.com/itchyny/gojq/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/itchyny/gojq)](https://goreportcard.com/report/github.com/itchyny/gojq) +[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/itchyny/gojq/blob/main/LICENSE) +[![release](https://img.shields.io/github/release/itchyny/gojq/all.svg)](https://github.com/itchyny/gojq/releases) +[![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/gojq)](https://pkg.go.dev/github.com/itchyny/gojq) + +### Pure Go implementation of [jq](https://github.com/stedolan/jq) +This is an implementation of jq command written in Go language. +You can also embed gojq as a library to your Go products. + +## Usage +```sh + $ echo '{"foo": 128}' | gojq '.foo' +128 + $ echo '{"a": {"b": 42}}' | gojq '.a.b' +42 + $ echo '{"id": "sample", "10": {"b": 42}}' | gojq '{(.id): .["10"].b}' +{ + "sample": 42 +} + $ echo '[{"id":1},{"id":2},{"id":3}]' | gojq '.[] | .id' +1 +2 +3 + $ echo '{"a":1,"b":2}' | gojq '.a += 1 | .b *= 2' +{ + "a": 2, + "b": 4 +} + $ echo '{"a":1} [2] 3' | gojq '. as {$a} ?// [$a] ?// $a | $a' +1 +2 +3 + $ echo '{"foo": 4722366482869645213696}' | gojq .foo +4722366482869645213696 # keeps the precision of large numbers + $ gojq -n 'def fact($n): if $n < 1 then 1 else $n * fact($n - 1) end; fact(50)' +30414093201713378043612608166064768844377641568960512000000000000 # arbitrary-precision integer calculation +``` + +Nice error messages. +```sh + $ echo '[1,2,3]' | gojq '.foo & .bar' +gojq: invalid query: .foo & .bar + .foo & .bar + ^ unexpected token "&" + $ echo '{"foo": { bar: [] } }' | gojq '.' +gojq: invalid json: + {"foo": { bar: [] } } + ^ invalid character 'b' looking for beginning of object key string +``` + +## Installation +### Homebrew +```sh +brew install gojq +``` + +### Zero Install +```sh +0install add gojq https://apps.0install.net/utils/gojq.xml +``` + +### Build from source +```sh +go install github.com/itchyny/gojq/cmd/gojq@latest +``` + +### Docker +```sh +docker run -i --rm itchyny/gojq +docker run -i --rm ghcr.io/itchyny/gojq +``` + +## Difference to jq +- gojq is purely implemented with Go language and is completely portable. jq depends on the C standard library so the availability of math functions depends on the library. jq also depends on the regular expression library and it makes build scripts complex. +- gojq implements nice error messages for invalid query and JSON input. The error message of jq is sometimes difficult to tell where to fix the query. +- gojq does not keep the order of object keys. I understand this might cause problems for some scripts but basically, we should not rely on the order of object keys. Due to this limitation, gojq does not have `keys_unsorted` function and `--sort-keys` (`-S`) option. I would implement when ordered map is implemented in the standard library of Go but I'm less motivated. +- gojq supports arbitrary-precision integer calculation while jq does not; jq looses the precision of large integers when calculation is involved. Note that even with gojq, all mathematical functions, including `floor` and `round`, convert integers to floating-point numbers; only addition, subtraction, multiplication, modulo, and division operators (when divisible) keep the integer precision. To calculate floor division of integers without loosing the precision, use `def idivide($n): (. - . % $n) / $n;`. To round down floating-point numbers to integers, use `def ifloor: floor | tostring | tonumber;`, but note that this function does not work with large floating-point numbers and also looses the precision of large integers. +- gojq fixes various bugs of jq. gojq correctly deletes elements of arrays by `|= empty` ([jq#2051](https://github.com/stedolan/jq/issues/2051)). gojq fixes `try`/`catch` handling ([jq#1859](https://github.com/stedolan/jq/issues/1859), [jq#1885](https://github.com/stedolan/jq/issues/1885), [jq#2140](https://github.com/stedolan/jq/issues/2140)). gojq fixes `nth/2` to output nothing when the count is equal to or larger than the stream size ([jq#1867](https://github.com/stedolan/jq/issues/1867)). gojq consistently counts by characters (not by bytes) in `index`, `rindex`, and `indices` functions; `"12345" | .[index("3"):]` results in `"345"` ([jq#1430](https://github.com/stedolan/jq/issues/1430), [jq#1624](https://github.com/stedolan/jq/issues/1624)). gojq handles overlapping occurrence differently in `rindex` and `indices`; `"ababa" | [rindex("aba"), indices("aba")]` results in `[2,[0,2]]` ([jq#2433](https://github.com/stedolan/jq/issues/2433)). gojq supports string indexing; `"abcde"[2]` ([jq#1520](https://github.com/stedolan/jq/issues/1520)). gojq accepts indexing query `.e0` ([jq#1526](https://github.com/stedolan/jq/issues/1526), [jq#1651](https://github.com/stedolan/jq/issues/1651)), and allows `gsub` to handle patterns including `"^"` ([jq#2148](https://github.com/stedolan/jq/issues/2148)). gojq improves variable lexer to allow using keywords for variable names, especially in binding patterns, also disallows spaces after `$` ([jq#526](https://github.com/stedolan/jq/issues/526)). gojq fixes handling files with no newline characters at the end ([jq#2374](https://github.com/stedolan/jq/issues/2374)). +- gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/stedolan/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/stedolan/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/stedolan/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/stedolan/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/stedolan/jq/issues/929), [jq#2195](https://github.com/stedolan/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/stedolan/jq/issues/1912)). gojq supports nanoseconds in date and time functions. +- gojq does not support some functions intentionally; `get_jq_origin`, `get_prog_origin`, `get_search_list` (unstable, not listed in jq document), `input_line_number`, `$__loc__` (performance issue), `recurse_down` (deprecated in jq). gojq does not support some flags; `--ascii-output, -a` (performance issue), `--seq` (not used commonly), `--sort-keys, -S` (sorts by default because `map[string]interface{}` does not keep the order), `--unbuffered` (unbuffered by default). gojq does not parse JSON extensions supported by jq; `NaN`, `Infinity`, and `[000]`. gojq normalizes floating-point numbers to fit to double-precision floating-point numbers. gojq does not support some regular expression flags (regular expression engine differences). gojq does not support BOM (`encoding/json` does not support this). gojq disallows using keywords for function names (declaration of `def true: .;` is a confusing query). +- gojq supports reading from YAML input (`--yaml-input`) while jq does not. gojq also supports YAML output (`--yaml-output`). + +### Color configuration +The gojq command automatically disables coloring output when the output is not a tty. +To force coloring output, specify `--color-output` (`-C`) option. +When [`NO_COLOR` environment variable](https://no-color.org/) is present or `--monochrome-output` (`-M`) option is specified, gojq disables coloring output. + +Use `GOJQ_COLORS` environment variable to configure individual colors. +The variable is a colon-separated list of ANSI escape sequences of `null`, `false`, `true`, numbers, strings, object keys, arrays, and objects. +The default configuration is `90:33:33:36:32:34;1`. + +## Usage as a library +You can use the gojq parser and interpreter from your Go products. + +```go +package main + +import ( + "fmt" + "log" + + "github.com/itchyny/gojq" +) + +func main() { + query, err := gojq.Parse(".foo | ..") + if err != nil { + log.Fatalln(err) + } + input := map[string]interface{}{"foo": []interface{}{1, 2, 3}} + iter := query.Run(input) // or query.RunWithContext + for { + v, ok := iter.Next() + if !ok { + break + } + if err, ok := v.(error); ok { + log.Fatalln(err) + } + fmt.Printf("%#v\n", v) + } +} +``` + +- Firstly, use [`gojq.Parse(string) (*Query, error)`](https://pkg.go.dev/github.com/itchyny/gojq#Parse) to get the query from a string. +- Secondly, get the result iterator + - using [`query.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Query.Run) or [`query.RunWithContext`](https://pkg.go.dev/github.com/itchyny/gojq#Query.RunWithContext) + - or alternatively, compile the query using [`gojq.Compile`](https://pkg.go.dev/github.com/itchyny/gojq#Compile) and then [`code.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Code.Run) or [`code.RunWithContext`](https://pkg.go.dev/github.com/itchyny/gojq#Code.RunWithContext). You can reuse the `*Code` against multiple inputs to avoid compilation of the same query. + - In either case, you cannot use custom type values as the query input. The type should be `[]interface{}` for an array and `map[string]interface{}` for a map (just like decoded to an `interface{}` using the [encoding/json](https://golang.org/pkg/encoding/json/) package). You can't use `[]int` or `map[string]string`, for example. If you want to query your custom struct, marshal to JSON, unmarshal to `interface{}` and use it as the query input. +- Thirdly, iterate through the results using [`iter.Next() (interface{}, bool)`](https://pkg.go.dev/github.com/itchyny/gojq#Iter). The iterator can emit an error so make sure to handle it. The method returns `true` with results, and `false` when the iterator terminates. + - The return type is not `(interface{}, error)` because iterators can emit multiple errors and you can continue after an error. It is difficult for the iterator to tell the termination in this situation. + - Note that the result iterator may emit infinite number of values; `repeat(0)` and `range(infinite)`. It may stuck with no output value; `def f: f; f`. Use `RunWithContext` when you want to limit the execution time. + +[`gojq.Compile`](https://pkg.go.dev/github.com/itchyny/gojq#Compile) allows to configure the following compiler options. + +- [`gojq.WithModuleLoader`](https://pkg.go.dev/github.com/itchyny/gojq#WithModuleLoader) allows to load modules. By default, the module feature is disabled. If you want to load modules from the file system, use [`gojq.NewModuleLoader`](https://pkg.go.dev/github.com/itchyny/gojq#NewModuleLoader). +- [`gojq.WithEnvironLoader`](https://pkg.go.dev/github.com/itchyny/gojq#WithEnvironLoader) allows to configure the environment variables referenced by `env` and `$ENV`. By default, OS environment variables are not accessible due to security reasons. You can use `gojq.WithEnvironLoader(os.Environ)` if you want. +- [`gojq.WithVariables`](https://pkg.go.dev/github.com/itchyny/gojq#WithVariables) allows to configure the variables which can be used in the query. Pass the values of the variables to [`code.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Code.Run) in the same order. +- [`gojq.WithFunction`](https://pkg.go.dev/github.com/itchyny/gojq#WithFunction) allows to add a custom internal function. An internal function can return a single value (which can be an error) each invocation. To add a jq function (which may include a comma operator to emit multiple values, `empty` function, accept a filter for its argument, or call another built-in function), use `LoadInitModules` of the module loader. +- [`gojq.WithIterFunction`](https://pkg.go.dev/github.com/itchyny/gojq#WithIterFunction) allows to add a custom iterator function. An iterator function returns an iterator to emit multiple values. You cannot define both iterator and non-iterator functions of the same name (with possibly different arities). You can use [`gojq.NewIter`](https://pkg.go.dev/github.com/itchyny/gojq#NewIter) to convert values or an error to a [`gojq.Iter`](https://pkg.go.dev/github.com/itchyny/gojq#Iter). +- [`gojq.WithInputIter`](https://pkg.go.dev/github.com/itchyny/gojq#WithInputIter) allows to use `input` and `inputs` functions. By default, these functions are disabled. + +## Bug Tracker +Report bug at [Issues・itchyny/gojq - GitHub](https://github.com/itchyny/gojq/issues). + +## Author +itchyny (https://github.com/itchyny) + +## License +This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/itchyny/gojq/_gojq b/vendor/github.com/itchyny/gojq/_gojq new file mode 100644 index 00000000..4c94718a --- /dev/null +++ b/vendor/github.com/itchyny/gojq/_gojq @@ -0,0 +1,32 @@ +#compdef gojq + +_gojq() +{ + _arguments -C \ + '(-c --compact-output)'{-c,--compact-output}'[compact output]' \ + '(-r --raw-output)'{-r,--raw-output}'[output raw strings]' \ + '(-j --join-output)'{-j,--join-output}'[stop printing a newline after each output]' \ + '(-0 --nul-output)'{-0,--nul-output}'[print NUL after each output]' \ + '(-C --color-output)'{-C,--color-output}'[colorize output even if piped]' \ + '(-M --monochrome-output)'{-M,--monochrome-output}'[stop colorizing output]' \ + '(--yaml-output)'--yaml-output'[output by YAML]' \ + '(--indent)'--indent'[number of spaces for indentation]:indentation count' \ + '(--tab)'--tab'[use tabs for indentation]' \ + '(-n --null-input)'{-n,--null-input}'[use null as input value]' \ + '(-R --raw-input)'{-R,--raw-input}'[read input as raw strings]' \ + '(-s --slurp)'{-s,--slurp}'[read all inputs into an array]' \ + '(--stream)'--stream'[parse input in stream fashion]' \ + '(--yaml-input)'--yaml-input'[read input as YAML]' \ + '(-f --from-file)'{-f,--from-file}'[load query from file]:filename of jq query:_files' \ + '(-L)'-L'[directory to search modules from]:module directory:_directories' \ + '(--arg)'--arg'[set variable to string value]:variable name:' \ + '(--argjson)'--argjson'[set variable to JSON value]:variable name:' \ + '(--slurpfile)'--slurpfile'[set variable to the JSON contents of the file]:variable name:' \ + '(--rawfile)'--rawfile'[set variable to the contents of the file]:variable name:' \ + '(--args)'--args'[consume remaining arguments as positional string values]' \ + '(--jsonargs)'--jsonargs'[consume remaining arguments as positional JSON values]' \ + '(-e --exit-status)'{-e,--exit-status}'[exit 1 when the last value is false or null]' \ + '(-v --version)'{-v,--version}'[print version]' \ + '(-h --help)'{-h,--help}'[print help]' \ + && ret=0 +} diff --git a/vendor/github.com/itchyny/gojq/builtin.go b/vendor/github.com/itchyny/gojq/builtin.go new file mode 100644 index 00000000..a59795d4 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/builtin.go @@ -0,0 +1,70 @@ +// Code generated by _tools/gen_builtin.go; DO NOT EDIT. + +package gojq + +func init() { + builtinFuncDefs = map[string][]*FuncDef{ + "IN": []*FuncDef{&FuncDef{Name: "IN", Args: []string{"s"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Left: &Query{Func: "s"}, Op: OpEq, Right: &Query{Func: "."}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "IN", Args: []string{"src", "s"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Left: &Query{Func: "src"}, Op: OpEq, Right: &Query{Func: "s"}}, &Query{Func: "."}}}}}}}, + "INDEX": []*FuncDef{&FuncDef{Name: "INDEX", Args: []string{"stream", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "stream"}}, Pattern: &Pattern{Name: "$row"}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: "$row"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "idx_expr"}, Op: OpPipe, Right: &Query{Func: "tostring"}}}}}}, Op: OpAssign, Right: &Query{Func: "$row"}}}}}}, &FuncDef{Name: "INDEX", Args: []string{"idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "INDEX", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "idx_expr"}}}}}}}, + "JOIN": []*FuncDef{&FuncDef{Name: "JOIN", Args: []string{"$idx", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr", "join_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "join_expr"}}}}}, + "_assign": []*FuncDef{&FuncDef{Name: "_assign", Args: []string{"ps", "$v"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "ps"}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Func: "."}, Update: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Func: "$p"}, &Query{Func: "$v"}}}}}}}}}}, + "_modify": []*FuncDef{&FuncDef{Name: "_modify", Args: []string{"ps", "f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "ps"}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}}}}, Update: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpAdd, Right: &Query{Func: "$p"}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$q"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Func: "$q"}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$q"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$p"}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "delpaths", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}}}}}}}}}, + "all": []*FuncDef{&FuncDef{Name: "all", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&Query{Func: "."}}}}}}, &FuncDef{Name: "all", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "y"}}}}}}, &FuncDef{Name: "all", Args: []string{"g", "y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{&Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "y"}, Op: OpPipe, Right: &Query{Func: "not"}}}}}}}}}}}}}, + "any": []*FuncDef{&FuncDef{Name: "any", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Func: "."}}}}}}, &FuncDef{Name: "any", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "y"}}}}}}, &FuncDef{Name: "any", Args: []string{"g", "y"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{&Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "y"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "not"}}}}, + "arrays": []*FuncDef{&FuncDef{Name: "arrays", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}}}}}}}, + "ascii_downcase": []*FuncDef{&FuncDef{Name: "ascii_downcase", Body: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: "65"}}, Op: OpLe, Right: &Query{Func: "."}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "90"}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "32"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "implode"}}}}}, + "ascii_upcase": []*FuncDef{&FuncDef{Name: "ascii_upcase", Body: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: "97"}}, Op: OpLe, Right: &Query{Func: "."}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "122"}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "32"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "implode"}}}}}, + "booleans": []*FuncDef{&FuncDef{Name: "booleans", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "boolean"}}}}}}}}}}, + "capture": []*FuncDef{&FuncDef{Name: "capture", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "capture", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "capture", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}, Op: OpPipe, Right: &Query{Func: "_capture"}}}}, + "combinations": []*FuncDef{&FuncDef{Name: "combinations", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$x"}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}, IsSlice: true}}}, Op: OpPipe, Right: &Query{Func: "combinations"}}}}}}}}}}}}}}, &FuncDef{Name: "combinations", Args: []string{"n"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "limit", Args: []*Query{&Query{Func: "n"}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "repeat", Args: []*Query{&Query{Func: "."}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "combinations"}}}}, + "del": []*FuncDef{&FuncDef{Name: "del", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "delpaths", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "f"}}}}}}}}}}}}}}, + "finites": []*FuncDef{&FuncDef{Name: "finites", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isfinite"}}}}}}}, + "first": []*FuncDef{&FuncDef{Name: "first", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}, &FuncDef{Name: "first", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}, + "fromdate": []*FuncDef{&FuncDef{Name: "fromdate", Body: &Query{Func: "fromdateiso8601"}}}, + "fromdateiso8601": []*FuncDef{&FuncDef{Name: "fromdateiso8601", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strptime", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%S%z"}}}}}}}, Op: OpPipe, Right: &Query{Func: "mktime"}}}}, + "fromstream": []*FuncDef{&FuncDef{Name: "fromstream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "x", Val: &ObjectVal{Queries: []*Query{&Query{Func: "null"}}}}, &ObjectKeyVal{Key: "e", Val: &ObjectVal{Queries: []*Query{&Query{Func: "false"}}}}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$init"}}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "f"}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Func: "$init"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Func: "$init"}, Else: &Query{Func: "."}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "2"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "x"}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "x"}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}, + "group_by": []*FuncDef{&FuncDef{Name: "group_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_group_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "gsub": []*FuncDef{&FuncDef{Name: "gsub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, &FuncDef{Name: "gsub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Left: &Query{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}}}, + "in": []*FuncDef{&FuncDef{Name: "in", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "has", Args: []*Query{&Query{Func: "$x"}}}}}}}}}}}}}, + "inputs": []*FuncDef{&FuncDef{Name: "inputs", Body: &Query{Term: &Term{Type: TermTypeTry, Try: &Try{Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "repeat", Args: []*Query{&Query{Func: "input"}}}}}, Catch: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "break"}}}}, Then: &Query{Func: "empty"}, Else: &Query{Func: "error"}}}}}}}}}, + "inside": []*FuncDef{&FuncDef{Name: "inside", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "contains", Args: []*Query{&Query{Func: "$x"}}}}}}}}}}}}}, + "isempty": []*FuncDef{&FuncDef{Name: "isempty", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "false"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}, Op: OpComma, Right: &Query{Func: "true"}}}}}}}, + "iterables": []*FuncDef{&FuncDef{Name: "iterables", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, + "last": []*FuncDef{&FuncDef{Name: "last", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}, &FuncDef{Name: "last", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "null"}, Update: &Query{Func: "$item"}}}}}}, + "leaf_paths": []*FuncDef{&FuncDef{Name: "leaf_paths", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "paths", Args: []*Query{&Query{Func: "scalars"}}}}}}}, + "limit": []*FuncDef{&FuncDef{Name: "limit", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}, Else: &Query{Func: "empty"}}}}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Func: "empty"}}}, Else: &Query{Func: "g"}}}}}}, + "map": []*FuncDef{&FuncDef{Name: "map", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}, + "map_values": []*FuncDef{&FuncDef{Name: "map_values", Args: []string{"f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpModify, Right: &Query{Func: "f"}}}}, + "match": []*FuncDef{&FuncDef{Name: "match", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "match", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "false"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, + "max_by": []*FuncDef{&FuncDef{Name: "max_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_max_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "min_by": []*FuncDef{&FuncDef{Name: "min_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_min_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "normals": []*FuncDef{&FuncDef{Name: "normals", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isnormal"}}}}}}}, + "not": []*FuncDef{&FuncDef{Name: "not", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "."}, Then: &Query{Func: "false"}, Else: &Query{Func: "true"}}}}}}, + "nth": []*FuncDef{&FuncDef{Name: "nth", Args: []string{"$n"}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$n"}}}}}, &FuncDef{Name: "nth", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "nth doesn't support negative indices"}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Left: &Query{Func: "$n"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}}, + "nulls": []*FuncDef{&FuncDef{Name: "nulls", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Func: "null"}}}}}}}}, + "numbers": []*FuncDef{&FuncDef{Name: "numbers", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}}}}}}, + "objects": []*FuncDef{&FuncDef{Name: "objects", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}, + "paths": []*FuncDef{&FuncDef{Name: "paths", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: ".."}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}}}}}}}, &FuncDef{Name: "paths", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "paths"}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$p"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}, Op: OpPipe, Right: &Query{Func: "$p"}}}}}}}}}, + "range": []*FuncDef{&FuncDef{Name: "range", Args: []string{"$end"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_range", Args: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}, &Query{Func: "$end"}, &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_range", Args: []*Query{&Query{Func: "$start"}, &Query{Func: "$end"}, &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end", "$step"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_range", Args: []*Query{&Query{Func: "$start"}, &Query{Func: "$end"}, &Query{Func: "$step"}}}}}}}, + "recurse": []*FuncDef{&FuncDef{Name: "recurse", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "recurse", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}, &FuncDef{Name: "recurse", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Func: "r"}}}}}}}, Func: "r"}}, &FuncDef{Name: "recurse", Args: []string{"f", "cond"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "cond"}}}}}, Op: OpPipe, Right: &Query{Func: "r"}}}}}}}}, Func: "r"}}}, + "repeat": []*FuncDef{&FuncDef{Name: "repeat", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_repeat", Body: &Query{Left: &Query{Func: "f"}, Op: OpComma, Right: &Query{Func: "_repeat"}}}}, Func: "_repeat"}}}, + "scalars": []*FuncDef{&FuncDef{Name: "scalars", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, + "scan": []*FuncDef{&FuncDef{Name: "scan", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "scan", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "scan", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Left: &Query{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Index: &Index{Name: "string"}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, + "select": []*FuncDef{&FuncDef{Name: "select", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "f"}, Then: &Query{Func: "."}, Else: &Query{Func: "empty"}}}}}}, + "sort_by": []*FuncDef{&FuncDef{Name: "sort_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_sort_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "splits": []*FuncDef{&FuncDef{Name: "splits", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "splits", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "splits", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "split", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, + "strings": []*FuncDef{&FuncDef{Name: "strings", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}}}, + "sub": []*FuncDef{&FuncDef{Name: "sub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "sub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$str"}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_sub", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$r"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "string", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$r"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "_capture"}, Op: OpPipe, Right: &Query{Func: "str"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$str"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "length"}}}}}}, End: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, &ObjectKeyVal{Key: "offset", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}}}}, &ObjectKeyVal{Key: "matches", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{End: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}, IsSlice: true}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "_sub"}}}}}}}, Else: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$str"}, SuffixList: []*Suffix{&Suffix{Index: &Index{End: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, Left: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "string", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{}}}}}}, &ObjectKeyVal{Key: "matches", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "_sub"}}}}}}}}}, + "test": []*FuncDef{&FuncDef{Name: "test", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "test", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "test", Args: []string{"$re", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "true"}}}}}}}, + "todate": []*FuncDef{&FuncDef{Name: "todate", Body: &Query{Func: "todateiso8601"}}}, + "todateiso8601": []*FuncDef{&FuncDef{Name: "todateiso8601", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strftime", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%SZ"}}}}}}}}}, + "tostream": []*FuncDef{&FuncDef{Name: "tostream", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}, Op: OpPipe, Right: &Query{Func: "r"}}}}, Op: OpComma, Right: &Query{Func: "."}}}}, Func: "r"}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$p"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}, Pattern: &Pattern{Name: "$q"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$p"}, Op: OpComma, Right: &Query{Func: "."}}}}}, Update: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$p"}, Op: OpAdd, Right: &Query{Func: "$q"}}}}}}}}}}}}}}}}, + "truncate_stream": []*FuncDef{&FuncDef{Name: "truncate_stream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$n"}}, Body: &Query{Left: &Query{Func: "null"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Func: "$n"}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpModify, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$n"}, IsSlice: true}}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}, + "unique_by": []*FuncDef{&FuncDef{Name: "unique_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_unique_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "until": []*FuncDef{&FuncDef{Name: "until", Args: []string{"cond", "next"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_until", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "cond"}, Then: &Query{Func: "."}, Else: &Query{Left: &Query{Func: "next"}, Op: OpPipe, Right: &Query{Func: "_until"}}}}}}}, Func: "_until"}}}, + "values": []*FuncDef{&FuncDef{Name: "values", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Func: "null"}}}}}}}}, + "walk": []*FuncDef{&FuncDef{Name: "walk", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_walk", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map_values", Args: []*Query{&Query{Func: "_walk"}}}}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}, Func: "_walk"}}}, + "while": []*FuncDef{&FuncDef{Name: "while", Args: []string{"cond", "update"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_while", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "cond"}, Then: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "update"}, Op: OpPipe, Right: &Query{Func: "_while"}}}}}, Else: &Query{Func: "empty"}}}}}}, Func: "_while"}}}, + "with_entries": []*FuncDef{&FuncDef{Name: "with_entries", Args: []string{"f"}, Body: &Query{Left: &Query{Func: "to_entries"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Func: "f"}}}}}, Op: OpPipe, Right: &Query{Func: "from_entries"}}}}}, + } +} diff --git a/vendor/github.com/itchyny/gojq/builtin.jq b/vendor/github.com/itchyny/gojq/builtin.jq new file mode 100644 index 00000000..491f57f3 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/builtin.jq @@ -0,0 +1,164 @@ +def not: if . then false else true end; +def in(xs): . as $x | xs | has($x); +def map(f): [.[] | f]; +def with_entries(f): to_entries | map(f) | from_entries; +def select(f): if f then . else empty end; +def recurse: recurse(.[]?); +def recurse(f): def r: ., (f | r); r; +def recurse(f; cond): def r: ., (f | select(cond) | r); r; + +def while(cond; update): + def _while: if cond then ., (update | _while) else empty end; + _while; +def until(cond; next): + def _until: if cond then . else next | _until end; + _until; +def repeat(f): + def _repeat: f, _repeat; + _repeat; +def range($end): _range(0; $end; 1); +def range($start; $end): _range($start; $end; 1); +def range($start; $end; $step): _range($start; $end; $step); + +def min_by(f): _min_by(map([f])); +def max_by(f): _max_by(map([f])); +def sort_by(f): _sort_by(map([f])); +def group_by(f): _group_by(map([f])); +def unique_by(f): _unique_by(map([f])); + +def arrays: select(type == "array"); +def objects: select(type == "object"); +def iterables: select(type | . == "array" or . == "object"); +def booleans: select(type == "boolean"); +def numbers: select(type == "number"); +def finites: select(isfinite); +def normals: select(isnormal); +def strings: select(type == "string"); +def nulls: select(. == null); +def values: select(. != null); +def scalars: select(type | . != "array" and . != "object"); +def leaf_paths: paths(scalars); + +def inside(xs): . as $x | xs | contains($x); +def combinations: if length == 0 then [] else .[0][] as $x | [$x] + (.[1:] | combinations) end; +def combinations(n): [limit(n; repeat(.))] | combinations; +def ascii_downcase: + explode | map(if 65 <= . and . <= 90 then . + 32 end) | implode; +def ascii_upcase: + explode | map(if 97 <= . and . <= 122 then . - 32 end) | implode; +def walk(f): + def _walk: if type | . == "array" or . == "object" then map_values(_walk) end | f; + _walk; + +def first: .[0]; +def first(g): label $out | g | ., break $out; +def last: .[-1]; +def last(g): reduce g as $item (null; $item); +def isempty(g): label $out | (g | false, break $out), true; +def all: all(.); +def all(y): all(.[]; y); +def all(g; y): isempty(g | select(y | not)); +def any: any(.); +def any(y): any(.[]; y); +def any(g; y): isempty(g | select(y)) | not; +def limit($n; g): + if $n > 0 then + label $out + | foreach g as $item + ($n; . - 1; $item, if . <= 0 then break $out else empty end) + elif $n == 0 then + empty + else + g + end; +def nth($n): .[$n]; +def nth($n; g): + if $n < 0 then + error("nth doesn't support negative indices") + else + label $out + | foreach g as $item + ($n + 1; . - 1; if . <= 0 then $item, break $out else empty end) + end; + +def truncate_stream(f): + . as $n | null | f | if .[0] | length > $n then .[0] |= .[$n:] else empty end; +def fromstream(f): + { x: null, e: false } as $init + | foreach f as $i + ( $init; + if .e then $init else . end + | if $i | length == 2 + then setpath(["e"]; $i[0] | length==0) | setpath(["x"] + $i[0]; $i[1]) + else setpath(["e"]; $i[0] | length==1) end; + if .e then .x else empty end); +def tostream: + path(def r: (.[]? | r), .; r) as $p + | getpath($p) + | reduce path(.[]?) as $q ([$p, .]; [$p + $q]); + +def _assign(ps; $v): + reduce path(ps) as $p (.; setpath($p; $v)); +def _modify(ps; f): + reduce path(ps) as $p + ([., []]; label $out | (([0] + $p) as $q | setpath($q; getpath($q) | f) | ., break $out), setpath([1]; .[1] + [$p])) + | . as $x | $x[0] | delpaths($x[1]); +def map_values(f): .[] |= f; +def del(f): delpaths([path(f)]); +def paths: path(..) | select(. != []); +def paths(f): paths as $p | select(getpath($p) | f) | $p; + +def fromdateiso8601: strptime("%Y-%m-%dT%H:%M:%S%z") | mktime; +def todateiso8601: strftime("%Y-%m-%dT%H:%M:%SZ"); +def fromdate: fromdateiso8601; +def todate: todateiso8601; + +def match($re): match($re; null); +def match($re; $flags): _match($re; $flags; false) | .[]; +def test($re): test($re; null); +def test($re; $flags): _match($re; $flags; true); +def capture($re): capture($re; null); +def capture($re; $flags): match($re; $flags) | _capture; +def scan($re): scan($re; null); +def scan($re; $flags): + match($re; $flags + "g") + | if .captures|length > 0 then [.captures[].string] else .string end; +def splits($re): splits($re; null); +def splits($re; $flags): split($re; $flags) | .[]; +def sub($re; str): sub($re; str; null); +def sub($re; str; $flags): + . as $str + | def _sub: + if .matches|length > 0 + then + .matches[-1] as $r + | { + string: (($r | _capture | str) + $str[$r.offset+$r.length:.offset] + .string), + offset: $r.offset, + matches: .matches[:-1], + } + | _sub + else + $str[:.offset] + .string + end; + { string: "", matches: [match($re; $flags)] } | _sub; +def gsub($re; str): sub($re; str; "g"); +def gsub($re; str; $flags): sub($re; str; $flags + "g"); + +def inputs: + try + repeat(input) + catch + if . == "break" then empty else error end; + +def INDEX(stream; idx_expr): + reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row); +def INDEX(idx_expr): INDEX(.[]; idx_expr); +def JOIN($idx; idx_expr): + [.[] | [., $idx[idx_expr]]]; +def JOIN($idx; stream; idx_expr): + stream | [., $idx[idx_expr]]; +def JOIN($idx; stream; idx_expr; join_expr): + stream | [., $idx[idx_expr]] | join_expr; +def IN(s): any(s == .; .); +def IN(src; s): any(src == s; .); diff --git a/vendor/github.com/itchyny/gojq/code.go b/vendor/github.com/itchyny/gojq/code.go new file mode 100644 index 00000000..efac134f --- /dev/null +++ b/vendor/github.com/itchyny/gojq/code.go @@ -0,0 +1,108 @@ +package gojq + +type code struct { + v interface{} + op opcode +} + +type opcode int + +const ( + opnop opcode = iota + oppush + oppop + opdup + opconst + opload + opstore + opobject + opappend + opfork + opforktrybegin + opforktryend + opforkalt + opforklabel + opbacktrack + opjump + opjumpifnot + opindex + opindexarray + opcall + opcallrec + oppushpc + opcallpc + opscope + opret + opiter + opexpbegin + opexpend + oppathbegin + oppathend +) + +func (op opcode) String() string { + switch op { + case opnop: + return "nop" + case oppush: + return "push" + case oppop: + return "pop" + case opdup: + return "dup" + case opconst: + return "const" + case opload: + return "load" + case opstore: + return "store" + case opobject: + return "object" + case opappend: + return "append" + case opfork: + return "fork" + case opforktrybegin: + return "forktrybegin" + case opforktryend: + return "forktryend" + case opforkalt: + return "forkalt" + case opforklabel: + return "forklabel" + case opbacktrack: + return "backtrack" + case opjump: + return "jump" + case opjumpifnot: + return "jumpifnot" + case opindex: + return "index" + case opindexarray: + return "indexarray" + case opcall: + return "call" + case opcallrec: + return "callrec" + case oppushpc: + return "pushpc" + case opcallpc: + return "callpc" + case opscope: + return "scope" + case opret: + return "ret" + case opiter: + return "iter" + case opexpbegin: + return "expbegin" + case opexpend: + return "expend" + case oppathbegin: + return "pathbegin" + case oppathend: + return "pathend" + default: + panic(op) + } +} diff --git a/vendor/github.com/itchyny/gojq/compare.go b/vendor/github.com/itchyny/gojq/compare.go new file mode 100644 index 00000000..fc054514 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/compare.go @@ -0,0 +1,104 @@ +package gojq + +import ( + "math" + "math/big" +) + +// Compare l and r, and returns jq-flavored comparison value. +// +// -1 if l < r +// 0 if l == r +// +1 if l > r +// +// This comparison is used by built-in operators and functions. +func Compare(l, r interface{}) int { + return compare(l, r) +} + +func compare(l, r interface{}) int { + return binopTypeSwitch(l, r, + compareInt, + func(l, r float64) interface{} { + switch { + case l < r || math.IsNaN(l): + return -1 + case l == r: + return 0 + default: + return 1 + } + }, + func(l, r *big.Int) interface{} { + return l.Cmp(r) + }, + func(l, r string) interface{} { + switch { + case l < r: + return -1 + case l == r: + return 0 + default: + return 1 + } + }, + func(l, r []interface{}) interface{} { + n := len(l) + if len(r) < n { + n = len(r) + } + for i := 0; i < n; i++ { + if cmp := compare(l[i], r[i]); cmp != 0 { + return cmp + } + } + return compareInt(len(l), len(r)) + }, + func(l, r map[string]interface{}) interface{} { + lk, rk := funcKeys(l), funcKeys(r) + if cmp := compare(lk, rk); cmp != 0 { + return cmp + } + for _, k := range lk.([]interface{}) { + if cmp := compare(l[k.(string)], r[k.(string)]); cmp != 0 { + return cmp + } + } + return 0 + }, + func(l, r interface{}) interface{} { + return compareInt(typeIndex(l), typeIndex(r)) + }, + ).(int) +} + +func compareInt(l, r int) interface{} { + switch { + case l < r: + return -1 + case l == r: + return 0 + default: + return 1 + } +} + +func typeIndex(v interface{}) int { + switch v := v.(type) { + default: + return 0 + case bool: + if !v { + return 1 + } + return 2 + case int, float64, *big.Int: + return 3 + case string: + return 4 + case []interface{}: + return 5 + case map[string]interface{}: + return 6 + } +} diff --git a/vendor/github.com/itchyny/gojq/compiler.go b/vendor/github.com/itchyny/gojq/compiler.go new file mode 100644 index 00000000..68b5318f --- /dev/null +++ b/vendor/github.com/itchyny/gojq/compiler.go @@ -0,0 +1,1506 @@ +package gojq + +import ( + "context" + "errors" + "fmt" + "sort" + "strconv" + "strings" +) + +type compiler struct { + moduleLoader ModuleLoader + environLoader func() []string + variables []string + customFuncs map[string]function + inputIter Iter + codes []*code + codeinfos []codeinfo + builtinScope *scopeinfo + scopes []*scopeinfo + scopecnt int +} + +// Code is a compiled jq query. +type Code struct { + variables []string + codes []*code + codeinfos []codeinfo +} + +// Run runs the code with the variable values (which should be in the +// same order as the given variables using WithVariables) and returns +// a result iterator. +// +// It is safe to call this method of a *Code in multiple goroutines. +func (c *Code) Run(v interface{}, values ...interface{}) Iter { + return c.RunWithContext(context.Background(), v, values...) +} + +// RunWithContext runs the code with context. +func (c *Code) RunWithContext(ctx context.Context, v interface{}, values ...interface{}) Iter { + if len(values) > len(c.variables) { + return NewIter(&tooManyVariableValuesError{}) + } else if len(values) < len(c.variables) { + return NewIter(&expectedVariableError{c.variables[len(values)]}) + } + for i, v := range values { + values[i] = normalizeNumbers(v) + } + return newEnv(ctx).execute(c, normalizeNumbers(v), values...) +} + +type scopeinfo struct { + variables []*varinfo + funcs []*funcinfo + id int + depth int + variablecnt int +} + +type varinfo struct { + name string + index [2]int + depth int +} + +type funcinfo struct { + name string + pc int + argcnt int +} + +// Compile compiles a query. +func Compile(q *Query, options ...CompilerOption) (*Code, error) { + c := &compiler{} + for _, opt := range options { + opt(c) + } + c.builtinScope = c.newScope() + scope := c.newScope() + c.scopes = []*scopeinfo{scope} + setscope := c.lazy(func() *code { + return &code{op: opscope, v: [3]int{scope.id, scope.variablecnt, 0}} + }) + if c.moduleLoader != nil { + if moduleLoader, ok := c.moduleLoader.(interface { + LoadInitModules() ([]*Query, error) + }); ok { + qs, err := moduleLoader.LoadInitModules() + if err != nil { + return nil, err + } + for _, q := range qs { + if err := c.compileModule(q, ""); err != nil { + return nil, err + } + } + } + } + if err := c.compile(q); err != nil { + return nil, err + } + setscope() + c.optimizeTailRec() + c.optimizeCodeOps() + return &Code{ + variables: c.variables, + codes: c.codes, + codeinfos: c.codeinfos, + }, nil +} + +func (c *compiler) compile(q *Query) error { + for _, name := range c.variables { + if !newLexer(name).validVarName() { + return &variableNameError{name} + } + c.appendCodeInfo(name) + c.append(&code{op: opstore, v: c.pushVariable(name)}) + } + for _, i := range q.Imports { + if err := c.compileImport(i); err != nil { + return err + } + } + if err := c.compileQuery(q); err != nil { + return err + } + c.append(&code{op: opret}) + return nil +} + +func (c *compiler) compileImport(i *Import) error { + var path, alias string + var err error + if i.ImportPath != "" { + path, alias = i.ImportPath, i.ImportAlias + } else { + path = i.IncludePath + } + if c.moduleLoader == nil { + return fmt.Errorf("cannot load module: %q", path) + } + if strings.HasPrefix(alias, "$") { + var vals interface{} + if moduleLoader, ok := c.moduleLoader.(interface { + LoadJSONWithMeta(string, map[string]interface{}) (interface{}, error) + }); ok { + if vals, err = moduleLoader.LoadJSONWithMeta(path, i.Meta.ToValue()); err != nil { + return err + } + } else if moduleLoader, ok := c.moduleLoader.(interface { + LoadJSON(string) (interface{}, error) + }); ok { + if vals, err = moduleLoader.LoadJSON(path); err != nil { + return err + } + } else { + return fmt.Errorf("module not found: %q", path) + } + vals = normalizeNumbers(vals) + c.append(&code{op: oppush, v: vals}) + c.append(&code{op: opstore, v: c.pushVariable(alias)}) + c.append(&code{op: oppush, v: vals}) + c.append(&code{op: opstore, v: c.pushVariable(alias + "::" + alias[1:])}) + return nil + } + var q *Query + if moduleLoader, ok := c.moduleLoader.(interface { + LoadModuleWithMeta(string, map[string]interface{}) (*Query, error) + }); ok { + if q, err = moduleLoader.LoadModuleWithMeta(path, i.Meta.ToValue()); err != nil { + return err + } + } else if moduleLoader, ok := c.moduleLoader.(interface { + LoadModule(string) (*Query, error) + }); ok { + if q, err = moduleLoader.LoadModule(path); err != nil { + return err + } + } + c.appendCodeInfo("module " + path) + if err = c.compileModule(q, alias); err != nil { + return err + } + c.appendCodeInfo("end of module " + path) + return nil +} + +func (c *compiler) compileModule(q *Query, alias string) error { + scope := c.scopes[len(c.scopes)-1] + scope.depth++ + defer func(l int) { + scope.depth-- + scope.variables = scope.variables[:l] + }(len(scope.variables)) + if alias != "" { + defer func(l int) { + for _, f := range scope.funcs[l:] { + f.name = alias + "::" + f.name + } + }(len(scope.funcs)) + } + for _, i := range q.Imports { + if err := c.compileImport(i); err != nil { + return err + } + } + for _, fd := range q.FuncDefs { + if err := c.compileFuncDef(fd, false); err != nil { + return err + } + } + return nil +} + +func (c *compiler) newVariable() [2]int { + return c.createVariable("") +} + +func (c *compiler) pushVariable(name string) [2]int { + s := c.scopes[len(c.scopes)-1] + for _, v := range s.variables { + if v.name == name && v.depth == s.depth { + return v.index + } + } + return c.createVariable(name) +} + +func (c *compiler) createVariable(name string) [2]int { + s := c.scopes[len(c.scopes)-1] + v := [2]int{s.id, s.variablecnt} + s.variablecnt++ + s.variables = append(s.variables, &varinfo{name, v, s.depth}) + return v +} + +func (c *compiler) lookupVariable(name string) ([2]int, error) { + for i := len(c.scopes) - 1; i >= 0; i-- { + s := c.scopes[i] + for j := len(s.variables) - 1; j >= 0; j-- { + if w := s.variables[j]; w.name == name { + return w.index, nil + } + } + } + return [2]int{}, &variableNotFoundError{name} +} + +func (c *compiler) lookupFuncOrVariable(name string) (*funcinfo, *varinfo) { + for i, isFunc := len(c.scopes)-1, name[0] != '$'; i >= 0; i-- { + s := c.scopes[i] + if isFunc { + for j := len(s.funcs) - 1; j >= 0; j-- { + if f := s.funcs[j]; f.name == name && f.argcnt == 0 { + return f, nil + } + } + } + for j := len(s.variables) - 1; j >= 0; j-- { + if v := s.variables[j]; v.name == name { + return nil, v + } + } + } + return nil, nil +} + +func (c *compiler) lookupBuiltin(name string, argcnt int) *funcinfo { + s := c.builtinScope + for i := len(s.funcs) - 1; i >= 0; i-- { + if f := s.funcs[i]; f.name == name && f.argcnt == argcnt { + return f + } + } + return nil +} + +func (c *compiler) newScope() *scopeinfo { + i := c.scopecnt // do not use len(c.scopes) because it pops + c.scopecnt++ + return &scopeinfo{id: i} +} + +func (c *compiler) newScopeDepth() func() { + scope := c.scopes[len(c.scopes)-1] + l, m := len(scope.variables), len(scope.funcs) + scope.depth++ + return func() { + scope.depth-- + scope.variables = scope.variables[:l] + scope.funcs = scope.funcs[:m] + } +} + +func (c *compiler) compileFuncDef(e *FuncDef, builtin bool) error { + var scope *scopeinfo + if builtin { + scope = c.builtinScope + } else { + scope = c.scopes[len(c.scopes)-1] + } + defer c.lazy(func() *code { + return &code{op: opjump, v: len(c.codes)} + })() + c.appendCodeInfo(e.Name) + scope.funcs = append(scope.funcs, &funcinfo{e.Name, len(c.codes), len(e.Args)}) + defer func(scopes []*scopeinfo, variables []string) { + c.scopes, c.variables = scopes, variables + }(c.scopes, c.variables) + c.variables = c.variables[len(c.variables):] + scope = c.newScope() + if builtin { + c.scopes = []*scopeinfo{c.builtinScope, scope} + } else { + c.scopes = append(c.scopes, scope) + } + defer c.lazy(func() *code { + return &code{op: opscope, v: [3]int{scope.id, scope.variablecnt, len(e.Args)}} + })() + if len(e.Args) > 0 { + type varIndex struct { + name string + index [2]int + } + vis := make([]varIndex, 0, len(e.Args)) + v := c.newVariable() + c.append(&code{op: opstore, v: v}) + for _, arg := range e.Args { + if arg[0] == '$' { + c.appendCodeInfo(arg[1:]) + w := c.createVariable(arg[1:]) + c.append(&code{op: opstore, v: w}) + vis = append(vis, varIndex{arg, w}) + } else { + c.appendCodeInfo(arg) + c.append(&code{op: opstore, v: c.createVariable(arg)}) + } + } + for _, w := range vis { + c.append(&code{op: opload, v: v}) + c.append(&code{op: opload, v: w.index}) + c.append(&code{op: opcallpc}) + c.appendCodeInfo(w.name) + c.append(&code{op: opstore, v: c.pushVariable(w.name)}) + } + c.append(&code{op: opload, v: v}) + } + if err := c.compile(e.Body); err != nil { + return err + } + c.appendCodeInfo("end of " + e.Name) + return nil +} + +func (c *compiler) compileQuery(e *Query) error { + for _, fd := range e.FuncDefs { + if err := c.compileFuncDef(fd, false); err != nil { + return err + } + } + if e.Func != "" { + switch e.Func { + case ".": + return c.compileTerm(&Term{Type: TermTypeIdentity}) + case "..": + return c.compileTerm(&Term{Type: TermTypeRecurse}) + case "null": + return c.compileTerm(&Term{Type: TermTypeNull}) + case "true": + return c.compileTerm(&Term{Type: TermTypeTrue}) + case "false": + return c.compileTerm(&Term{Type: TermTypeFalse}) + default: + return c.compileFunc(&Func{Name: e.Func}) + } + } else if e.Term != nil { + return c.compileTerm(e.Term) + } + switch e.Op { + case OpPipe: + if err := c.compileQuery(e.Left); err != nil { + return err + } + return c.compileQuery(e.Right) + case OpComma: + return c.compileComma(e.Left, e.Right) + case OpAlt: + return c.compileAlt(e.Left, e.Right) + case OpAssign, OpModify, OpUpdateAdd, OpUpdateSub, + OpUpdateMul, OpUpdateDiv, OpUpdateMod, OpUpdateAlt: + return c.compileQueryUpdate(e.Left, e.Right, e.Op) + case OpOr: + return c.compileIf( + &If{ + Cond: e.Left, + Then: &Query{Term: &Term{Type: TermTypeTrue}}, + Else: &Query{Term: &Term{Type: TermTypeIf, If: &If{ + Cond: e.Right, + Then: &Query{Term: &Term{Type: TermTypeTrue}}, + Else: &Query{Term: &Term{Type: TermTypeFalse}}, + }}}, + }, + ) + case OpAnd: + return c.compileIf( + &If{ + Cond: e.Left, + Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{ + Cond: e.Right, + Then: &Query{Term: &Term{Type: TermTypeTrue}}, + Else: &Query{Term: &Term{Type: TermTypeFalse}}, + }}}, + Else: &Query{Term: &Term{Type: TermTypeFalse}}, + }, + ) + default: + return c.compileCall( + e.Op.getFunc(), + []*Query{e.Left, e.Right}, + ) + } +} + +func (c *compiler) compileComma(l, r *Query) error { + setfork := c.lazy(func() *code { + return &code{op: opfork, v: len(c.codes)} + }) + if err := c.compileQuery(l); err != nil { + return err + } + defer c.lazy(func() *code { + return &code{op: opjump, v: len(c.codes)} + })() + setfork() + return c.compileQuery(r) +} + +func (c *compiler) compileAlt(l, r *Query) error { + c.append(&code{op: oppush, v: false}) + found := c.newVariable() + c.append(&code{op: opstore, v: found}) + setfork := c.lazy(func() *code { + return &code{op: opfork, v: len(c.codes)} // opload found + }) + if err := c.compileQuery(l); err != nil { + return err + } + c.append(&code{op: opdup}) + c.append(&code{op: opjumpifnot, v: len(c.codes) + 4}) // oppop + c.append(&code{op: oppush, v: true}) // found some value + c.append(&code{op: opstore, v: found}) + defer c.lazy(func() *code { + return &code{op: opjump, v: len(c.codes)} + })() + c.append(&code{op: oppop}) + c.append(&code{op: opbacktrack}) + setfork() + c.append(&code{op: opload, v: found}) + c.append(&code{op: opjumpifnot, v: len(c.codes) + 3}) + c.append(&code{op: opbacktrack}) // if found, backtrack + c.append(&code{op: oppop}) + return c.compileQuery(r) +} + +func (c *compiler) compileQueryUpdate(l, r *Query, op Operator) error { + switch op { + case OpAssign: + // optimize assignment operator with constant indexing and slicing + // .foo.[0].[1:2] = f => setpath(["foo",0,{"start":1,"end":2}]; f) + if xs := l.toIndices(nil); xs != nil { + // ref: compileCall + v := c.newVariable() + c.append(&code{op: opstore, v: v}) + c.append(&code{op: opload, v: v}) + if err := c.compileQuery(r); err != nil { + return err + } + c.append(&code{op: oppush, v: xs}) + c.append(&code{op: opload, v: v}) + c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["setpath"].callback, 2, "setpath"}}) + return nil + } + fallthrough + case OpModify: + return c.compileFunc( + &Func{ + Name: op.getFunc(), + Args: []*Query{l, r}, + }, + ) + default: + name := "$%0" + c.append(&code{op: opdup}) + if err := c.compileQuery(r); err != nil { + return err + } + c.append(&code{op: opstore, v: c.pushVariable(name)}) + return c.compileFunc( + &Func{ + Name: "_modify", + Args: []*Query{ + l, + {Term: &Term{ + Type: TermTypeFunc, + Func: &Func{ + Name: op.getFunc(), + Args: []*Query{ + {Term: &Term{Type: TermTypeIdentity}}, + {Func: name}, + }, + }, + }}, + }, + }, + ) + } +} + +func (c *compiler) compileBind(e *Term, b *Bind) error { + c.append(&code{op: opdup}) + c.append(&code{op: opexpbegin}) + if err := c.compileTerm(e); err != nil { + return err + } + var pc int + var vs [][2]int + for i, p := range b.Patterns { + var pcc int + var err error + if i < len(b.Patterns)-1 { + defer c.lazy(func() *code { + return &code{op: opforkalt, v: pcc} + })() + } + if 0 < i { + for _, v := range vs { + c.append(&code{op: oppush, v: nil}) + c.append(&code{op: opstore, v: v}) + } + } + if vs, err = c.compilePattern(vs[:0], p); err != nil { + return err + } + if i < len(b.Patterns)-1 { + defer c.lazy(func() *code { + return &code{op: opjump, v: pc} + })() + pcc = len(c.codes) + } + } + if len(b.Patterns) > 1 { + pc = len(c.codes) + } + if len(b.Patterns) == 1 && c.codes[len(c.codes)-2].op == opexpbegin { + c.codes[len(c.codes)-2].op = opnop + } else { + c.append(&code{op: opexpend}) + } + return c.compileQuery(b.Body) +} + +func (c *compiler) compilePattern(vs [][2]int, p *Pattern) ([][2]int, error) { + var err error + c.appendCodeInfo(p) + if p.Name != "" { + v := c.pushVariable(p.Name) + c.append(&code{op: opstore, v: v}) + return append(vs, v), nil + } else if len(p.Array) > 0 { + v := c.newVariable() + c.append(&code{op: opstore, v: v}) + for i, p := range p.Array { + c.append(&code{op: opload, v: v}) + c.append(&code{op: opindexarray, v: i}) + if vs, err = c.compilePattern(vs, p); err != nil { + return nil, err + } + } + return vs, nil + } else if len(p.Object) > 0 { + v := c.newVariable() + c.append(&code{op: opstore, v: v}) + for _, kv := range p.Object { + var key, name string + c.append(&code{op: opload, v: v}) + if key = kv.Key; key != "" { + if key[0] == '$' { + key, name = key[1:], key + } + } else if kv.KeyString != nil { + if key = kv.KeyString.Str; key == "" { + if err := c.compileString(kv.KeyString, nil); err != nil { + return nil, err + } + } + } else if kv.KeyQuery != nil { + if err := c.compileQuery(kv.KeyQuery); err != nil { + return nil, err + } + } + if key != "" { + c.append(&code{op: opindex, v: key}) + } else { + c.append(&code{op: opload, v: v}) + c.append(&code{op: oppush, v: nil}) + // ref: compileCall + c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["_index"].callback, 2, "_index"}}) + } + if name != "" { + if kv.Val != nil { + c.append(&code{op: opdup}) + } + if vs, err = c.compilePattern(vs, &Pattern{Name: name}); err != nil { + return nil, err + } + } + if kv.Val != nil { + if vs, err = c.compilePattern(vs, kv.Val); err != nil { + return nil, err + } + } + } + return vs, nil + } else { + return nil, fmt.Errorf("invalid pattern: %s", p) + } +} + +func (c *compiler) compileIf(e *If) error { + c.appendCodeInfo(e) + c.append(&code{op: opdup}) // duplicate the value for then or else clause + c.append(&code{op: opexpbegin}) + pc := len(c.codes) + f := c.newScopeDepth() + if err := c.compileQuery(e.Cond); err != nil { + return err + } + f() + if pc == len(c.codes) { + c.codes = c.codes[:pc-1] + } else { + c.append(&code{op: opexpend}) + } + pcc := len(c.codes) + setjumpifnot := c.lazy(func() *code { + return &code{op: opjumpifnot, v: len(c.codes)} // skip then clause + }) + f = c.newScopeDepth() + if err := c.compileQuery(e.Then); err != nil { + return err + } + f() + defer c.lazy(func() *code { + return &code{op: opjump, v: len(c.codes)} + })() + setjumpifnot() + if len(e.Elif) > 0 { + return c.compileIf(&If{e.Elif[0].Cond, e.Elif[0].Then, e.Elif[1:], e.Else}) + } + if e.Else != nil { + defer c.newScopeDepth()() + defer func() { + // optimize constant results + // opdup, ..., opjumpifnot, opconst, opjump, opconst + // => opnop, ..., opjumpifnot, oppush, opjump, oppush + if pcc+4 == len(c.codes) && + c.codes[pcc+1] != nil && c.codes[pcc+1].op == opconst && + c.codes[pcc+3] != nil && c.codes[pcc+3].op == opconst { + c.codes[pc-2].op = opnop + c.codes[pcc+1].op = oppush + c.codes[pcc+3].op = oppush + } + }() + return c.compileQuery(e.Else) + } + return nil +} + +func (c *compiler) compileTry(e *Try) error { + c.appendCodeInfo(e) + setforktrybegin := c.lazy(func() *code { + return &code{op: opforktrybegin, v: len(c.codes)} + }) + f := c.newScopeDepth() + if err := c.compileQuery(e.Body); err != nil { + return err + } + f() + c.append(&code{op: opforktryend}) + defer c.lazy(func() *code { + return &code{op: opjump, v: len(c.codes)} + })() + setforktrybegin() + if e.Catch != nil { + defer c.newScopeDepth()() + return c.compileQuery(e.Catch) + } + c.append(&code{op: opbacktrack}) + return nil +} + +func (c *compiler) compileReduce(e *Reduce) error { + c.appendCodeInfo(e) + defer c.newScopeDepth()() + setfork := c.lazy(func() *code { + return &code{op: opfork, v: len(c.codes)} + }) + c.append(&code{op: opdup}) + v := c.newVariable() + f := c.newScopeDepth() + if err := c.compileQuery(e.Start); err != nil { + return err + } + f() + c.append(&code{op: opstore, v: v}) + if err := c.compileTerm(e.Term); err != nil { + return err + } + if _, err := c.compilePattern(nil, e.Pattern); err != nil { + return err + } + c.append(&code{op: opload, v: v}) + f = c.newScopeDepth() + if err := c.compileQuery(e.Update); err != nil { + return err + } + f() + c.append(&code{op: opstore, v: v}) + c.append(&code{op: opbacktrack}) + setfork() + c.append(&code{op: oppop}) + c.append(&code{op: opload, v: v}) + return nil +} + +func (c *compiler) compileForeach(e *Foreach) error { + c.appendCodeInfo(e) + defer c.newScopeDepth()() + c.append(&code{op: opdup}) + v := c.newVariable() + f := c.newScopeDepth() + if err := c.compileQuery(e.Start); err != nil { + return err + } + f() + c.append(&code{op: opstore, v: v}) + if err := c.compileTerm(e.Term); err != nil { + return err + } + if _, err := c.compilePattern(nil, e.Pattern); err != nil { + return err + } + c.append(&code{op: opload, v: v}) + f = c.newScopeDepth() + if err := c.compileQuery(e.Update); err != nil { + return err + } + f() + c.append(&code{op: opdup}) + c.append(&code{op: opstore, v: v}) + if e.Extract != nil { + defer c.newScopeDepth()() + return c.compileQuery(e.Extract) + } + return nil +} + +func (c *compiler) compileLabel(e *Label) error { + c.appendCodeInfo(e) + v := c.pushVariable("$%" + e.Ident[1:]) + defer c.lazy(func() *code { + return &code{op: opforklabel, v: v} + })() + return c.compileQuery(e.Body) +} + +func (c *compiler) compileBreak(label string) error { + v, err := c.lookupVariable("$%" + label[1:]) + if err != nil { + return &breakError{label, nil} + } + c.append(&code{op: oppop}) + c.append(&code{op: opload, v: v}) + c.append(&code{op: opcall, v: [3]interface{}{ + func(v interface{}, _ []interface{}) interface{} { + return &breakError{label, v} + }, + 0, + "_break", + }}) + return nil +} + +func (c *compiler) compileTerm(e *Term) error { + if len(e.SuffixList) > 0 { + s := e.SuffixList[len(e.SuffixList)-1] + t := *e // clone without changing e + t.SuffixList = t.SuffixList[:len(e.SuffixList)-1] + return c.compileTermSuffix(&t, s) + } + switch e.Type { + case TermTypeIdentity: + return nil + case TermTypeRecurse: + return c.compileFunc(&Func{Name: "recurse"}) + case TermTypeNull: + c.append(&code{op: opconst, v: nil}) + return nil + case TermTypeTrue: + c.append(&code{op: opconst, v: true}) + return nil + case TermTypeFalse: + c.append(&code{op: opconst, v: false}) + return nil + case TermTypeIndex: + return c.compileIndex(&Term{Type: TermTypeIdentity}, e.Index) + case TermTypeFunc: + return c.compileFunc(e.Func) + case TermTypeObject: + return c.compileObject(e.Object) + case TermTypeArray: + return c.compileArray(e.Array) + case TermTypeNumber: + c.append(&code{op: opconst, v: toNumber(e.Number)}) + return nil + case TermTypeUnary: + return c.compileUnary(e.Unary) + case TermTypeFormat: + return c.compileFormat(e.Format, e.Str) + case TermTypeString: + return c.compileString(e.Str, nil) + case TermTypeIf: + return c.compileIf(e.If) + case TermTypeTry: + return c.compileTry(e.Try) + case TermTypeReduce: + return c.compileReduce(e.Reduce) + case TermTypeForeach: + return c.compileForeach(e.Foreach) + case TermTypeLabel: + return c.compileLabel(e.Label) + case TermTypeBreak: + return c.compileBreak(e.Break) + case TermTypeQuery: + defer c.newScopeDepth()() + return c.compileQuery(e.Query) + default: + panic("invalid term: " + e.String()) + } +} + +func (c *compiler) compileIndex(e *Term, x *Index) error { + if k := x.toIndexKey(); k != nil { + if err := c.compileTerm(e); err != nil { + return err + } + c.appendCodeInfo(x) + c.append(&code{op: opindex, v: k}) + return nil + } + c.appendCodeInfo(x) + if x.Str != nil { + return c.compileCall("_index", []*Query{{Term: e}, {Term: &Term{Type: TermTypeString, Str: x.Str}}}) + } + if !x.IsSlice { + return c.compileCall("_index", []*Query{{Term: e}, x.Start}) + } + if x.Start == nil { + return c.compileCall("_slice", []*Query{{Term: e}, x.End, {Term: &Term{Type: TermTypeNull}}}) + } + if x.End == nil { + return c.compileCall("_slice", []*Query{{Term: e}, {Term: &Term{Type: TermTypeNull}}, x.Start}) + } + return c.compileCall("_slice", []*Query{{Term: e}, x.End, x.Start}) +} + +func (c *compiler) compileFunc(e *Func) error { + if len(e.Args) == 0 { + if f, v := c.lookupFuncOrVariable(e.Name); f != nil { + return c.compileCallPc(f, e.Args) + } else if v != nil { + if e.Name[0] == '$' { + c.append(&code{op: oppop}) + c.append(&code{op: opload, v: v.index}) + } else { + c.append(&code{op: opload, v: v.index}) + c.append(&code{op: opcallpc}) + } + return nil + } else if e.Name == "$ENV" || e.Name == "env" { + env := make(map[string]interface{}) + if c.environLoader != nil { + for _, kv := range c.environLoader() { + if i := strings.IndexByte(kv, '='); i > 0 { + env[kv[:i]] = kv[i+1:] + } + } + } + c.append(&code{op: opconst, v: env}) + return nil + } else if e.Name[0] == '$' { + return &variableNotFoundError{e.Name} + } + } else { + for i := len(c.scopes) - 1; i >= 0; i-- { + s := c.scopes[i] + for j := len(s.funcs) - 1; j >= 0; j-- { + if f := s.funcs[j]; f.name == e.Name && f.argcnt == len(e.Args) { + return c.compileCallPc(f, e.Args) + } + } + } + } + if f := c.lookupBuiltin(e.Name, len(e.Args)); f != nil { + return c.compileCallPc(f, e.Args) + } + if fds, ok := builtinFuncDefs[e.Name]; ok { + for _, fd := range fds { + if len(fd.Args) == len(e.Args) { + if err := c.compileFuncDef(fd, true); err != nil { + return err + } + break + } + } + if f := c.lookupBuiltin(e.Name, len(e.Args)); f != nil { + return c.compileCallPc(f, e.Args) + } + } + if fn, ok := internalFuncs[e.Name]; ok && fn.accept(len(e.Args)) { + switch e.Name { + case "empty": + c.append(&code{op: opbacktrack}) + return nil + case "path": + c.append(&code{op: oppathbegin}) + if err := c.compileCall(e.Name, e.Args); err != nil { + return err + } + c.codes[len(c.codes)-1] = &code{op: oppathend} + return nil + case "builtins": + return c.compileCallInternal( + [3]interface{}{c.funcBuiltins, 0, e.Name}, + e.Args, + true, + false, + ) + case "input": + if c.inputIter == nil { + return &inputNotAllowedError{} + } + return c.compileCallInternal( + [3]interface{}{c.funcInput, 0, e.Name}, + e.Args, + true, + false, + ) + case "modulemeta": + return c.compileCallInternal( + [3]interface{}{c.funcModulemeta, 0, e.Name}, + e.Args, + true, + false, + ) + default: + return c.compileCall(e.Name, e.Args) + } + } + if fn, ok := c.customFuncs[e.Name]; ok && fn.accept(len(e.Args)) { + if err := c.compileCallInternal( + [3]interface{}{fn.callback, len(e.Args), e.Name}, + e.Args, + true, + false, + ); err != nil { + return err + } + if fn.iter { + c.append(&code{op: opiter}) + } + return nil + } + return &funcNotFoundError{e} +} + +func (c *compiler) funcBuiltins(interface{}, []interface{}) interface{} { + type funcNameArity struct { + name string + arity int + } + var xs []*funcNameArity + for _, fds := range builtinFuncDefs { + for _, fd := range fds { + if fd.Name[0] != '_' { + xs = append(xs, &funcNameArity{fd.Name, len(fd.Args)}) + } + } + } + for name, fn := range internalFuncs { + if name[0] != '_' { + for i, cnt := 0, fn.argcount; cnt > 0; i, cnt = i+1, cnt>>1 { + if cnt&1 > 0 { + xs = append(xs, &funcNameArity{name, i}) + } + } + } + } + for name, fn := range c.customFuncs { + if name[0] != '_' { + for i, cnt := 0, fn.argcount; cnt > 0; i, cnt = i+1, cnt>>1 { + if cnt&1 > 0 { + xs = append(xs, &funcNameArity{name, i}) + } + } + } + } + sort.Slice(xs, func(i, j int) bool { + return xs[i].name < xs[j].name || + xs[i].name == xs[j].name && xs[i].arity < xs[j].arity + }) + ys := make([]interface{}, len(xs)) + for i, x := range xs { + ys[i] = x.name + "/" + strconv.Itoa(x.arity) + } + return ys +} + +func (c *compiler) funcInput(interface{}, []interface{}) interface{} { + v, ok := c.inputIter.Next() + if !ok { + return errors.New("break") + } + return normalizeNumbers(v) +} + +func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"modulemeta", v} + } + if c.moduleLoader == nil { + return fmt.Errorf("cannot load module: %q", s) + } + var q *Query + var err error + if moduleLoader, ok := c.moduleLoader.(interface { + LoadModuleWithMeta(string, map[string]interface{}) (*Query, error) + }); ok { + if q, err = moduleLoader.LoadModuleWithMeta(s, nil); err != nil { + return err + } + } else if moduleLoader, ok := c.moduleLoader.(interface { + LoadModule(string) (*Query, error) + }); ok { + if q, err = moduleLoader.LoadModule(s); err != nil { + return err + } + } + meta := q.Meta.ToValue() + if meta == nil { + meta = make(map[string]interface{}) + } + var deps []interface{} + for _, i := range q.Imports { + v := i.Meta.ToValue() + if v == nil { + v = make(map[string]interface{}) + } else { + for k := range v { + // dirty hack to remove the internal fields + if strings.HasPrefix(k, "$$") { + delete(v, k) + } + } + } + if i.ImportPath == "" { + v["relpath"] = i.IncludePath + } else { + v["relpath"] = i.ImportPath + } + if err != nil { + return err + } + if i.ImportAlias != "" { + v["as"] = strings.TrimPrefix(i.ImportAlias, "$") + } + v["is_data"] = strings.HasPrefix(i.ImportAlias, "$") + deps = append(deps, v) + } + meta["deps"] = deps + return meta +} + +func (c *compiler) compileObject(e *Object) error { + c.appendCodeInfo(e) + if len(e.KeyVals) == 0 { + c.append(&code{op: opconst, v: map[string]interface{}{}}) + return nil + } + defer c.newScopeDepth()() + v := c.newVariable() + c.append(&code{op: opstore, v: v}) + pc := len(c.codes) + for _, kv := range e.KeyVals { + if err := c.compileObjectKeyVal(v, kv); err != nil { + return err + } + } + c.append(&code{op: opobject, v: len(e.KeyVals)}) + // optimize constant objects + l := len(e.KeyVals) + if pc+l*3+1 != len(c.codes) { + return nil + } + for i := 0; i < l; i++ { + if c.codes[pc+i*3].op != oppush || + c.codes[pc+i*3+1].op != opload || + c.codes[pc+i*3+2].op != opconst { + return nil + } + } + w := make(map[string]interface{}, l) + for i := 0; i < l; i++ { + w[c.codes[pc+i*3].v.(string)] = c.codes[pc+i*3+2].v + } + c.codes[pc-1] = &code{op: opconst, v: w} + c.codes = c.codes[:pc] + return nil +} + +func (c *compiler) compileObjectKeyVal(v [2]int, kv *ObjectKeyVal) error { + if key := kv.Key; key != "" { + if key[0] == '$' { + if kv.Val == nil { // {$foo} == {foo:$foo} + c.append(&code{op: oppush, v: key[1:]}) + } + c.append(&code{op: opload, v: v}) + if err := c.compileFunc(&Func{Name: key}); err != nil { + return err + } + } else { + c.append(&code{op: oppush, v: key}) + if kv.Val == nil { // {foo} == {foo:.foo} + c.append(&code{op: opload, v: v}) + c.append(&code{op: opindex, v: key}) + } + } + } else if key := kv.KeyString; key != nil { + if key.Queries == nil { + c.append(&code{op: oppush, v: key.Str}) + if kv.Val == nil { // {"foo"} == {"foo":.["foo"]} + c.append(&code{op: opload, v: v}) + c.append(&code{op: opindex, v: key.Str}) + } + } else { + c.append(&code{op: opload, v: v}) + if err := c.compileString(key, nil); err != nil { + return err + } + if kv.Val == nil { + c.append(&code{op: opdup}) + c.append(&code{op: opload, v: v}) + c.append(&code{op: oppush, v: nil}) + // ref: compileCall + c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["_index"].callback, 2, "_index"}}) + } + } + } else if kv.KeyQuery != nil { + c.append(&code{op: opload, v: v}) + f := c.newScopeDepth() + if err := c.compileQuery(kv.KeyQuery); err != nil { + return err + } + f() + } + if kv.Val != nil { + c.append(&code{op: opload, v: v}) + for _, e := range kv.Val.Queries { + if err := c.compileQuery(e); err != nil { + return err + } + } + } + return nil +} + +func (c *compiler) compileArray(e *Array) error { + c.appendCodeInfo(e) + if e.Query == nil { + c.append(&code{op: opconst, v: []interface{}{}}) + return nil + } + c.append(&code{op: oppush, v: []interface{}{}}) + arr := c.newVariable() + c.append(&code{op: opstore, v: arr}) + pc := len(c.codes) + setfork := c.lazy(func() *code { + return &code{op: opfork, v: len(c.codes)} + }) + defer c.newScopeDepth()() + if err := c.compileQuery(e.Query); err != nil { + return err + } + c.append(&code{op: opappend, v: arr}) + c.append(&code{op: opbacktrack}) + setfork() + c.append(&code{op: oppop}) + c.append(&code{op: opload, v: arr}) + if e.Query.Op == OpPipe { + return nil + } + // optimize constant arrays + if (len(c.codes)-pc)%3 != 0 { + return nil + } + l := (len(c.codes) - pc - 3) / 3 + for i := 0; i < l; i++ { + if c.codes[pc+i].op != opfork || + c.codes[pc+i*2+l].op != opconst || + (i < l-1 && c.codes[pc+i*2+l+1].op != opjump) { + return nil + } + } + v := make([]interface{}, l) + for i := 0; i < l; i++ { + v[i] = c.codes[pc+i*2+l].v + } + c.codes[pc-2] = &code{op: opconst, v: v} + c.codes = c.codes[:pc-1] + return nil +} + +func (c *compiler) compileUnary(e *Unary) error { + c.appendCodeInfo(e) + if v := e.toNumber(); v != nil { + c.append(&code{op: opconst, v: v}) + return nil + } + if err := c.compileTerm(e.Term); err != nil { + return err + } + switch e.Op { + case OpAdd: + return c.compileCall("_plus", nil) + case OpSub: + return c.compileCall("_negate", nil) + default: + return fmt.Errorf("unexpected operator in Unary: %s", e.Op) + } +} + +func (c *compiler) compileFormat(fmt string, str *String) error { + f := formatToFunc(fmt) + if f == nil { + f = &Func{ + Name: "format", + Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: fmt[1:]}}}}, + } + } + if str == nil { + return c.compileFunc(f) + } + return c.compileString(str, f) +} + +func formatToFunc(fmt string) *Func { + switch fmt { + case "@text": + return &Func{Name: "tostring"} + case "@json": + return &Func{Name: "tojson"} + case "@html": + return &Func{Name: "_tohtml"} + case "@uri": + return &Func{Name: "_touri"} + case "@csv": + return &Func{Name: "_tocsv"} + case "@tsv": + return &Func{Name: "_totsv"} + case "@sh": + return &Func{Name: "_tosh"} + case "@base64": + return &Func{Name: "_tobase64"} + case "@base64d": + return &Func{Name: "_tobase64d"} + default: + return nil + } +} + +func (c *compiler) compileString(s *String, f *Func) error { + if s.Queries == nil { + c.append(&code{op: opconst, v: s.Str}) + return nil + } + if f == nil { + f = &Func{Name: "tostring"} + } + var q *Query + for _, e := range s.Queries { + if e.Term.Str == nil { + e = &Query{Left: e, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: f}}} + } + if q == nil { + q = e + } else { + q = &Query{Left: q, Op: OpAdd, Right: e} + } + } + return c.compileQuery(q) +} + +func (c *compiler) compileTermSuffix(e *Term, s *Suffix) error { + if s.Index != nil { + return c.compileIndex(e, s.Index) + } else if s.Iter { + if err := c.compileTerm(e); err != nil { + return err + } + c.append(&code{op: opiter}) + return nil + } else if s.Optional { + if len(e.SuffixList) > 0 { + if u := e.SuffixList[len(e.SuffixList)-1].toTerm(); u != nil { + // no need to clone (ref: compileTerm) + e.SuffixList = e.SuffixList[:len(e.SuffixList)-1] + if err := c.compileTerm(e); err != nil { + return err + } + e = u + } + } + return c.compileTry(&Try{Body: &Query{Term: e}}) + } else if s.Bind != nil { + return c.compileBind(e, s.Bind) + } else { + return fmt.Errorf("invalid suffix: %s", s) + } +} + +func (c *compiler) compileCall(name string, args []*Query) error { + fn := internalFuncs[name] + if err := c.compileCallInternal( + [3]interface{}{fn.callback, len(args), name}, + args, + true, + name == "_index" || name == "_slice", + ); err != nil { + return err + } + if fn.iter { + c.append(&code{op: opiter}) + } + return nil +} + +func (c *compiler) compileCallPc(fn *funcinfo, args []*Query) error { + return c.compileCallInternal(fn.pc, args, false, false) +} + +func (c *compiler) compileCallInternal( + fn interface{}, args []*Query, internal, indexing bool) error { + if len(args) == 0 { + c.append(&code{op: opcall, v: fn}) + return nil + } + v := c.newVariable() + c.append(&code{op: opstore, v: v}) + if indexing { + c.append(&code{op: opexpbegin}) + } + for i := len(args) - 1; i >= 0; i-- { + pc := len(c.codes) + 1 // skip opjump (ref: compileFuncDef) + name := "lambda:" + strconv.Itoa(pc) + if err := c.compileFuncDef(&FuncDef{Name: name, Body: args[i]}, false); err != nil { + return err + } + if internal { + switch len(c.codes) - pc { + case 2: // optimize identity argument (opscope, opret) + j := len(c.codes) - 3 + c.codes[j] = &code{op: opload, v: v} + c.codes = c.codes[:j+1] + s := c.scopes[len(c.scopes)-1] + s.funcs = s.funcs[:len(s.funcs)-1] + c.deleteCodeInfo(name) + case 3: // optimize one instruction argument (opscope, opX, opret) + j := len(c.codes) - 4 + if c.codes[j+2].op == opconst { + c.codes[j] = &code{op: oppush, v: c.codes[j+2].v} + c.codes = c.codes[:j+1] + } else { + c.codes[j] = &code{op: opload, v: v} + c.codes[j+1] = c.codes[j+2] + c.codes = c.codes[:j+2] + } + s := c.scopes[len(c.scopes)-1] + s.funcs = s.funcs[:len(s.funcs)-1] + c.deleteCodeInfo(name) + default: + c.append(&code{op: opload, v: v}) + c.append(&code{op: oppushpc, v: pc}) + c.append(&code{op: opcallpc}) + } + } else { + c.append(&code{op: oppushpc, v: pc}) + } + if indexing && i == 1 { + if c.codes[len(c.codes)-2].op == opexpbegin { + c.codes[len(c.codes)-2] = c.codes[len(c.codes)-1] + c.codes = c.codes[:len(c.codes)-1] + } else { + c.append(&code{op: opexpend}) + } + } + } + if indexing { + c.append(&code{op: oppush, v: nil}) + } else { + c.append(&code{op: opload, v: v}) + } + c.append(&code{op: opcall, v: fn}) + return nil +} + +func (c *compiler) append(code *code) { + c.codes = append(c.codes, code) +} + +func (c *compiler) lazy(f func() *code) func() { + i := len(c.codes) + c.codes = append(c.codes, nil) + return func() { c.codes[i] = f() } +} + +func (c *compiler) optimizeTailRec() { + var pcs []int + scopes := map[int]bool{} +L: + for i, l := 0, len(c.codes); i < l; i++ { + switch c.codes[i].op { + case opscope: + pcs = append(pcs, i) + if v := c.codes[i].v.([3]int); v[2] == 0 { + scopes[i] = v[1] == 0 + } + case opcall: + var canjump bool + if j, ok := c.codes[i].v.(int); !ok || + len(pcs) == 0 || pcs[len(pcs)-1] != j { + break + } else if canjump, ok = scopes[j]; !ok { + break + } + for j := i + 1; j < l; { + switch c.codes[j].op { + case opjump: + j = c.codes[j].v.(int) + case opret: + if canjump { + c.codes[i].op = opjump + c.codes[i].v = pcs[len(pcs)-1] + 1 + } else { + c.codes[i].op = opcallrec + } + continue L + default: + continue L + } + } + case opret: + if len(pcs) == 0 { + break L + } + pcs = pcs[:len(pcs)-1] + } + } +} + +func (c *compiler) optimizeCodeOps() { + for i, next := len(c.codes)-1, (*code)(nil); i >= 0; i-- { + code := c.codes[i] + switch code.op { + case oppush, opdup, opload: + switch next.op { + case oppop: + code.op = opnop + next.op = opnop + case opconst: + code.op = opnop + next.op = oppush + } + case opjump, opjumpifnot: + if j := code.v.(int); j-1 == i { + code.op = opnop + } else if next = c.codes[j]; next.op == opjump { + code.v = next.v + } + } + next = code + } +} diff --git a/vendor/github.com/itchyny/gojq/debug.go b/vendor/github.com/itchyny/gojq/debug.go new file mode 100644 index 00000000..c353ac80 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/debug.go @@ -0,0 +1,210 @@ +//go:build gojq_debug +// +build gojq_debug + +package gojq + +import ( + "fmt" + "io" + "os" + "strconv" + "strings" +) + +var ( + debug bool + debugOut io.Writer +) + +func init() { + if out := os.Getenv("GOJQ_DEBUG"); out != "" { + debug = true + if out == "stdout" { + debugOut = os.Stdout + } else { + debugOut = os.Stderr + } + } +} + +type codeinfo struct { + name string + pc int +} + +func (c *compiler) appendCodeInfo(x interface{}) { + if !debug { + return + } + var name string + switch x := x.(type) { + case string: + name = x + default: + name = fmt.Sprint(x) + } + var diff int + if c.codes[len(c.codes)-1] != nil && c.codes[len(c.codes)-1].op == opret && strings.HasPrefix(name, "end of ") { + diff = -1 + } + c.codeinfos = append(c.codeinfos, codeinfo{name, len(c.codes) + diff}) +} + +func (c *compiler) deleteCodeInfo(name string) { + for i := 0; i < len(c.codeinfos); i++ { + if strings.HasSuffix(c.codeinfos[i].name, name) { + copy(c.codeinfos[i:], c.codeinfos[i+1:]) + c.codeinfos = c.codeinfos[:len(c.codeinfos)-1] + i-- + } + } +} + +func (env *env) lookupInfoName(pc int) string { + var name string + for _, ci := range env.codeinfos { + if ci.pc == pc { + if name != "" { + name += ", " + } + name += ci.name + } + } + return name +} + +func (env *env) debugCodes() { + if !debug { + return + } + for i, c := range env.codes { + pc := i + switch c.op { + case opcall, opcallrec: + if x, ok := c.v.(int); ok { + pc = x + } + case opjump: + x := c.v.(int) + if x > 0 && env.codes[x-1].op == opscope { + pc = x - 1 + } + } + var s string + if name := env.lookupInfoName(pc); name != "" { + switch c.op { + case opcall, opcallrec, opjump: + if !strings.HasPrefix(name, "module ") { + s = "\t## call " + name + break + } + fallthrough + default: + s = "\t## " + name + } + } + fmt.Fprintf(debugOut, "\t%d\t%s%s%s\n", i, formatOp(c.op, false), debugOperand(c), s) + } + fmt.Fprintln(debugOut, "\t"+strings.Repeat("-", 40)+"+") +} + +func (env *env) debugState(pc int, backtrack bool) { + if !debug { + return + } + var sb strings.Builder + c := env.codes[pc] + fmt.Fprintf(&sb, "\t%d\t%s%s\t|", pc, formatOp(c.op, backtrack), debugOperand(c)) + var xs []int + for i := env.stack.index; i >= 0; i = env.stack.data[i].next { + xs = append(xs, i) + } + for i := len(xs) - 1; i >= 0; i-- { + sb.WriteString("\t") + sb.WriteString(debugValue(env.stack.data[xs[i]].value)) + } + switch c.op { + case opcall, opcallrec: + if x, ok := c.v.(int); ok { + pc = x + } + case opjump: + x := c.v.(int) + if x > 0 && env.codes[x-1].op == opscope { + pc = x - 1 + } + } + if name := env.lookupInfoName(pc); name != "" { + switch c.op { + case opcall, opcallrec, opjump: + if !strings.HasPrefix(name, "module ") { + sb.WriteString("\t\t\t## call " + name) + break + } + fallthrough + default: + sb.WriteString("\t\t\t## " + name) + } + } + fmt.Fprintln(debugOut, sb.String()) +} + +func formatOp(c opcode, backtrack bool) string { + if backtrack { + return c.String() + " " + strings.Repeat(" ", 13-len(c.String())) + } + return c.String() + strings.Repeat(" ", 25-len(c.String())) +} + +func (env *env) debugForks(pc int, op string) { + if !debug { + return + } + var sb strings.Builder + for i, v := range env.forks { + if i > 0 { + sb.WriteByte('\t') + } + if i == len(env.forks)-1 { + sb.WriteByte('<') + } + fmt.Fprintf(&sb, "%d, %s", v.pc, debugValue(env.stack.data[v.stackindex].value)) + if i == len(env.forks)-1 { + sb.WriteByte('>') + } + } + fmt.Fprintf(debugOut, "\t-\t%s%s%d\t|\t%s\n", op, strings.Repeat(" ", 22), pc, sb.String()) +} + +func debugOperand(c *code) string { + switch c.op { + case opcall, opcallrec: + switch v := c.v.(type) { + case int: + return strconv.Itoa(v) + case [3]interface{}: + return fmt.Sprintf("%s/%d", v[2], v[1]) + default: + panic(c) + } + default: + return debugValue(c.v) + } +} + +func debugValue(v interface{}) string { + switch v := v.(type) { + case Iter: + return fmt.Sprintf("gojq.Iter(%#v)", v) + case []pathValue: + return fmt.Sprintf("[]gojq.pathValue(%v)", v) + case [2]int: + return fmt.Sprintf("[%d,%d]", v[0], v[1]) + case [3]int: + return fmt.Sprintf("[%d,%d,%d]", v[0], v[1], v[2]) + case [3]interface{}: + return fmt.Sprintf("[%v,%v,%v]", v[0], v[1], v[2]) + default: + return Preview(v) + } +} diff --git a/vendor/github.com/itchyny/gojq/encoder.go b/vendor/github.com/itchyny/gojq/encoder.go new file mode 100644 index 00000000..d61456cd --- /dev/null +++ b/vendor/github.com/itchyny/gojq/encoder.go @@ -0,0 +1,193 @@ +package gojq + +import ( + "bytes" + "fmt" + "io" + "math" + "math/big" + "sort" + "strconv" + "strings" + "unicode/utf8" +) + +// Marshal returns the jq-flavored JSON encoding of v. +// +// This method accepts only limited types (nil, bool, int, float64, *big.Int, +// string, []interface{}, and map[string]interface{}) because these are the +// possible types a gojq iterator can emit. This method marshals NaN to null, +// truncates infinities to (+|-) math.MaxFloat64, uses \b and \f in strings, +// and does not escape '<', '>', '&', '\u2028', and '\u2029'. These behaviors +// are based on the marshaler of jq command, and different from json.Marshal in +// the Go standard library. Note that the result is not safe to embed in HTML. +func Marshal(v interface{}) ([]byte, error) { + var b bytes.Buffer + (&encoder{w: &b}).encode(v) + return b.Bytes(), nil +} + +func jsonMarshal(v interface{}) string { + var sb strings.Builder + (&encoder{w: &sb}).encode(v) + return sb.String() +} + +func jsonEncodeString(sb *strings.Builder, v string) { + (&encoder{w: sb}).encodeString(v) +} + +type encoder struct { + w interface { + io.Writer + io.ByteWriter + io.StringWriter + } + buf [64]byte +} + +func (e *encoder) encode(v interface{}) { + switch v := v.(type) { + case nil: + e.w.WriteString("null") + case bool: + if v { + e.w.WriteString("true") + } else { + e.w.WriteString("false") + } + case int: + e.w.Write(strconv.AppendInt(e.buf[:0], int64(v), 10)) + case float64: + e.encodeFloat64(v) + case *big.Int: + e.w.Write(v.Append(e.buf[:0], 10)) + case string: + e.encodeString(v) + case []interface{}: + e.encodeArray(v) + case map[string]interface{}: + e.encodeMap(v) + default: + panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v)) + } +} + +// ref: floatEncoder in encoding/json +func (e *encoder) encodeFloat64(f float64) { + if math.IsNaN(f) { + e.w.WriteString("null") + return + } + if f >= math.MaxFloat64 { + f = math.MaxFloat64 + } else if f <= -math.MaxFloat64 { + f = -math.MaxFloat64 + } + fmt := byte('f') + if x := math.Abs(f); x != 0 && x < 1e-6 || x >= 1e21 { + fmt = 'e' + } + buf := strconv.AppendFloat(e.buf[:0], f, fmt, -1, 64) + if fmt == 'e' { + // clean up e-09 to e-9 + if n := len(buf); n >= 4 && buf[n-4] == 'e' && buf[n-3] == '-' && buf[n-2] == '0' { + buf[n-2] = buf[n-1] + buf = buf[:n-1] + } + } + e.w.Write(buf) +} + +// ref: encodeState#string in encoding/json +func (e *encoder) encodeString(s string) { + e.w.WriteByte('"') + start := 0 + for i := 0; i < len(s); { + if b := s[i]; b < utf8.RuneSelf { + if ' ' <= b && b <= '~' && b != '"' && b != '\\' { + i++ + continue + } + if start < i { + e.w.WriteString(s[start:i]) + } + switch b { + case '"': + e.w.WriteString(`\"`) + case '\\': + e.w.WriteString(`\\`) + case '\b': + e.w.WriteString(`\b`) + case '\f': + e.w.WriteString(`\f`) + case '\n': + e.w.WriteString(`\n`) + case '\r': + e.w.WriteString(`\r`) + case '\t': + e.w.WriteString(`\t`) + default: + const hex = "0123456789abcdef" + e.w.WriteString(`\u00`) + e.w.WriteByte(hex[b>>4]) + e.w.WriteByte(hex[b&0xF]) + } + i++ + start = i + continue + } + c, size := utf8.DecodeRuneInString(s[i:]) + if c == utf8.RuneError && size == 1 { + if start < i { + e.w.WriteString(s[start:i]) + } + e.w.WriteString(`\ufffd`) + i += size + start = i + continue + } + i += size + } + if start < len(s) { + e.w.WriteString(s[start:]) + } + e.w.WriteByte('"') +} + +func (e *encoder) encodeArray(vs []interface{}) { + e.w.WriteByte('[') + for i, v := range vs { + if i > 0 { + e.w.WriteByte(',') + } + e.encode(v) + } + e.w.WriteByte(']') +} + +func (e *encoder) encodeMap(vs map[string]interface{}) { + e.w.WriteByte('{') + type keyVal struct { + key string + val interface{} + } + kvs := make([]keyVal, len(vs)) + var i int + for k, v := range vs { + kvs[i] = keyVal{k, v} + i++ + } + sort.Slice(kvs, func(i, j int) bool { + return kvs[i].key < kvs[j].key + }) + for i, kv := range kvs { + if i > 0 { + e.w.WriteByte(',') + } + e.encodeString(kv.key) + e.w.WriteByte(':') + e.encode(kv.val) + } + e.w.WriteByte('}') +} diff --git a/vendor/github.com/itchyny/gojq/env.go b/vendor/github.com/itchyny/gojq/env.go new file mode 100644 index 00000000..dd1859c4 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/env.go @@ -0,0 +1,48 @@ +package gojq + +import "context" + +type env struct { + pc int + stack *stack + paths *stack + scopes *scopeStack + values []interface{} + codes []*code + codeinfos []codeinfo + forks []fork + backtrack bool + offset int + expdepth int + label int + args [32]interface{} // len(env.args) > maxarity + ctx context.Context +} + +func newEnv(ctx context.Context) *env { + return &env{ + stack: newStack(), + paths: newStack(), + scopes: newScopeStack(), + ctx: ctx, + } +} + +type scope struct { + id int + offset int + pc int + saveindex int + outerindex int +} + +type fork struct { + pc int + stackindex int + stacklimit int + scopeindex int + scopelimit int + pathindex int + pathlimit int + expdepth int +} diff --git a/vendor/github.com/itchyny/gojq/error.go b/vendor/github.com/itchyny/gojq/error.go new file mode 100644 index 00000000..c72d69ec --- /dev/null +++ b/vendor/github.com/itchyny/gojq/error.go @@ -0,0 +1,340 @@ +package gojq + +import "strconv" + +// ValueError is an interface for errors with a value for internal function. +// Return an error implementing this interface when you want to catch error +// values (not error messages) by try-catch, just like built-in error function. +// Refer to WithFunction to add a custom internal function. +type ValueError interface { + error + Value() interface{} +} + +type expectedObjectError struct { + v interface{} +} + +func (err *expectedObjectError) Error() string { + return "expected an object but got: " + typeErrorPreview(err.v) +} + +type expectedArrayError struct { + v interface{} +} + +func (err *expectedArrayError) Error() string { + return "expected an array but got: " + typeErrorPreview(err.v) +} + +type expectedStringError struct { + v interface{} +} + +func (err *expectedStringError) Error() string { + return "expected a string but got: " + typeErrorPreview(err.v) +} + +type iteratorError struct { + v interface{} +} + +func (err *iteratorError) Error() string { + return "cannot iterate over: " + typeErrorPreview(err.v) +} + +type arrayIndexTooLargeError struct { + v interface{} +} + +func (err *arrayIndexTooLargeError) Error() string { + return "array index too large: " + Preview(err.v) +} + +type objectKeyNotStringError struct { + v interface{} +} + +func (err *objectKeyNotStringError) Error() string { + return "expected a string for object key but got: " + typeErrorPreview(err.v) +} + +type arrayIndexNotNumberError struct { + v interface{} +} + +func (err *arrayIndexNotNumberError) Error() string { + return "expected a number for indexing an array but got: " + typeErrorPreview(err.v) +} + +type stringIndexNotNumberError struct { + v interface{} +} + +func (err *stringIndexNotNumberError) Error() string { + return "expected a number for indexing a string but got: " + typeErrorPreview(err.v) +} + +type expectedStartEndError struct { + v interface{} +} + +func (err *expectedStartEndError) Error() string { + return `expected "start" and "end" for slicing but got: ` + typeErrorPreview(err.v) +} + +type lengthMismatchError struct { + name string + v, x []interface{} +} + +func (err *lengthMismatchError) Error() string { + return "length mismatch in " + err.name + ": " + typeErrorPreview(err.v) + ", " + typeErrorPreview(err.x) +} + +type inputNotAllowedError struct{} + +func (*inputNotAllowedError) Error() string { + return "input(s)/0 is not allowed" +} + +type funcNotFoundError struct { + f *Func +} + +func (err *funcNotFoundError) Error() string { + return "function not defined: " + err.f.Name + "/" + strconv.Itoa(len(err.f.Args)) +} + +type funcTypeError struct { + name string + v interface{} +} + +func (err *funcTypeError) Error() string { + return err.name + " cannot be applied to: " + typeErrorPreview(err.v) +} + +type exitCodeError struct { + value interface{} + code int + halt bool +} + +func (err *exitCodeError) Error() string { + if s, ok := err.value.(string); ok { + return "error: " + s + } + return "error: " + jsonMarshal(err.value) +} + +func (err *exitCodeError) IsEmptyError() bool { + return err.value == nil +} + +func (err *exitCodeError) Value() interface{} { + return err.value +} + +func (err *exitCodeError) ExitCode() int { + return err.code +} + +func (err *exitCodeError) IsHaltError() bool { + return err.halt +} + +type containsTypeError struct { + l, r interface{} +} + +func (err *containsTypeError) Error() string { + return "cannot check contains(" + Preview(err.r) + "): " + typeErrorPreview(err.l) +} + +type hasKeyTypeError struct { + l, r interface{} +} + +func (err *hasKeyTypeError) Error() string { + return "cannot check whether " + typeErrorPreview(err.l) + " has a key: " + typeErrorPreview(err.r) +} + +type flattenDepthError struct { + v float64 +} + +func (err *flattenDepthError) Error() string { + return "flatten depth must not be negative: " + typeErrorPreview(err.v) +} + +type joinTypeError struct { + v interface{} +} + +func (err *joinTypeError) Error() string { + return "cannot join: " + typeErrorPreview(err.v) +} + +type unaryTypeError struct { + name string + v interface{} +} + +func (err *unaryTypeError) Error() string { + return "cannot " + err.name + ": " + typeErrorPreview(err.v) +} + +type binopTypeError struct { + name string + l, r interface{} +} + +func (err *binopTypeError) Error() string { + return "cannot " + err.name + ": " + typeErrorPreview(err.l) + " and " + typeErrorPreview(err.r) +} + +type zeroDivisionError struct { + l, r interface{} +} + +func (err *zeroDivisionError) Error() string { + return "cannot divide " + typeErrorPreview(err.l) + " by: " + typeErrorPreview(err.r) +} + +type zeroModuloError struct { + l, r interface{} +} + +func (err *zeroModuloError) Error() string { + return "cannot modulo " + typeErrorPreview(err.l) + " by: " + typeErrorPreview(err.r) +} + +type formatNotFoundError struct { + n string +} + +func (err *formatNotFoundError) Error() string { + return "format not defined: " + err.n +} + +type formatRowError struct { + typ string + v interface{} +} + +func (err *formatRowError) Error() string { + return "@" + err.typ + " cannot format an array including: " + typeErrorPreview(err.v) +} + +type tooManyVariableValuesError struct{} + +func (err *tooManyVariableValuesError) Error() string { + return "too many variable values provided" +} + +type expectedVariableError struct { + n string +} + +func (err *expectedVariableError) Error() string { + return "variable defined but not bound: " + err.n +} + +type variableNotFoundError struct { + n string +} + +func (err *variableNotFoundError) Error() string { + return "variable not defined: " + err.n +} + +type variableNameError struct { + n string +} + +func (err *variableNameError) Error() string { + return "invalid variable name: " + err.n +} + +type breakError struct { + n string + v interface{} +} + +func (err *breakError) Error() string { + return "label not defined: " + err.n +} + +func (err *breakError) ExitCode() int { + return 3 +} + +type tryEndError struct { + err error +} + +func (err *tryEndError) Error() string { + return err.err.Error() +} + +type invalidPathError struct { + v interface{} +} + +func (err *invalidPathError) Error() string { + return "invalid path against: " + typeErrorPreview(err.v) +} + +type invalidPathIterError struct { + v interface{} +} + +func (err *invalidPathIterError) Error() string { + return "invalid path on iterating against: " + typeErrorPreview(err.v) +} + +type getpathError struct { + v, path interface{} +} + +func (err *getpathError) Error() string { + return "cannot getpath with " + Preview(err.path) + " against: " + typeErrorPreview(err.v) +} + +type queryParseError struct { + fname, contents string + err error +} + +func (err *queryParseError) QueryParseError() (string, string, error) { + return err.fname, err.contents, err.err +} + +func (err *queryParseError) Error() string { + return "invalid query: " + err.fname + ": " + err.err.Error() +} + +type jsonParseError struct { + fname, contents string + err error +} + +func (err *jsonParseError) JSONParseError() (string, string, error) { + return err.fname, err.contents, err.err +} + +func (err *jsonParseError) Error() string { + return "invalid json: " + err.fname + ": " + err.err.Error() +} + +func typeErrorPreview(v interface{}) string { + switch v.(type) { + case nil: + return "null" + case Iter: + return "gojq.Iter" + default: + return TypeOf(v) + " (" + Preview(v) + ")" + } +} diff --git a/vendor/github.com/itchyny/gojq/execute.go b/vendor/github.com/itchyny/gojq/execute.go new file mode 100644 index 00000000..695481cf --- /dev/null +++ b/vendor/github.com/itchyny/gojq/execute.go @@ -0,0 +1,453 @@ +package gojq + +import ( + "context" + "math" + "reflect" + "sort" +) + +func (env *env) execute(bc *Code, v interface{}, vars ...interface{}) Iter { + env.codes = bc.codes + env.codeinfos = bc.codeinfos + env.push(v) + for i := len(vars) - 1; i >= 0; i-- { + env.push(vars[i]) + } + env.debugCodes() + return env +} + +func (env *env) Next() (interface{}, bool) { + var err error + pc, callpc, index := env.pc, len(env.codes)-1, -1 + backtrack, hasCtx := env.backtrack, env.ctx != context.Background() + defer func() { env.pc, env.backtrack = pc, true }() +loop: + for ; pc < len(env.codes); pc++ { + env.debugState(pc, backtrack) + code := env.codes[pc] + if hasCtx { + select { + case <-env.ctx.Done(): + pc, env.forks = len(env.codes), nil + return env.ctx.Err(), true + default: + } + } + switch code.op { + case opnop: + // nop + case oppush: + env.push(code.v) + case oppop: + env.pop() + case opdup: + v := env.pop() + env.push(v) + env.push(v) + case opconst: + env.pop() + env.push(code.v) + case opload: + env.push(env.values[env.index(code.v.([2]int))]) + case opstore: + env.values[env.index(code.v.([2]int))] = env.pop() + case opobject: + if backtrack { + break loop + } + n := code.v.(int) + m := make(map[string]interface{}, n) + for i := 0; i < n; i++ { + v, k := env.pop(), env.pop() + s, ok := k.(string) + if !ok { + err = &objectKeyNotStringError{k} + break loop + } + m[s] = v + } + env.push(m) + case opappend: + i := env.index(code.v.([2]int)) + env.values[i] = append(env.values[i].([]interface{}), env.pop()) + case opfork: + if backtrack { + if err != nil { + break loop + } + pc, backtrack = code.v.(int), false + goto loop + } + env.pushfork(pc) + case opforktrybegin: + if backtrack { + if err == nil { + break loop + } + switch er := err.(type) { + case *tryEndError: + err = er.err + break loop + case ValueError: + if er, ok := er.(*exitCodeError); ok && er.halt { + break loop + } + if v := er.Value(); v != nil { + env.pop() + env.push(v) + } else { + err = nil + break loop + } + default: + env.pop() + env.push(err.Error()) + } + pc, backtrack, err = code.v.(int), false, nil + goto loop + } + env.pushfork(pc) + case opforktryend: + if backtrack { + if err != nil { + err = &tryEndError{err} + } + break loop + } + env.pushfork(pc) + case opforkalt: + if backtrack { + if err == nil { + break loop + } + pc, backtrack, err = code.v.(int), false, nil + goto loop + } + env.pushfork(pc) + case opforklabel: + if backtrack { + label := env.pop() + if e, ok := err.(*breakError); ok && e.v == label { + err = nil + } + break loop + } + env.push(env.label) + env.pushfork(pc) + env.pop() + env.values[env.index(code.v.([2]int))] = env.label + env.label++ + case opbacktrack: + break loop + case opjump: + pc = code.v.(int) + goto loop + case opjumpifnot: + if v := env.pop(); v == nil || v == false { + pc = code.v.(int) + goto loop + } + case opindex, opindexarray: + if backtrack { + break loop + } + p, v := code.v, env.pop() + if code.op == opindexarray && v != nil { + if _, ok := v.([]interface{}); !ok { + err = &expectedArrayError{v} + break loop + } + } + w := funcIndex2(nil, v, p) + if e, ok := w.(error); ok { + err = e + break loop + } + env.push(w) + if !env.paths.empty() && env.expdepth == 0 { + if !env.pathIntact(v) { + err = &invalidPathError{v} + break loop + } + env.paths.push(pathValue{path: p, value: w}) + } + case opcall: + if backtrack { + break loop + } + switch v := code.v.(type) { + case int: + pc, callpc, index = v, pc, env.scopes.index + goto loop + case [3]interface{}: + argcnt := v[1].(int) + x, args := env.pop(), env.args[:argcnt] + for i := 0; i < argcnt; i++ { + args[i] = env.pop() + } + w := v[0].(func(interface{}, []interface{}) interface{})(x, args) + if e, ok := w.(error); ok { + if er, ok := e.(*exitCodeError); !ok || er.value != nil || er.halt { + err = e + } + break loop + } + env.push(w) + if !env.paths.empty() && env.expdepth == 0 { + switch v[2].(string) { + case "_index": + if x = args[0]; !env.pathIntact(x) { + err = &invalidPathError{x} + break loop + } + env.paths.push(pathValue{path: args[1], value: w}) + case "_slice": + if x = args[0]; !env.pathIntact(x) { + err = &invalidPathError{x} + break loop + } + env.paths.push(pathValue{ + path: map[string]interface{}{"start": args[2], "end": args[1]}, + value: w, + }) + case "getpath": + if !env.pathIntact(x) { + err = &invalidPathError{x} + break loop + } + for _, p := range args[0].([]interface{}) { + env.paths.push(pathValue{path: p, value: w}) + } + } + } + default: + panic(v) + } + case opcallrec: + pc, callpc, index = code.v.(int), -1, env.scopes.index + goto loop + case oppushpc: + env.push([2]int{code.v.(int), env.scopes.index}) + case opcallpc: + xs := env.pop().([2]int) + pc, callpc, index = xs[0], pc, xs[1] + goto loop + case opscope: + xs := code.v.([3]int) + var saveindex, outerindex int + if index == env.scopes.index { + if callpc >= 0 { + saveindex = index + } else { + callpc, saveindex = env.popscope() + } + } else { + saveindex, _ = env.scopes.save() + env.scopes.index = index + } + if outerindex = index; outerindex >= 0 { + if s := env.scopes.data[outerindex].value; s.id == xs[0] { + outerindex = s.outerindex + } + } + env.scopes.push(scope{xs[0], env.offset, callpc, saveindex, outerindex}) + env.offset += xs[1] + if env.offset > len(env.values) { + vs := make([]interface{}, env.offset*2) + copy(vs, env.values) + env.values = vs + } + case opret: + if backtrack { + break loop + } + pc, env.scopes.index = env.popscope() + if env.scopes.empty() { + return env.pop(), true + } + case opiter: + if err != nil { + break loop + } + backtrack = false + var xs []pathValue + switch v := env.pop().(type) { + case []pathValue: + xs = v + case []interface{}: + if !env.paths.empty() && env.expdepth == 0 && !env.pathIntact(v) { + err = &invalidPathIterError{v} + break loop + } + if len(v) == 0 { + break loop + } + xs = make([]pathValue, len(v)) + for i, v := range v { + xs[i] = pathValue{path: i, value: v} + } + case map[string]interface{}: + if !env.paths.empty() && env.expdepth == 0 && !env.pathIntact(v) { + err = &invalidPathIterError{v} + break loop + } + if len(v) == 0 { + break loop + } + xs = make([]pathValue, len(v)) + var i int + for k, v := range v { + xs[i] = pathValue{path: k, value: v} + i++ + } + sort.Slice(xs, func(i, j int) bool { + return xs[i].path.(string) < xs[j].path.(string) + }) + case Iter: + if !env.paths.empty() && env.expdepth == 0 { + err = &invalidPathIterError{v} + break loop + } + if w, ok := v.Next(); ok { + env.push(v) + env.pushfork(pc) + env.pop() + if e, ok := w.(error); ok { + err = e + break loop + } + env.push(w) + continue + } + break loop + default: + err = &iteratorError{v} + env.push(emptyIter{}) + break loop + } + if len(xs) > 1 { + env.push(xs[1:]) + env.pushfork(pc) + env.pop() + } + env.push(xs[0].value) + if !env.paths.empty() && env.expdepth == 0 { + env.paths.push(xs[0]) + } + case opexpbegin: + env.expdepth++ + case opexpend: + env.expdepth-- + case oppathbegin: + env.paths.push(env.expdepth) + env.paths.push(pathValue{value: env.stack.top()}) + env.expdepth = 0 + case oppathend: + if backtrack { + break loop + } + env.pop() + if v := env.pop(); !env.pathIntact(v) { + err = &invalidPathError{v} + break loop + } + env.push(env.poppaths()) + env.expdepth = env.paths.pop().(int) + default: + panic(code.op) + } + } + if len(env.forks) > 0 { + pc, backtrack = env.popfork(), true + goto loop + } + if err != nil { + return err, true + } + return nil, false +} + +func (env *env) push(v interface{}) { + env.stack.push(v) +} + +func (env *env) pop() interface{} { + return env.stack.pop() +} + +func (env *env) popscope() (int, int) { + free := env.scopes.index > env.scopes.limit + s := env.scopes.pop() + if free { + env.offset = s.offset + } + return s.pc, s.saveindex +} + +func (env *env) pushfork(pc int) { + f := fork{pc: pc, expdepth: env.expdepth} + f.stackindex, f.stacklimit = env.stack.save() + f.scopeindex, f.scopelimit = env.scopes.save() + f.pathindex, f.pathlimit = env.paths.save() + env.forks = append(env.forks, f) + env.debugForks(pc, ">>>") +} + +func (env *env) popfork() int { + f := env.forks[len(env.forks)-1] + env.debugForks(f.pc, "<<<") + env.forks, env.expdepth = env.forks[:len(env.forks)-1], f.expdepth + env.stack.restore(f.stackindex, f.stacklimit) + env.scopes.restore(f.scopeindex, f.scopelimit) + env.paths.restore(f.pathindex, f.pathlimit) + return f.pc +} + +func (env *env) index(v [2]int) int { + for id, i := v[0], env.scopes.index; i >= 0; { + s := env.scopes.data[i].value + if s.id == id { + return s.offset + v[1] + } + i = s.outerindex + } + panic("env.index") +} + +type pathValue struct { + path, value interface{} +} + +func (env *env) pathIntact(v interface{}) bool { + w := env.paths.top().(pathValue).value + switch v := v.(type) { + case []interface{}, map[string]interface{}: + switch w.(type) { + case []interface{}, map[string]interface{}: + v, w := reflect.ValueOf(v), reflect.ValueOf(w) + return v.Pointer() == w.Pointer() && v.Len() == w.Len() + } + case float64: + if w, ok := w.(float64); ok { + return v == w || math.IsNaN(v) && math.IsNaN(w) + } + } + return v == w +} + +func (env *env) poppaths() []interface{} { + var xs []interface{} + for { + p := env.paths.pop().(pathValue) + if p.path == nil { + break + } + xs = append(xs, p.path) + } + for i, j := 0, len(xs)-1; i < j; i, j = i+1, j-1 { + xs[i], xs[j] = xs[j], xs[i] + } + return xs +} diff --git a/vendor/github.com/itchyny/gojq/func.go b/vendor/github.com/itchyny/gojq/func.go new file mode 100644 index 00000000..25268e07 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/func.go @@ -0,0 +1,1975 @@ +package gojq + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "math" + "math/big" + "net/url" + "regexp" + "sort" + "strconv" + "strings" + "time" + "unicode/utf8" + + "github.com/itchyny/timefmt-go" +) + +//go:generate go run -modfile=go.dev.mod _tools/gen_builtin.go -i builtin.jq -o builtin.go +var builtinFuncDefs map[string][]*FuncDef + +const ( + argcount0 = 1 << iota + argcount1 + argcount2 + argcount3 +) + +type function struct { + argcount int + iter bool + callback func(interface{}, []interface{}) interface{} +} + +func (fn function) accept(cnt int) bool { + return fn.argcount&(1<= 0 { + return v + } + return -v + case float64: + return math.Abs(v) + case *big.Int: + if v.Sign() >= 0 { + return v + } + return new(big.Int).Abs(v) + case string: + return len([]rune(v)) + case []interface{}: + return len(v) + case map[string]interface{}: + return len(v) + default: + return &funcTypeError{"length", v} + } +} + +func funcUtf8ByteLength(v interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"utf8bytelength", v} + } + return len(s) +} + +func funcKeys(v interface{}) interface{} { + switch v := v.(type) { + case []interface{}: + w := make([]interface{}, len(v)) + for i := range v { + w[i] = i + } + return w + case map[string]interface{}: + w := make([]interface{}, len(v)) + for i, k := range keys(v) { + w[i] = k + } + return w + default: + return &funcTypeError{"keys", v} + } +} + +func keys(v map[string]interface{}) []string { + w := make([]string, len(v)) + var i int + for k := range v { + w[i] = k + i++ + } + sort.Strings(w) + return w +} + +func values(v interface{}) ([]interface{}, bool) { + switch v := v.(type) { + case []interface{}: + return v, true + case map[string]interface{}: + vs := make([]interface{}, len(v)) + for i, k := range keys(v) { + vs[i] = v[k] + } + return vs, true + default: + return nil, false + } +} + +func funcHas(v, x interface{}) interface{} { + switch v := v.(type) { + case []interface{}: + if x, ok := toInt(x); ok { + return 0 <= x && x < len(v) + } + case map[string]interface{}: + if x, ok := x.(string); ok { + _, ok := v[x] + return ok + } + case nil: + return false + } + return &hasKeyTypeError{v, x} +} + +func funcToEntries(v interface{}) interface{} { + switch v := v.(type) { + case []interface{}: + w := make([]interface{}, len(v)) + for i, x := range v { + w[i] = map[string]interface{}{"key": i, "value": x} + } + return w + case map[string]interface{}: + w := make([]interface{}, len(v)) + for i, k := range keys(v) { + w[i] = map[string]interface{}{"key": k, "value": v[k]} + } + return w + default: + return &funcTypeError{"to_entries", v} + } +} + +func funcFromEntries(v interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"from_entries", v} + } + w := make(map[string]interface{}, len(vs)) + for _, v := range vs { + switch v := v.(type) { + case map[string]interface{}: + var ( + key string + value interface{} + ok bool + ) + for _, k := range [4]string{"key", "Key", "name", "Name"} { + if k := v[k]; k != nil && k != false { + if key, ok = k.(string); !ok { + return &objectKeyNotStringError{k} + } + break + } + } + if !ok { + return &objectKeyNotStringError{nil} + } + for _, k := range [2]string{"value", "Value"} { + if value, ok = v[k]; ok { + break + } + } + w[key] = value + default: + return &funcTypeError{"from_entries", v} + } + } + return w +} + +func funcAdd(v interface{}) interface{} { + vs, ok := values(v) + if !ok { + return &funcTypeError{"add", v} + } + v = nil + for _, x := range vs { + switch x := x.(type) { + case nil: + continue + case string: + switch w := v.(type) { + case nil: + var sb strings.Builder + sb.WriteString(x) + v = &sb + continue + case *strings.Builder: + w.WriteString(x) + continue + } + case []interface{}: + switch w := v.(type) { + case nil: + s := make([]interface{}, len(x)) + copy(s, x) + v = s + continue + case []interface{}: + v = append(w, x...) + continue + } + case map[string]interface{}: + switch w := v.(type) { + case nil: + m := make(map[string]interface{}, len(x)) + for k, e := range x { + m[k] = e + } + v = m + continue + case map[string]interface{}: + for k, e := range x { + w[k] = e + } + continue + } + } + if sb, ok := v.(*strings.Builder); ok { + v = sb.String() + } + v = funcOpAdd(nil, v, x) + if err, ok := v.(error); ok { + return err + } + } + if sb, ok := v.(*strings.Builder); ok { + v = sb.String() + } + return v +} + +func funcToNumber(v interface{}) interface{} { + switch v := v.(type) { + case int, float64, *big.Int: + return v + case string: + if !newLexer(v).validNumber() { + return fmt.Errorf("invalid number: %q", v) + } + return toNumber(v) + default: + return &funcTypeError{"tonumber", v} + } +} + +func toNumber(v string) interface{} { + return normalizeNumber(json.Number(v)) +} + +func funcToString(v interface{}) interface{} { + if s, ok := v.(string); ok { + return s + } + return funcToJSON(v) +} + +func funcType(v interface{}) interface{} { + return TypeOf(v) +} + +func funcReverse(v interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"reverse", v} + } + ws := make([]interface{}, len(vs)) + for i, v := range vs { + ws[len(ws)-i-1] = v + } + return ws +} + +func funcContains(v, x interface{}) interface{} { + return binopTypeSwitch(v, x, + func(l, r int) interface{} { return l == r }, + func(l, r float64) interface{} { return l == r }, + func(l, r *big.Int) interface{} { return l.Cmp(r) == 0 }, + func(l, r string) interface{} { return strings.Contains(l, r) }, + func(l, r []interface{}) interface{} { + R: + for _, r := range r { + for _, l := range l { + if funcContains(l, r) == true { + continue R + } + } + return false + } + return true + }, + func(l, r map[string]interface{}) interface{} { + if len(l) < len(r) { + return false + } + for k, r := range r { + if l, ok := l[k]; !ok || funcContains(l, r) != true { + return false + } + } + return true + }, + func(l, r interface{}) interface{} { + if l == r { + return true + } + return &containsTypeError{l, r} + }, + ) +} + +func funcIndices(v, x interface{}) interface{} { + return indexFunc(v, x, indices) +} + +func indices(vs, xs []interface{}) interface{} { + var rs []interface{} + if len(xs) == 0 { + return rs + } + for i := 0; i <= len(vs)-len(xs); i++ { + if compare(vs[i:i+len(xs)], xs) == 0 { + rs = append(rs, i) + } + } + return rs +} + +func funcIndex(v, x interface{}) interface{} { + return indexFunc(v, x, func(vs, xs []interface{}) interface{} { + if len(xs) == 0 { + return nil + } + for i := 0; i <= len(vs)-len(xs); i++ { + if compare(vs[i:i+len(xs)], xs) == 0 { + return i + } + } + return nil + }) +} + +func funcRindex(v, x interface{}) interface{} { + return indexFunc(v, x, func(vs, xs []interface{}) interface{} { + if len(xs) == 0 { + return nil + } + for i := len(vs) - len(xs); i >= 0; i-- { + if compare(vs[i:i+len(xs)], xs) == 0 { + return i + } + } + return nil + }) +} + +func indexFunc(v, x interface{}, f func(_, _ []interface{}) interface{}) interface{} { + switch v := v.(type) { + case nil: + return nil + case []interface{}: + switch x := x.(type) { + case []interface{}: + return f(v, x) + default: + return f(v, []interface{}{x}) + } + case string: + if x, ok := x.(string); ok { + return f(explode(v), explode(x)) + } + return &expectedStringError{x} + default: + return &expectedArrayError{v} + } +} + +func funcStartsWith(v, x interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"startswith", v} + } + t, ok := x.(string) + if !ok { + return &funcTypeError{"startswith", x} + } + return strings.HasPrefix(s, t) +} + +func funcEndsWith(v, x interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"endswith", v} + } + t, ok := x.(string) + if !ok { + return &funcTypeError{"endswith", x} + } + return strings.HasSuffix(s, t) +} + +func funcLtrimstr(v, x interface{}) interface{} { + s, ok := v.(string) + if !ok { + return v + } + t, ok := x.(string) + if !ok { + return v + } + return strings.TrimPrefix(s, t) +} + +func funcRtrimstr(v, x interface{}) interface{} { + s, ok := v.(string) + if !ok { + return v + } + t, ok := x.(string) + if !ok { + return v + } + return strings.TrimSuffix(s, t) +} + +func funcExplode(v interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"explode", v} + } + return explode(s) +} + +func explode(s string) []interface{} { + xs := make([]interface{}, len([]rune(s))) + var i int + for _, r := range s { + xs[i] = int(r) + i++ + } + return xs +} + +func funcImplode(v interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"implode", v} + } + var sb strings.Builder + sb.Grow(len(vs)) + for _, v := range vs { + if r, ok := toInt(v); ok && 0 <= r && r <= utf8.MaxRune { + sb.WriteRune(rune(r)) + } else { + return &funcTypeError{"implode", vs} + } + } + return sb.String() +} + +func funcSplit(v interface{}, args []interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"split", v} + } + x, ok := args[0].(string) + if !ok { + return &funcTypeError{"split", x} + } + var ss []string + if len(args) == 1 { + ss = strings.Split(s, x) + } else { + var flags string + if args[1] != nil { + v, ok := args[1].(string) + if !ok { + return &funcTypeError{"split", args[1]} + } + flags = v + } + r, err := compileRegexp(x, flags) + if err != nil { + return err + } + ss = r.Split(s, -1) + } + xs := make([]interface{}, len(ss)) + for i, s := range ss { + xs[i] = s + } + return xs +} + +func funcToJSON(v interface{}) interface{} { + return jsonMarshal(v) +} + +func funcFromJSON(v interface{}) interface{} { + s, ok := v.(string) + if !ok { + return &funcTypeError{"fromjson", v} + } + var w interface{} + dec := json.NewDecoder(strings.NewReader(s)) + dec.UseNumber() + if err := dec.Decode(&w); err != nil { + return err + } + return normalizeNumbers(w) +} + +func funcFormat(v, x interface{}) interface{} { + s, ok := x.(string) + if !ok { + return &funcTypeError{"format", x} + } + fmt := "@" + s + f := formatToFunc(fmt) + if f == nil { + return &formatNotFoundError{fmt} + } + return internalFuncs[f.Name].callback(v, nil) +} + +var htmlEscaper = strings.NewReplacer( + `<`, "<", + `>`, ">", + `&`, "&", + `'`, "'", + `"`, """, +) + +func funcToHTML(v interface{}) interface{} { + switch x := funcToString(v).(type) { + case string: + return htmlEscaper.Replace(x) + default: + return x + } +} + +func funcToURI(v interface{}) interface{} { + switch x := funcToString(v).(type) { + case string: + return url.QueryEscape(x) + default: + return x + } +} + +func funcToCSV(v interface{}) interface{} { + return formatJoin("csv", v, ",", func(s string) string { + return `"` + strings.ReplaceAll(s, `"`, `""`) + `"` + }) +} + +var tsvEscaper = strings.NewReplacer( + "\t", `\t`, + "\r", `\r`, + "\n", `\n`, + "\\", `\\`, +) + +func funcToTSV(v interface{}) interface{} { + return formatJoin("tsv", v, "\t", tsvEscaper.Replace) +} + +func funcToSh(v interface{}) interface{} { + if _, ok := v.([]interface{}); !ok { + v = []interface{}{v} + } + return formatJoin("sh", v, " ", func(s string) string { + return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'" + }) +} + +func formatJoin(typ string, v interface{}, sep string, escape func(string) string) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"@" + typ, v} + } + ss := make([]string, len(vs)) + for i, v := range vs { + switch v := v.(type) { + case []interface{}, map[string]interface{}: + return &formatRowError{typ, v} + case string: + ss[i] = escape(v) + default: + if s := jsonMarshal(v); s != "null" || typ == "sh" { + ss[i] = s + } + } + } + return strings.Join(ss, sep) +} + +func funcToBase64(v interface{}) interface{} { + switch x := funcToString(v).(type) { + case string: + return base64.StdEncoding.EncodeToString([]byte(x)) + default: + return x + } +} + +func funcToBase64d(v interface{}) interface{} { + switch x := funcToString(v).(type) { + case string: + if i := strings.IndexRune(x, base64.StdPadding); i >= 0 { + x = x[:i] + } + y, err := base64.RawStdEncoding.DecodeString(x) + if err != nil { + return err + } + return string(y) + default: + return x + } +} + +func funcIndex2(_, v, x interface{}) interface{} { + switch x := x.(type) { + case string: + switch v := v.(type) { + case nil: + return nil + case map[string]interface{}: + return v[x] + default: + return &expectedObjectError{v} + } + case int, float64, *big.Int: + i, _ := toInt(x) + switch v := v.(type) { + case nil: + return nil + case []interface{}: + return index(v, i) + case string: + return indexString(v, i) + default: + return &expectedArrayError{v} + } + case []interface{}: + switch v := v.(type) { + case nil: + return nil + case []interface{}: + return indices(v, x) + default: + return &expectedArrayError{v} + } + case map[string]interface{}: + if v == nil { + return nil + } + start, ok := x["start"] + if !ok { + return &expectedStartEndError{x} + } + end, ok := x["end"] + if !ok { + return &expectedStartEndError{x} + } + return funcSlice(nil, v, end, start) + default: + switch v.(type) { + case []interface{}: + return &arrayIndexNotNumberError{x} + case string: + return &stringIndexNotNumberError{x} + default: + return &objectKeyNotStringError{x} + } + } +} + +func index(vs []interface{}, i int) interface{} { + i = clampIndex(i, -1, len(vs)) + if 0 <= i && i < len(vs) { + return vs[i] + } + return nil +} + +func indexString(s string, i int) interface{} { + l := len([]rune(s)) + i = clampIndex(i, -1, l) + if 0 <= i && i < l { + for _, r := range s { + if i--; i < 0 { + return string(r) + } + } + } + return nil +} + +func funcSlice(_, v, e, s interface{}) (r interface{}) { + switch v := v.(type) { + case nil: + return nil + case []interface{}: + return slice(v, e, s) + case string: + return sliceString(v, e, s) + default: + return &expectedArrayError{v} + } +} + +func slice(vs []interface{}, e, s interface{}) interface{} { + var start, end int + if s != nil { + if i, ok := toInt(s); ok { + start = clampIndex(i, 0, len(vs)) + } else { + return &arrayIndexNotNumberError{s} + } + } + if e != nil { + if i, ok := toInt(e); ok { + end = clampIndex(i, start, len(vs)) + } else { + return &arrayIndexNotNumberError{e} + } + } else { + end = len(vs) + } + return vs[start:end] +} + +func sliceString(v string, e, s interface{}) interface{} { + var start, end int + l := len([]rune(v)) + if s != nil { + if i, ok := toInt(s); ok { + start = clampIndex(i, 0, l) + } else { + return &stringIndexNotNumberError{s} + } + } + if e != nil { + if i, ok := toInt(e); ok { + end = clampIndex(i, start, l) + } else { + return &stringIndexNotNumberError{e} + } + } else { + end = l + } + if start < l { + for i := range v { + if start--; start < 0 { + start = i + break + } + } + } else { + start = len(v) + } + if end < l { + for i := range v { + if end--; end < 0 { + end = i + break + } + } + } else { + end = len(v) + } + return v[start:end] +} + +func clampIndex(i, min, max int) int { + if i < 0 { + i += max + } + if i < min { + return min + } else if i < max { + return i + } else { + return max + } +} + +func funcFlatten(v interface{}, args []interface{}) interface{} { + vs, ok := values(v) + if !ok { + return &funcTypeError{"flatten", v} + } + var depth float64 + if len(args) == 0 { + depth = -1 + } else { + depth, ok = toFloat(args[0]) + if !ok { + return &funcTypeError{"flatten", args[0]} + } + if depth < 0 { + return &flattenDepthError{depth} + } + } + return flatten(nil, vs, depth) +} + +func flatten(xs, vs []interface{}, depth float64) []interface{} { + for _, v := range vs { + if vs, ok := v.([]interface{}); ok && depth != 0 { + xs = flatten(xs, vs, depth-1) + } else { + xs = append(xs, v) + } + } + return xs +} + +type rangeIter struct { + value, end, step interface{} +} + +func (iter *rangeIter) Next() (interface{}, bool) { + if compare(iter.step, 0)*compare(iter.value, iter.end) >= 0 { + return nil, false + } + v := iter.value + iter.value = funcOpAdd(nil, v, iter.step) + return v, true +} + +func funcRange(_ interface{}, xs []interface{}) interface{} { + for _, x := range xs { + switch x.(type) { + case int, float64, *big.Int: + default: + return &funcTypeError{"range", x} + } + } + return &rangeIter{xs[0], xs[1], xs[2]} +} + +func funcMin(v interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"min", v} + } + return minMaxBy(vs, vs, true) +} + +func funcMinBy(v, x interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"min_by", v} + } + xs, ok := x.([]interface{}) + if !ok { + return &funcTypeError{"min_by", x} + } + if len(vs) != len(xs) { + return &lengthMismatchError{"min_by", vs, xs} + } + return minMaxBy(vs, xs, true) +} + +func funcMax(v interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"max", v} + } + return minMaxBy(vs, vs, false) +} + +func funcMaxBy(v, x interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"max_by", v} + } + xs, ok := x.([]interface{}) + if !ok { + return &funcTypeError{"max_by", x} + } + if len(vs) != len(xs) { + return &lengthMismatchError{"max_by", vs, xs} + } + return minMaxBy(vs, xs, false) +} + +func minMaxBy(vs, xs []interface{}, isMin bool) interface{} { + if len(vs) == 0 { + return nil + } + i, j, x := 0, 0, xs[0] + for i++; i < len(xs); i++ { + if compare(x, xs[i]) > 0 == isMin { + j, x = i, xs[i] + } + } + return vs[j] +} + +type sortItem struct { + value, key interface{} +} + +func sortItems(name string, v, x interface{}) ([]*sortItem, error) { + vs, ok := v.([]interface{}) + if !ok { + return nil, &funcTypeError{name, v} + } + xs, ok := x.([]interface{}) + if !ok { + return nil, &funcTypeError{name, x} + } + if len(vs) != len(xs) { + return nil, &lengthMismatchError{name, vs, xs} + } + items := make([]*sortItem, len(vs)) + for i, v := range vs { + items[i] = &sortItem{v, xs[i]} + } + sort.SliceStable(items, func(i, j int) bool { + return compare(items[i].key, items[j].key) < 0 + }) + return items, nil +} + +func funcSort(v interface{}) interface{} { + return sortBy("sort", v, v) +} + +func funcSortBy(v, x interface{}) interface{} { + return sortBy("sort_by", v, x) +} + +func sortBy(name string, v, x interface{}) interface{} { + items, err := sortItems(name, v, x) + if err != nil { + return err + } + rs := make([]interface{}, len(items)) + for i, x := range items { + rs[i] = x.value + } + return rs +} + +func funcGroupBy(v, x interface{}) interface{} { + items, err := sortItems("group_by", v, x) + if err != nil { + return err + } + var rs []interface{} + var last interface{} + for i, r := range items { + if i == 0 || compare(last, r.key) != 0 { + rs, last = append(rs, []interface{}{r.value}), r.key + } else { + rs[len(rs)-1] = append(rs[len(rs)-1].([]interface{}), r.value) + } + } + return rs +} + +func funcUnique(v interface{}) interface{} { + return uniqueBy("unique", v, v) +} + +func funcUniqueBy(v, x interface{}) interface{} { + return uniqueBy("unique_by", v, x) +} + +func uniqueBy(name string, v, x interface{}) interface{} { + items, err := sortItems(name, v, x) + if err != nil { + return err + } + var rs []interface{} + var last interface{} + for i, r := range items { + if i == 0 || compare(last, r.key) != 0 { + rs, last = append(rs, r.value), r.key + } + } + return rs +} + +func funcJoin(v, x interface{}) interface{} { + vs, ok := values(v) + if !ok { + return &funcTypeError{"join", v} + } + if len(vs) == 0 { + return "" + } + sep, ok := x.(string) + if len(vs) > 1 && !ok { + return &funcTypeError{"join", x} + } + ss := make([]string, len(vs)) + for i, v := range vs { + switch v := v.(type) { + case nil: + case string: + ss[i] = v + case bool: + if v { + ss[i] = "true" + } else { + ss[i] = "false" + } + case int, float64, *big.Int: + ss[i] = jsonMarshal(v) + default: + return &joinTypeError{v} + } + } + return strings.Join(ss, sep) +} + +func funcSignificand(v float64) float64 { + if math.IsNaN(v) || math.IsInf(v, 0) || v == 0.0 { + return v + } + return math.Float64frombits((math.Float64bits(v) & 0x800fffffffffffff) | 0x3ff0000000000000) +} + +func funcExp10(v float64) float64 { + return math.Pow(10, v) +} + +func funcFrexp(v interface{}) interface{} { + x, ok := toFloat(v) + if !ok { + return &funcTypeError{"frexp", v} + } + f, e := math.Frexp(x) + return []interface{}{f, e} +} + +func funcModf(v interface{}) interface{} { + x, ok := toFloat(v) + if !ok { + return &funcTypeError{"modf", v} + } + i, f := math.Modf(x) + return []interface{}{f, i} +} + +func funcLgamma(v float64) float64 { + v, _ = math.Lgamma(v) + return v +} + +func funcDrem(l, r float64) float64 { + x := math.Remainder(l, r) + if x == 0.0 { + return math.Copysign(x, l) + } + return x +} + +func funcJn(l, r float64) float64 { + return math.Jn(int(l), r) +} + +func funcLdexp(l, r float64) float64 { + return math.Ldexp(l, int(r)) +} + +func funcScalb(l, r float64) float64 { + return l * math.Pow(2, r) +} + +func funcScalbln(l, r float64) float64 { + return l * math.Pow(2, r) +} + +func funcYn(l, r float64) float64 { + return math.Yn(int(l), r) +} + +func funcInfinite(interface{}) interface{} { + return math.Inf(1) +} + +func funcIsfinite(v interface{}) interface{} { + x, ok := toFloat(v) + return ok && !math.IsInf(x, 0) +} + +func funcIsinfinite(v interface{}) interface{} { + x, ok := toFloat(v) + return ok && math.IsInf(x, 0) +} + +func funcNan(interface{}) interface{} { + return math.NaN() +} + +func funcIsnan(v interface{}) interface{} { + x, ok := toFloat(v) + if !ok { + if v == nil { + return false + } + return &funcTypeError{"isnan", v} + } + return math.IsNaN(x) +} + +func funcIsnormal(v interface{}) interface{} { + x, ok := toFloat(v) + return ok && !math.IsNaN(x) && !math.IsInf(x, 0) && x != 0.0 +} + +func funcSetpath(v, p, n interface{}) interface{} { + path, ok := p.([]interface{}) + if !ok { + return &funcTypeError{"setpath", p} + } + var err error + if v, err = update(v, path, n); err != nil { + if err, ok := err.(*funcTypeError); ok { + err.name = "setpath" + } + return err + } + return v +} + +func funcDelpaths(v, p interface{}) interface{} { + paths, ok := p.([]interface{}) + if !ok { + return &funcTypeError{"delpaths", p} + } + // Fills the paths with an empty value and then delete them. We cannot delete + // in each loop because array indices should not change. For example, + // jq -n "[0, 1, 2, 3] | delpaths([[1], [2]])" #=> [0, 3]. + var empty struct{} + var err error + for _, p := range paths { + path, ok := p.([]interface{}) + if !ok { + return &funcTypeError{"delpaths", p} + } + if v, err = update(v, path, empty); err != nil { + return err + } + } + return deleteEmpty(v) +} + +func update(v interface{}, path []interface{}, n interface{}) (interface{}, error) { + if len(path) == 0 { + return n, nil + } + switch p := path[0].(type) { + case string: + switch v := v.(type) { + case nil: + return updateObject(nil, p, path[1:], n) + case map[string]interface{}: + return updateObject(v, p, path[1:], n) + case struct{}: + return v, nil + default: + return nil, &expectedObjectError{v} + } + case int, float64, *big.Int: + i, _ := toInt(p) + switch v := v.(type) { + case nil: + return updateArrayIndex(nil, i, path[1:], n) + case []interface{}: + return updateArrayIndex(v, i, path[1:], n) + case struct{}: + return v, nil + default: + return nil, &expectedArrayError{v} + } + case map[string]interface{}: + switch v := v.(type) { + case nil: + return updateArraySlice(nil, p, path[1:], n) + case []interface{}: + return updateArraySlice(v, p, path[1:], n) + case struct{}: + return v, nil + default: + return nil, &expectedArrayError{v} + } + default: + switch v.(type) { + case []interface{}: + return nil, &arrayIndexNotNumberError{p} + default: + return nil, &objectKeyNotStringError{p} + } + } +} + +func updateObject(v map[string]interface{}, k string, path []interface{}, n interface{}) (interface{}, error) { + x, ok := v[k] + if !ok && n == struct{}{} { + return v, nil + } + u, err := update(x, path, n) + if err != nil { + return nil, err + } + w := make(map[string]interface{}, len(v)+1) + for k, v := range v { + w[k] = v + } + w[k] = u + return w, nil +} + +func updateArrayIndex(v []interface{}, i int, path []interface{}, n interface{}) (interface{}, error) { + var x interface{} + if j := clampIndex(i, -1, len(v)); j < 0 { + if n == struct{}{} { + return v, nil + } + return nil, &funcTypeError{v: i} + } else if j < len(v) { + i = j + x = v[i] + } else { + if n == struct{}{} { + return v, nil + } + if i >= 0x8000000 { + return nil, &arrayIndexTooLargeError{i} + } + } + u, err := update(x, path, n) + if err != nil { + return nil, err + } + l := len(v) + if i >= l { + l = i + 1 + } + w := make([]interface{}, l) + copy(w, v) + w[i] = u + return w, nil +} + +func updateArraySlice(v []interface{}, m map[string]interface{}, path []interface{}, n interface{}) (interface{}, error) { + s, ok := m["start"] + if !ok { + return nil, &expectedStartEndError{m} + } + e, ok := m["end"] + if !ok { + return nil, &expectedStartEndError{m} + } + var start, end int + if i, ok := toInt(s); ok { + start = clampIndex(i, 0, len(v)) + } + if i, ok := toInt(e); ok { + end = clampIndex(i, start, len(v)) + } else { + end = len(v) + } + if start == end && n == struct{}{} { + return v, nil + } + u, err := update(v[start:end], path, n) + if err != nil { + return nil, err + } + switch u := u.(type) { + case []interface{}: + w := make([]interface{}, len(v)-(end-start)+len(u)) + copy(w, v[:start]) + copy(w[start:], u) + copy(w[start+len(u):], v[end:]) + return w, nil + case struct{}: + w := make([]interface{}, len(v)) + copy(w, v) + for i := start; i < end; i++ { + w[i] = u + } + return w, nil + default: + return nil, &expectedArrayError{u} + } +} + +func deleteEmpty(v interface{}) interface{} { + switch v := v.(type) { + case struct{}: + return nil + case map[string]interface{}: + for k, w := range v { + if w == struct{}{} { + delete(v, k) + } else { + v[k] = deleteEmpty(w) + } + } + return v + case []interface{}: + var j int + for _, w := range v { + if w != struct{}{} { + v[j] = deleteEmpty(w) + j++ + } + } + for i := j; i < len(v); i++ { + v[i] = nil + } + return v[:j] + default: + return v + } +} + +func funcGetpath(v, p interface{}) interface{} { + keys, ok := p.([]interface{}) + if !ok { + return &funcTypeError{"getpath", p} + } + u := v + for _, x := range keys { + switch v.(type) { + case nil, []interface{}, map[string]interface{}: + v = funcIndex2(nil, v, x) + if _, ok := v.(error); ok { + return &getpathError{u, p} + } + default: + return &getpathError{u, p} + } + } + return v +} + +func funcTranspose(v interface{}) interface{} { + vss, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"transpose", v} + } + if len(vss) == 0 { + return []interface{}{} + } + var l int + for _, vs := range vss { + vs, ok := vs.([]interface{}) + if !ok { + return &funcTypeError{"transpose", v} + } + if k := len(vs); l < k { + l = k + } + } + wss := make([][]interface{}, l) + xs := make([]interface{}, l) + for i, k := 0, len(vss); i < l; i++ { + s := make([]interface{}, k) + wss[i] = s + xs[i] = s + } + for i, vs := range vss { + for j, v := range vs.([]interface{}) { + wss[j][i] = v + } + } + return xs +} + +func funcBsearch(v, t interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"bsearch", v} + } + i := sort.Search(len(vs), func(i int) bool { + return compare(vs[i], t) >= 0 + }) + if i < len(vs) && compare(vs[i], t) == 0 { + return i + } + return -i - 1 +} + +func funcGmtime(v interface{}) interface{} { + if v, ok := toFloat(v); ok { + return epochToArray(v, time.UTC) + } + return &funcTypeError{"gmtime", v} +} + +func funcLocaltime(v interface{}) interface{} { + if v, ok := toFloat(v); ok { + return epochToArray(v, time.Local) + } + return &funcTypeError{"localtime", v} +} + +func epochToArray(v float64, loc *time.Location) []interface{} { + t := time.Unix(int64(v), int64((v-math.Floor(v))*1e9)).In(loc) + return []interface{}{ + t.Year(), + int(t.Month()) - 1, + t.Day(), + t.Hour(), + t.Minute(), + float64(t.Second()) + float64(t.Nanosecond())/1e9, + int(t.Weekday()), + t.YearDay() - 1, + } +} + +func funcMktime(v interface{}) interface{} { + if a, ok := v.([]interface{}); ok { + t, err := arrayToTime("mktime", a, time.UTC) + if err != nil { + return err + } + return timeToEpoch(t) + } + return &funcTypeError{"mktime", v} +} + +func timeToEpoch(t time.Time) float64 { + return float64(t.Unix()) + float64(t.Nanosecond())/1e9 +} + +func funcStrftime(v, x interface{}) interface{} { + if w, ok := toFloat(v); ok { + v = epochToArray(w, time.UTC) + } + if a, ok := v.([]interface{}); ok { + if format, ok := x.(string); ok { + t, err := arrayToTime("strftime", a, time.UTC) + if err != nil { + return err + } + return timefmt.Format(t, format) + } + return &funcTypeError{"strftime", x} + } + return &funcTypeError{"strftime", v} +} + +func funcStrflocaltime(v, x interface{}) interface{} { + if w, ok := toFloat(v); ok { + v = epochToArray(w, time.Local) + } + if a, ok := v.([]interface{}); ok { + if format, ok := x.(string); ok { + t, err := arrayToTime("strflocaltime", a, time.Local) + if err != nil { + return err + } + return timefmt.Format(t, format) + } + return &funcTypeError{"strflocaltime", x} + } + return &funcTypeError{"strflocaltime", v} +} + +func funcStrptime(v, x interface{}) interface{} { + if v, ok := v.(string); ok { + if format, ok := x.(string); ok { + t, err := timefmt.Parse(v, format) + if err != nil { + return err + } + var s time.Time + if t == s { + return &funcTypeError{"strptime", v} + } + return epochToArray(timeToEpoch(t), time.UTC) + } + return &funcTypeError{"strptime", x} + } + return &funcTypeError{"strptime", v} +} + +func arrayToTime(name string, a []interface{}, loc *time.Location) (time.Time, error) { + var t time.Time + if len(a) != 8 { + return t, &funcTypeError{name, a} + } + var y, m, d, h, min, sec, nsec int + if x, ok := toInt(a[0]); ok { + y = x + } else { + return t, &funcTypeError{name, a} + } + if x, ok := toInt(a[1]); ok { + m = x + 1 + } else { + return t, &funcTypeError{name, a} + } + if x, ok := toInt(a[2]); ok { + d = x + } else { + return t, &funcTypeError{name, a} + } + if x, ok := toInt(a[3]); ok { + h = x + } else { + return t, &funcTypeError{name, a} + } + if x, ok := toInt(a[4]); ok { + min = x + } else { + return t, &funcTypeError{name, a} + } + if x, ok := toFloat(a[5]); ok { + sec = int(x) + nsec = int((x - math.Floor(x)) * 1e9) + } else { + return t, &funcTypeError{name, a} + } + return time.Date(y, time.Month(m), d, h, min, sec, nsec, loc), nil +} + +func funcNow(interface{}) interface{} { + return timeToEpoch(time.Now()) +} + +func funcMatch(v, re, fs, testing interface{}) interface{} { + var flags string + if fs != nil { + v, ok := fs.(string) + if !ok { + return &funcTypeError{"match", fs} + } + flags = v + } + s, ok := v.(string) + if !ok { + return &funcTypeError{"match", v} + } + restr, ok := re.(string) + if !ok { + return &funcTypeError{"match", v} + } + r, err := compileRegexp(restr, flags) + if err != nil { + return err + } + var xs [][]int + if strings.ContainsRune(flags, 'g') && testing != true { + xs = r.FindAllStringSubmatchIndex(s, -1) + } else { + got := r.FindStringSubmatchIndex(s) + if testing == true { + return got != nil + } + if got != nil { + xs = [][]int{got} + } + } + res, names := make([]interface{}, len(xs)), r.SubexpNames() + for i, x := range xs { + captures := make([]interface{}, (len(x)-2)/2) + for j := 1; j < len(x)/2; j++ { + var name interface{} + if n := names[j]; n != "" { + name = n + } + if x[j*2] < 0 { + captures[j-1] = map[string]interface{}{ + "name": name, + "offset": -1, + "length": 0, + "string": nil, + } + continue + } + captures[j-1] = map[string]interface{}{ + "name": name, + "offset": len([]rune(s[:x[j*2]])), + "length": len([]rune(s[:x[j*2+1]])) - len([]rune(s[:x[j*2]])), + "string": s[x[j*2]:x[j*2+1]], + } + } + res[i] = map[string]interface{}{ + "offset": len([]rune(s[:x[0]])), + "length": len([]rune(s[:x[1]])) - len([]rune(s[:x[0]])), + "string": s[x[0]:x[1]], + "captures": captures, + } + } + return res +} + +func compileRegexp(re, flags string) (*regexp.Regexp, error) { + if strings.IndexFunc(flags, func(r rune) bool { + return r != 'g' && r != 'i' && r != 'm' + }) >= 0 { + return nil, fmt.Errorf("unsupported regular expression flag: %q", flags) + } + re = strings.ReplaceAll(re, "(?<", "(?P<") + if strings.ContainsRune(flags, 'i') { + re = "(?i)" + re + } + if strings.ContainsRune(flags, 'm') { + re = "(?s)" + re + } + r, err := regexp.Compile(re) + if err != nil { + return nil, fmt.Errorf("invalid regular expression %q: %s", re, err) + } + return r, nil +} + +func funcCapture(v interface{}) interface{} { + vs, ok := v.(map[string]interface{}) + if !ok { + return &expectedObjectError{v} + } + v = vs["captures"] + captures, ok := v.([]interface{}) + if !ok { + return &expectedArrayError{v} + } + w := make(map[string]interface{}, len(captures)) + for _, capture := range captures { + if capture, ok := capture.(map[string]interface{}); ok { + if name, ok := capture["name"].(string); ok { + w[name] = capture["string"] + } + } + } + return w +} + +func funcError(v interface{}, args []interface{}) interface{} { + if len(args) > 0 { + v = args[0] + } + code := 5 + if v == nil { + code = 0 + } + return &exitCodeError{v, code, false} +} + +func funcHalt(interface{}) interface{} { + return &exitCodeError{nil, 0, true} +} + +func funcHaltError(v interface{}, args []interface{}) interface{} { + code := 5 + if len(args) > 0 { + var ok bool + if code, ok = toInt(args[0]); !ok { + return &funcTypeError{"halt_error", args[0]} + } + } + return &exitCodeError{v, code, true} +} + +func toInt(x interface{}) (int, bool) { + switch x := x.(type) { + case int: + return x, true + case float64: + return floatToInt(x), true + case *big.Int: + if x.IsInt64() { + if i := x.Int64(); minInt <= i && i <= maxInt { + return int(i), true + } + } + if x.Sign() > 0 { + return maxInt, true + } + return minInt, true + default: + return 0, false + } +} + +func floatToInt(x float64) int { + if minInt <= x && x <= maxInt { + return int(x) + } + if x > 0 { + return maxInt + } + return minInt +} + +func toFloat(x interface{}) (float64, bool) { + switch x := x.(type) { + case int: + return float64(x), true + case float64: + return x, true + case *big.Int: + return bigToFloat(x), true + default: + return 0.0, false + } +} + +func bigToFloat(x *big.Int) float64 { + if x.IsInt64() { + return float64(x.Int64()) + } + if f, err := strconv.ParseFloat(x.String(), 64); err == nil { + return f + } + return math.Inf(x.Sign()) +} diff --git a/vendor/github.com/itchyny/gojq/go.dev.mod b/vendor/github.com/itchyny/gojq/go.dev.mod new file mode 100644 index 00000000..46e652e2 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/go.dev.mod @@ -0,0 +1,8 @@ +module github.com/itchyny/gojq + +go 1.16 + +require ( + github.com/itchyny/astgen-go v0.0.0-20210914105503-cc8fccf6f972 // indirect + github.com/itchyny/timefmt-go v0.1.3 // indirect +) diff --git a/vendor/github.com/itchyny/gojq/go.dev.sum b/vendor/github.com/itchyny/gojq/go.dev.sum new file mode 100644 index 00000000..467aa0b9 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/go.dev.sum @@ -0,0 +1,4 @@ +github.com/itchyny/astgen-go v0.0.0-20210914105503-cc8fccf6f972 h1:XYWolmPDLTY9B1O5o/Ad811/mtVkaHWMiZdbPLm/nDA= +github.com/itchyny/astgen-go v0.0.0-20210914105503-cc8fccf6f972/go.mod h1:jTXcxGeQMJfFN3wWjtzb4aAaWDDN+QbezE0HjH1XfNk= +github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU= +github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A= diff --git a/vendor/github.com/itchyny/gojq/gojq.go b/vendor/github.com/itchyny/gojq/gojq.go new file mode 100644 index 00000000..8f53b356 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/gojq.go @@ -0,0 +1,5 @@ +// Package gojq provides the parser and interpreter of gojq. +// +// Please refer to https://github.com/itchyny/gojq#usage-as-a-library for +// introduction of the usage as a library. +package gojq diff --git a/vendor/github.com/itchyny/gojq/iter.go b/vendor/github.com/itchyny/gojq/iter.go new file mode 100644 index 00000000..0cee25ba --- /dev/null +++ b/vendor/github.com/itchyny/gojq/iter.go @@ -0,0 +1,49 @@ +package gojq + +// Iter is an interface for an iterator. +type Iter interface { + Next() (interface{}, bool) +} + +// NewIter creates a new Iter from values. +func NewIter(values ...interface{}) Iter { + switch len(values) { + case 0: + return emptyIter{} + case 1: + return &unitIter{value: values[0]} + default: + iter := sliceIter(values) + return &iter + } +} + +type emptyIter struct{} + +func (emptyIter) Next() (interface{}, bool) { + return nil, false +} + +type unitIter struct { + value interface{} + done bool +} + +func (iter *unitIter) Next() (interface{}, bool) { + if iter.done { + return nil, false + } + iter.done = true + return iter.value, true +} + +type sliceIter []interface{} + +func (iter *sliceIter) Next() (interface{}, bool) { + if len(*iter) == 0 { + return nil, false + } + value := (*iter)[0] + *iter = (*iter)[1:] + return value, true +} diff --git a/vendor/github.com/itchyny/gojq/lexer.go b/vendor/github.com/itchyny/gojq/lexer.go new file mode 100644 index 00000000..82bb2b6b --- /dev/null +++ b/vendor/github.com/itchyny/gojq/lexer.go @@ -0,0 +1,573 @@ +package gojq + +import ( + "encoding/json" + "unicode/utf8" +) + +type lexer struct { + source string + offset int + result *Query + token string + tokenType int + inString bool + err error +} + +func newLexer(src string) *lexer { + return &lexer{source: src} +} + +const eof = -1 + +var keywords = map[string]int{ + "or": tokOrOp, + "and": tokAndOp, + "module": tokModule, + "import": tokImport, + "include": tokInclude, + "def": tokDef, + "as": tokAs, + "label": tokLabel, + "break": tokBreak, + "null": tokNull, + "true": tokTrue, + "false": tokFalse, + "if": tokIf, + "then": tokThen, + "elif": tokElif, + "else": tokElse, + "end": tokEnd, + "try": tokTry, + "catch": tokCatch, + "reduce": tokReduce, + "foreach": tokForeach, +} + +func (l *lexer) Lex(lval *yySymType) (tokenType int) { + defer func() { l.tokenType = tokenType }() + if len(l.source) == l.offset { + l.token = "" + return eof + } + if l.inString { + tok, str := l.scanString(l.offset) + lval.token = str + return tok + } + ch, iseof := l.next() + if iseof { + l.token = "" + return eof + } + switch { + case isIdent(ch, false): + i := l.offset - 1 + j, isModule := l.scanIdentOrModule() + l.token = l.source[i:j] + lval.token = l.token + if isModule { + return tokModuleIdent + } + if tok, ok := keywords[l.token]; ok { + return tok + } + return tokIdent + case isNumber(ch): + i := l.offset - 1 + j := l.scanNumber(numberStateLead) + if j < 0 { + l.token = l.source[i:-j] + return tokInvalid + } + l.token = l.source[i:j] + lval.token = l.token + return tokNumber + } + switch ch { + case '.': + ch := l.peek() + switch { + case ch == '.': + l.offset++ + l.token = ".." + return tokRecurse + case isIdent(ch, false): + l.token = l.source[l.offset-1 : l.scanIdent()] + lval.token = l.token[1:] + return tokIndex + case isNumber(ch): + i := l.offset - 1 + j := l.scanNumber(numberStateFloat) + if j < 0 { + l.token = l.source[i:-j] + return tokInvalid + } + l.token = l.source[i:j] + lval.token = l.token + return tokNumber + default: + return '.' + } + case '$': + if isIdent(l.peek(), false) { + i := l.offset - 1 + j, isModule := l.scanIdentOrModule() + l.token = l.source[i:j] + lval.token = l.token + if isModule { + return tokModuleVariable + } + return tokVariable + } + case '|': + if l.peek() == '=' { + l.offset++ + l.token = "|=" + lval.operator = OpModify + return tokUpdateOp + } + case '?': + if l.peek() == '/' { + l.offset++ + if l.peek() == '/' { + l.offset++ + l.token = "?//" + return tokDestAltOp + } + l.offset-- + } + case '+': + if l.peek() == '=' { + l.offset++ + l.token = "+=" + lval.operator = OpUpdateAdd + return tokUpdateOp + } + case '-': + if l.peek() == '=' { + l.offset++ + l.token = "-=" + lval.operator = OpUpdateSub + return tokUpdateOp + } + case '*': + if l.peek() == '=' { + l.offset++ + l.token = "*=" + lval.operator = OpUpdateMul + return tokUpdateOp + } + case '/': + switch l.peek() { + case '=': + l.offset++ + l.token = "/=" + lval.operator = OpUpdateDiv + return tokUpdateOp + case '/': + l.offset++ + if l.peek() == '=' { + l.offset++ + l.token = "//=" + lval.operator = OpUpdateAlt + return tokUpdateOp + } + l.token = "//" + lval.operator = OpAlt + return tokAltOp + } + case '%': + if l.peek() == '=' { + l.offset++ + l.token = "%=" + lval.operator = OpUpdateMod + return tokUpdateOp + } + case '=': + if l.peek() == '=' { + l.offset++ + l.token = "==" + lval.operator = OpEq + return tokCompareOp + } + l.token = "=" + lval.operator = OpAssign + return tokUpdateOp + case '!': + if l.peek() == '=' { + l.offset++ + l.token = "!=" + lval.operator = OpNe + return tokCompareOp + } + case '>': + if l.peek() == '=' { + l.offset++ + l.token = ">=" + lval.operator = OpGe + return tokCompareOp + } + l.token = ">" + lval.operator = OpGt + return tokCompareOp + case '<': + if l.peek() == '=' { + l.offset++ + l.token = "<=" + lval.operator = OpLe + return tokCompareOp + } + l.token = "<" + lval.operator = OpLt + return tokCompareOp + case '@': + if isIdent(l.peek(), true) { + l.token = l.source[l.offset-1 : l.scanIdent()] + lval.token = l.token + return tokFormat + } + case '"': + tok, str := l.scanString(l.offset - 1) + lval.token = str + return tok + default: + if ch >= utf8.RuneSelf { + r, size := utf8.DecodeRuneInString(l.source[l.offset-1:]) + l.offset += size + l.token = string(r) + } + } + return int(ch) +} + +func (l *lexer) next() (byte, bool) { + for { + ch := l.source[l.offset] + l.offset++ + if ch == '#' { + if len(l.source) == l.offset { + return 0, true + } + for !isNewLine(l.source[l.offset]) { + l.offset++ + if len(l.source) == l.offset { + return 0, true + } + } + } else if !isWhite(ch) { + return ch, false + } else if len(l.source) == l.offset { + return 0, true + } + } +} + +func (l *lexer) peek() byte { + if len(l.source) == l.offset { + return 0 + } + return l.source[l.offset] +} + +func (l *lexer) scanIdent() int { + for isIdent(l.peek(), true) { + l.offset++ + } + return l.offset +} + +func (l *lexer) scanIdentOrModule() (int, bool) { + index := l.scanIdent() + var isModule bool + if l.peek() == ':' { + l.offset++ + if l.peek() == ':' { + l.offset++ + if isIdent(l.peek(), false) { + l.offset++ + index = l.scanIdent() + isModule = true + } else { + l.offset -= 2 + } + } else { + l.offset-- + } + } + return index, isModule +} + +func (l *lexer) validVarName() bool { + if l.peek() != '$' { + return false + } + l.offset++ + return isIdent(l.peek(), false) && l.scanIdent() == len(l.source) +} + +const ( + numberStateLead = iota + numberStateFloat + numberStateExpLead + numberStateExp +) + +func (l *lexer) scanNumber(state int) int { + for { + switch state { + case numberStateLead, numberStateFloat: + if ch := l.peek(); isNumber(ch) { + l.offset++ + } else { + switch ch { + case '.': + if state != numberStateLead { + l.offset++ + return -l.offset + } + l.offset++ + state = numberStateFloat + case 'e', 'E': + l.offset++ + switch l.peek() { + case '-', '+': + l.offset++ + } + state = numberStateExpLead + default: + if isIdent(ch, false) { + l.offset++ + return -l.offset + } + return l.offset + } + } + case numberStateExpLead, numberStateExp: + if ch := l.peek(); !isNumber(ch) { + if isIdent(ch, false) { + l.offset++ + return -l.offset + } + if state == numberStateExpLead { + return -l.offset + } + return l.offset + } + l.offset++ + state = numberStateExp + default: + panic(state) + } + } +} + +func (l *lexer) validNumber() bool { + ch := l.peek() + switch ch { + case '+', '-': + l.offset++ + ch = l.peek() + } + state := numberStateLead + if ch == '.' { + l.offset++ + ch = l.peek() + state = numberStateFloat + } + return isNumber(ch) && l.scanNumber(state) == len(l.source) +} + +func (l *lexer) scanString(start int) (int, string) { + var decode bool + var controls int + unquote := func(src string, quote bool) (string, error) { + if !decode { + if quote { + return src, nil + } + return src[1 : len(src)-1], nil + } + var buf []byte + if !quote && controls == 0 { + buf = []byte(src) + } else { + buf = quoteAndEscape(src, quote, controls) + } + if err := json.Unmarshal(buf, &src); err != nil { + return "", err + } + return src, nil + } + for i := l.offset; i < len(l.source); i++ { + ch := l.source[i] + switch ch { + case '\\': + if i++; i >= len(l.source) { + break + } + switch l.source[i] { + case 'u': + for j := 1; j <= 4; j++ { + if i+j >= len(l.source) || !isHex(l.source[i+j]) { + l.offset = i + j + l.token = l.source[i-1 : l.offset] + return tokInvalidEscapeSequence, "" + } + } + i += 4 + fallthrough + case '"', '/', '\\', 'b', 'f', 'n', 'r', 't': + decode = true + case '(': + if !l.inString { + l.inString = true + return tokStringStart, "" + } + if i == l.offset+1 { + l.offset += 2 + l.inString = false + return tokStringQuery, "" + } + l.offset = i - 1 + l.token = l.source[start:l.offset] + str, err := unquote(l.token, true) + if err != nil { + return tokInvalid, "" + } + return tokString, str + default: + l.offset = i + 1 + l.token = l.source[l.offset-2 : l.offset] + return tokInvalidEscapeSequence, "" + } + case '"': + if !l.inString { + l.offset = i + 1 + l.token = l.source[start:l.offset] + str, err := unquote(l.token, false) + if err != nil { + return tokInvalid, "" + } + return tokString, str + } + if i > l.offset { + l.offset = i + l.token = l.source[start:l.offset] + str, err := unquote(l.token, true) + if err != nil { + return tokInvalid, "" + } + return tokString, str + } + l.inString = false + l.offset = i + 1 + return tokStringEnd, "" + default: + if !decode { + decode = ch > '~' + } + if ch < ' ' { // ref: unquoteBytes in encoding/json + controls++ + } + } + } + l.offset = len(l.source) + l.token = "" + return tokUnterminatedString, "" +} + +func quoteAndEscape(src string, quote bool, controls int) []byte { + size := len(src) + controls*5 + if quote { + size += 2 + } + buf := make([]byte, size) + var j int + if quote { + buf[0] = '"' + buf[len(buf)-1] = '"' + j++ + } + for i := 0; i < len(src); i++ { + if ch := src[i]; ch < ' ' { + const hex = "0123456789abcdef" + copy(buf[j:], `\u00`) + buf[j+4] = hex[ch>>4] + buf[j+5] = hex[ch&0xF] + j += 6 + } else { + buf[j] = ch + j++ + } + } + return buf +} + +type parseError struct { + offset int + token string + tokenType int +} + +func (err *parseError) Error() string { + switch err.tokenType { + case eof: + return "unexpected EOF" + case tokInvalid: + return "invalid token " + jsonMarshal(err.token) + case tokInvalidEscapeSequence: + return `invalid escape sequence "` + err.token + `" in string literal` + case tokUnterminatedString: + return "unterminated string literal" + default: + return "unexpected token " + jsonMarshal(err.token) + } +} + +func (err *parseError) Token() (string, int) { + return err.token, err.offset +} + +func (l *lexer) Error(string) { + offset, token := l.offset, l.token + if l.tokenType != eof && l.tokenType < utf8.RuneSelf { + token = string(rune(l.tokenType)) + } + l.err = &parseError{offset, token, l.tokenType} +} + +func isWhite(ch byte) bool { + switch ch { + case '\t', '\n', '\r', ' ': + return true + default: + return false + } +} + +func isIdent(ch byte, tail bool) bool { + return 'a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || ch == '_' || + tail && isNumber(ch) +} + +func isHex(ch byte) bool { + return 'a' <= ch && ch <= 'f' || + 'A' <= ch && ch <= 'F' || + isNumber(ch) +} + +func isNumber(ch byte) bool { + return '0' <= ch && ch <= '9' +} + +func isNewLine(ch byte) bool { + switch ch { + case '\n', '\r': + return true + default: + return false + } +} diff --git a/vendor/github.com/itchyny/gojq/math.go b/vendor/github.com/itchyny/gojq/math.go new file mode 100644 index 00000000..c315f72d --- /dev/null +++ b/vendor/github.com/itchyny/gojq/math.go @@ -0,0 +1,8 @@ +package gojq + +import "math/bits" + +const ( + maxInt = 1<<(bits.UintSize-1) - 1 // math.MaxInt64 or math.MaxInt32 + minInt = -maxInt - 1 // math.MinInt64 or math.MinInt32 +) diff --git a/vendor/github.com/itchyny/gojq/module_loader.go b/vendor/github.com/itchyny/gojq/module_loader.go new file mode 100644 index 00000000..7c45904d --- /dev/null +++ b/vendor/github.com/itchyny/gojq/module_loader.go @@ -0,0 +1,190 @@ +package gojq + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "strings" +) + +// ModuleLoader is the interface for loading modules. +// +// Implement following optional methods. Use NewModuleLoader to load local modules. +// +// LoadModule(string) (*Query, error) +// LoadModuleWithMeta(string, map[string]interface{}) (*Query, error) +// LoadInitModules() ([]*Query, error) +// LoadJSON(string) (interface{}, error) +// LoadJSONWithMeta(string, map[string]interface{}) (interface{}, error) +type ModuleLoader interface{} + +// NewModuleLoader creates a new ModuleLoader reading local modules in the paths. +func NewModuleLoader(paths []string) ModuleLoader { + return &moduleLoader{expandHomeDir(paths)} +} + +type moduleLoader struct { + paths []string +} + +func (l *moduleLoader) LoadInitModules() ([]*Query, error) { + var qs []*Query + for _, path := range l.paths { + if filepath.Base(path) != ".jq" { + continue + } + fi, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + continue + } + return nil, err + } + if fi.IsDir() { + continue + } + cnt, err := os.ReadFile(path) + if err != nil { + return nil, err + } + q, err := parseModule(path, string(cnt)) + if err != nil { + return nil, &queryParseError{path, string(cnt), err} + } + qs = append(qs, q) + } + return qs, nil +} + +func (l *moduleLoader) LoadModuleWithMeta(name string, meta map[string]interface{}) (*Query, error) { + path, err := l.lookupModule(name, ".jq", meta) + if err != nil { + return nil, err + } + cnt, err := os.ReadFile(path) + if err != nil { + return nil, err + } + q, err := parseModule(path, string(cnt)) + if err != nil { + return nil, &queryParseError{path, string(cnt), err} + } + return q, nil +} + +func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]interface{}) (interface{}, error) { + path, err := l.lookupModule(name, ".json", meta) + if err != nil { + return nil, err + } + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + var vals []interface{} + dec := json.NewDecoder(f) + dec.UseNumber() + for { + var val interface{} + if err := dec.Decode(&val); err != nil { + if err == io.EOF { + break + } + if _, err := f.Seek(0, io.SeekStart); err != nil { + return nil, err + } + cnt, er := io.ReadAll(f) + if er != nil { + return nil, er + } + return nil, &jsonParseError{path, string(cnt), err} + } + vals = append(vals, val) + } + return vals, nil +} + +func (l *moduleLoader) lookupModule(name, extension string, meta map[string]interface{}) (string, error) { + paths := l.paths + if path := searchPath(meta); path != "" { + paths = append([]string{path}, paths...) + } + for _, base := range paths { + path := filepath.Clean(filepath.Join(base, name+extension)) + if _, err := os.Stat(path); err == nil { + return path, err + } + path = filepath.Clean(filepath.Join(base, name, filepath.Base(name)+extension)) + if _, err := os.Stat(path); err == nil { + return path, err + } + } + return "", fmt.Errorf("module not found: %q", name) +} + +// This is a dirty hack to implement the "search" field. +func parseModule(path, cnt string) (*Query, error) { + q, err := Parse(cnt) + if err != nil { + return nil, err + } + for _, i := range q.Imports { + if i.Meta == nil { + continue + } + i.Meta.KeyVals = append( + i.Meta.KeyVals, + &ConstObjectKeyVal{ + Key: "$$path", + Val: &ConstTerm{Str: path}, + }, + ) + } + return q, nil +} + +func searchPath(meta map[string]interface{}) string { + x, ok := meta["search"] + if !ok { + return "" + } + s, ok := x.(string) + if !ok { + return "" + } + if filepath.IsAbs(s) { + return s + } + if strings.HasPrefix(s, "~") { + if homeDir, err := os.UserHomeDir(); err == nil { + return filepath.Join(homeDir, s[1:]) + } + } + var path string + if x, ok := meta["$$path"]; ok { + path, _ = x.(string) + } + if path == "" { + return s + } + return filepath.Join(filepath.Dir(path), s) +} + +func expandHomeDir(paths []string) []string { + var homeDir string + var err error + for i, path := range paths { + if strings.HasPrefix(path, "~") { + if homeDir == "" && err == nil { + homeDir, err = os.UserHomeDir() + } + if homeDir != "" { + paths[i] = filepath.Join(homeDir, path[1:]) + } + } + } + return paths +} diff --git a/vendor/github.com/itchyny/gojq/normalize.go b/vendor/github.com/itchyny/gojq/normalize.go new file mode 100644 index 00000000..f021245a --- /dev/null +++ b/vendor/github.com/itchyny/gojq/normalize.go @@ -0,0 +1,84 @@ +package gojq + +import ( + "encoding/json" + "math" + "math/big" + "strings" +) + +func normalizeNumber(v json.Number) interface{} { + if i, err := v.Int64(); err == nil && minInt <= i && i <= maxInt { + return int(i) + } + if strings.ContainsAny(v.String(), ".eE") { + if f, err := v.Float64(); err == nil { + return f + } + } + if bi, ok := new(big.Int).SetString(v.String(), 10); ok { + return bi + } + if strings.HasPrefix(v.String(), "-") { + return math.Inf(-1) + } + return math.Inf(1) +} + +func normalizeNumbers(v interface{}) interface{} { + switch v := v.(type) { + case json.Number: + return normalizeNumber(v) + case *big.Int: + if v.IsInt64() { + if i := v.Int64(); minInt <= i && i <= maxInt { + return int(i) + } + } + return v + case int64: + if minInt <= v && v <= maxInt { + return int(v) + } + return big.NewInt(v) + case int32: + return int(v) + case int16: + return int(v) + case int8: + return int(v) + case uint: + if v <= maxInt { + return int(v) + } + return new(big.Int).SetUint64(uint64(v)) + case uint64: + if v <= maxInt { + return int(v) + } + return new(big.Int).SetUint64(v) + case uint32: + if uint64(v) <= maxInt { + return int(v) + } + return new(big.Int).SetUint64(uint64(v)) + case uint16: + return int(v) + case uint8: + return int(v) + case float32: + return float64(v) + case []interface{}: + for i, x := range v { + v[i] = normalizeNumbers(x) + } + return v + case map[string]interface{}: + for k, x := range v { + v[k] = normalizeNumbers(x) + } + return v + default: + return v + } +} diff --git a/vendor/github.com/itchyny/gojq/operator.go b/vendor/github.com/itchyny/gojq/operator.go new file mode 100644 index 00000000..1271a438 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/operator.go @@ -0,0 +1,555 @@ +package gojq + +import ( + "math" + "math/big" + "strings" +) + +// Operator ... +type Operator int + +// Operators ... +const ( + OpPipe Operator = iota + 1 + OpComma + OpAdd + OpSub + OpMul + OpDiv + OpMod + OpEq + OpNe + OpGt + OpLt + OpGe + OpLe + OpAnd + OpOr + OpAlt + OpAssign + OpModify + OpUpdateAdd + OpUpdateSub + OpUpdateMul + OpUpdateDiv + OpUpdateMod + OpUpdateAlt +) + +// String implements Stringer. +func (op Operator) String() string { + switch op { + case OpPipe: + return "|" + case OpComma: + return "," + case OpAdd: + return "+" + case OpSub: + return "-" + case OpMul: + return "*" + case OpDiv: + return "/" + case OpMod: + return "%" + case OpEq: + return "==" + case OpNe: + return "!=" + case OpGt: + return ">" + case OpLt: + return "<" + case OpGe: + return ">=" + case OpLe: + return "<=" + case OpAnd: + return "and" + case OpOr: + return "or" + case OpAlt: + return "//" + case OpAssign: + return "=" + case OpModify: + return "|=" + case OpUpdateAdd: + return "+=" + case OpUpdateSub: + return "-=" + case OpUpdateMul: + return "*=" + case OpUpdateDiv: + return "/=" + case OpUpdateMod: + return "%=" + case OpUpdateAlt: + return "//=" + default: + panic(op) + } +} + +// GoString implements GoStringer. +func (op Operator) GoString() (str string) { + defer func() { str = "gojq." + str }() + switch op { + case Operator(0): + return "Operator(0)" + case OpPipe: + return "OpPipe" + case OpComma: + return "OpComma" + case OpAdd: + return "OpAdd" + case OpSub: + return "OpSub" + case OpMul: + return "OpMul" + case OpDiv: + return "OpDiv" + case OpMod: + return "OpMod" + case OpEq: + return "OpEq" + case OpNe: + return "OpNe" + case OpGt: + return "OpGt" + case OpLt: + return "OpLt" + case OpGe: + return "OpGe" + case OpLe: + return "OpLe" + case OpAnd: + return "OpAnd" + case OpOr: + return "OpOr" + case OpAlt: + return "OpAlt" + case OpAssign: + return "OpAssign" + case OpModify: + return "OpModify" + case OpUpdateAdd: + return "OpUpdateAdd" + case OpUpdateSub: + return "OpUpdateSub" + case OpUpdateMul: + return "OpUpdateMul" + case OpUpdateDiv: + return "OpUpdateDiv" + case OpUpdateMod: + return "OpUpdateMod" + case OpUpdateAlt: + return "OpUpdateAlt" + default: + panic(op) + } +} + +func (op Operator) getFunc() string { + switch op { + case OpPipe: + panic("unreachable") + case OpComma: + panic("unreachable") + case OpAdd: + return "_add" + case OpSub: + return "_subtract" + case OpMul: + return "_multiply" + case OpDiv: + return "_divide" + case OpMod: + return "_modulo" + case OpEq: + return "_equal" + case OpNe: + return "_notequal" + case OpGt: + return "_greater" + case OpLt: + return "_less" + case OpGe: + return "_greatereq" + case OpLe: + return "_lesseq" + case OpAnd: + panic("unreachable") + case OpOr: + panic("unreachable") + case OpAlt: + panic("unreachable") + case OpAssign: + return "_assign" + case OpModify: + return "_modify" + case OpUpdateAdd: + return "_add" + case OpUpdateSub: + return "_subtract" + case OpUpdateMul: + return "_multiply" + case OpUpdateDiv: + return "_divide" + case OpUpdateMod: + return "_modulo" + case OpUpdateAlt: + return "_alternative" + default: + panic(op) + } +} + +func binopTypeSwitch( + l, r interface{}, + callbackInts func(_, _ int) interface{}, + callbackFloats func(_, _ float64) interface{}, + callbackBigInts func(_, _ *big.Int) interface{}, + callbackStrings func(_, _ string) interface{}, + callbackArrays func(_, _ []interface{}) interface{}, + callbackMaps func(_, _ map[string]interface{}) interface{}, + fallback func(_, _ interface{}) interface{}) interface{} { + switch l := l.(type) { + case int: + switch r := r.(type) { + case int: + return callbackInts(l, r) + case float64: + return callbackFloats(float64(l), r) + case *big.Int: + return callbackBigInts(big.NewInt(int64(l)), r) + default: + return fallback(l, r) + } + case float64: + switch r := r.(type) { + case int: + return callbackFloats(l, float64(r)) + case float64: + return callbackFloats(l, r) + case *big.Int: + return callbackFloats(l, bigToFloat(r)) + default: + return fallback(l, r) + } + case *big.Int: + switch r := r.(type) { + case int: + return callbackBigInts(l, big.NewInt(int64(r))) + case float64: + return callbackFloats(bigToFloat(l), r) + case *big.Int: + return callbackBigInts(l, r) + default: + return fallback(l, r) + } + case string: + switch r := r.(type) { + case string: + return callbackStrings(l, r) + default: + return fallback(l, r) + } + case []interface{}: + switch r := r.(type) { + case []interface{}: + return callbackArrays(l, r) + default: + return fallback(l, r) + } + case map[string]interface{}: + switch r := r.(type) { + case map[string]interface{}: + return callbackMaps(l, r) + default: + return fallback(l, r) + } + default: + return fallback(l, r) + } +} + +func funcOpPlus(v interface{}) interface{} { + switch v := v.(type) { + case int: + return v + case float64: + return v + case *big.Int: + return v + default: + return &unaryTypeError{"plus", v} + } +} + +func funcOpNegate(v interface{}) interface{} { + switch v := v.(type) { + case int: + return -v + case float64: + return -v + case *big.Int: + return new(big.Int).Neg(v) + default: + return &unaryTypeError{"negate", v} + } +} + +func funcOpAdd(_, l, r interface{}) interface{} { + return binopTypeSwitch(l, r, + func(l, r int) interface{} { + if v := l + r; (v >= l) == (r >= 0) { + return v + } + x, y := big.NewInt(int64(l)), big.NewInt(int64(r)) + return x.Add(x, y) + }, + func(l, r float64) interface{} { return l + r }, + func(l, r *big.Int) interface{} { return new(big.Int).Add(l, r) }, + func(l, r string) interface{} { return l + r }, + func(l, r []interface{}) interface{} { + if len(l) == 0 { + return r + } + if len(r) == 0 { + return l + } + v := make([]interface{}, len(l)+len(r)) + copy(v, l) + copy(v[len(l):], r) + return v + }, + func(l, r map[string]interface{}) interface{} { + if len(l) == 0 { + return r + } + if len(r) == 0 { + return l + } + m := make(map[string]interface{}, len(l)+len(r)) + for k, v := range l { + m[k] = v + } + for k, v := range r { + m[k] = v + } + return m + }, + func(l, r interface{}) interface{} { + if l == nil { + return r + } + if r == nil { + return l + } + return &binopTypeError{"add", l, r} + }, + ) +} + +func funcOpSub(_, l, r interface{}) interface{} { + return binopTypeSwitch(l, r, + func(l, r int) interface{} { + if v := l - r; (v <= l) == (r >= 0) { + return v + } + x, y := big.NewInt(int64(l)), big.NewInt(int64(r)) + return x.Sub(x, y) + }, + func(l, r float64) interface{} { return l - r }, + func(l, r *big.Int) interface{} { return new(big.Int).Sub(l, r) }, + func(l, r string) interface{} { return &binopTypeError{"subtract", l, r} }, + func(l, r []interface{}) interface{} { + v := make([]interface{}, 0, len(l)) + L: + for _, l := range l { + for _, r := range r { + if compare(l, r) == 0 { + continue L + } + } + v = append(v, l) + } + return v + }, + func(l, r map[string]interface{}) interface{} { return &binopTypeError{"subtract", l, r} }, + func(l, r interface{}) interface{} { return &binopTypeError{"subtract", l, r} }, + ) +} + +func funcOpMul(_, l, r interface{}) interface{} { + return binopTypeSwitch(l, r, + func(l, r int) interface{} { + if v := l * r; r == 0 || v/r == l { + return v + } + x, y := big.NewInt(int64(l)), big.NewInt(int64(r)) + return x.Mul(x, y) + }, + func(l, r float64) interface{} { return l * r }, + func(l, r *big.Int) interface{} { return new(big.Int).Mul(l, r) }, + func(l, r string) interface{} { return &binopTypeError{"multiply", l, r} }, + func(l, r []interface{}) interface{} { return &binopTypeError{"multiply", l, r} }, + deepMergeObjects, + func(l, r interface{}) interface{} { + if l, ok := l.(string); ok { + if r, ok := toFloat(r); ok { + return repeatString(l, r) + } + } + if r, ok := r.(string); ok { + if l, ok := toFloat(l); ok { + return repeatString(r, l) + } + } + return &binopTypeError{"multiply", l, r} + }, + ) +} + +func deepMergeObjects(l, r map[string]interface{}) interface{} { + m := make(map[string]interface{}, len(l)+len(r)) + for k, v := range l { + m[k] = v + } + for k, v := range r { + if mk, ok := m[k]; ok { + if mk, ok := mk.(map[string]interface{}); ok { + if w, ok := v.(map[string]interface{}); ok { + v = deepMergeObjects(mk, w) + } + } + } + m[k] = v + } + return m +} + +func repeatString(s string, n float64) interface{} { + if n <= 0.0 || len(s) > 0 && n > float64(0x10000000/len(s)) || math.IsNaN(n) { + return nil + } + if n < 1.0 { + return s + } + return strings.Repeat(s, int(n)) +} + +func funcOpDiv(_, l, r interface{}) interface{} { + return binopTypeSwitch(l, r, + func(l, r int) interface{} { + if r == 0 { + if l == 0 { + return math.NaN() + } + return &zeroDivisionError{l, r} + } + if l%r == 0 { + return l / r + } + return float64(l) / float64(r) + }, + func(l, r float64) interface{} { + if r == 0.0 { + if l == 0.0 { + return math.NaN() + } + return &zeroDivisionError{l, r} + } + return l / r + }, + func(l, r *big.Int) interface{} { + if r.Sign() == 0 { + if l.Sign() == 0 { + return math.NaN() + } + return &zeroDivisionError{l, r} + } + d, m := new(big.Int).DivMod(l, r, new(big.Int)) + if m.Sign() == 0 { + return d + } + return bigToFloat(l) / bigToFloat(r) + }, + func(l, r string) interface{} { + if l == "" { + return []interface{}{} + } + xs := strings.Split(l, r) + vs := make([]interface{}, len(xs)) + for i, x := range xs { + vs[i] = x + } + return vs + }, + func(l, r []interface{}) interface{} { return &binopTypeError{"divide", l, r} }, + func(l, r map[string]interface{}) interface{} { return &binopTypeError{"divide", l, r} }, + func(l, r interface{}) interface{} { return &binopTypeError{"divide", l, r} }, + ) +} + +func funcOpMod(_, l, r interface{}) interface{} { + return binopTypeSwitch(l, r, + func(l, r int) interface{} { + if r == 0 { + return &zeroModuloError{l, r} + } + return l % r + }, + func(l, r float64) interface{} { + ri := floatToInt(r) + if ri == 0 { + return &zeroModuloError{l, r} + } + return floatToInt(l) % ri + }, + func(l, r *big.Int) interface{} { + if r.Sign() == 0 { + return &zeroModuloError{l, r} + } + return new(big.Int).Rem(l, r) + }, + func(l, r string) interface{} { return &binopTypeError{"modulo", l, r} }, + func(l, r []interface{}) interface{} { return &binopTypeError{"modulo", l, r} }, + func(l, r map[string]interface{}) interface{} { return &binopTypeError{"modulo", l, r} }, + func(l, r interface{}) interface{} { return &binopTypeError{"modulo", l, r} }, + ) +} + +func funcOpAlt(_, l, r interface{}) interface{} { + if l == nil || l == false { + return r + } + return l +} + +func funcOpEq(_, l, r interface{}) interface{} { + return compare(l, r) == 0 +} + +func funcOpNe(_, l, r interface{}) interface{} { + return compare(l, r) != 0 +} + +func funcOpGt(_, l, r interface{}) interface{} { + return compare(l, r) > 0 +} + +func funcOpLt(_, l, r interface{}) interface{} { + return compare(l, r) < 0 +} + +func funcOpGe(_, l, r interface{}) interface{} { + return compare(l, r) >= 0 +} + +func funcOpLe(_, l, r interface{}) interface{} { + return compare(l, r) <= 0 +} diff --git a/vendor/github.com/itchyny/gojq/option.go b/vendor/github.com/itchyny/gojq/option.go new file mode 100644 index 00000000..5eb771cc --- /dev/null +++ b/vendor/github.com/itchyny/gojq/option.go @@ -0,0 +1,99 @@ +package gojq + +import "fmt" + +// CompilerOption is a compiler option. +type CompilerOption func(*compiler) + +// WithModuleLoader is a compiler option for module loader. +// If you want to load modules from the filesystem, use NewModuleLoader. +func WithModuleLoader(moduleLoader ModuleLoader) CompilerOption { + return func(c *compiler) { + c.moduleLoader = moduleLoader + } +} + +// WithEnvironLoader is a compiler option for environment variables loader. +// The OS environment variables are not accessible by default due to security +// reason. You can pass os.Environ if you allow to access it. +func WithEnvironLoader(environLoader func() []string) CompilerOption { + return func(c *compiler) { + c.environLoader = environLoader + } +} + +// WithVariables is a compiler option for variable names. The variables can be +// used in the query. You have to give the values to code.Run in the same order. +func WithVariables(variables []string) CompilerOption { + return func(c *compiler) { + c.variables = variables + } +} + +// WithFunction is a compiler option for adding a custom internal function. +// Specify the minimum and maximum count of the function arguments. These +// values should satisfy 0 <= minarity <= maxarity <= 30, otherwise panics. +// On handling numbers, you should take account to int, float64 and *big.Int. +// These are the number types you are allowed to return, so do not return int64. +// Refer to ValueError to return a value error just like built-in error function. +// If you want to emit multiple values, call the empty function, accept a filter +// for its argument, or call another built-in function, then use LoadInitModules +// of the module loader. +func WithFunction(name string, minarity, maxarity int, + f func(interface{}, []interface{}) interface{}) CompilerOption { + return withFunction(name, minarity, maxarity, false, f) +} + +// WithIterFunction is a compiler option for adding a custom iterator function. +// This is like the WithFunction option, but you can add a function which +// returns an Iter to emit multiple values. You cannot define both iterator and +// non-iterator functions of the same name (with possibly different arities). +// See also NewIter, which can be used to convert values or an error to an Iter. +func WithIterFunction(name string, minarity, maxarity int, + f func(interface{}, []interface{}) Iter) CompilerOption { + return withFunction(name, minarity, maxarity, true, + func(v interface{}, args []interface{}) interface{} { + return f(v, args) + }, + ) +} + +func withFunction(name string, minarity, maxarity int, iter bool, + f func(interface{}, []interface{}) interface{}) CompilerOption { + if !(0 <= minarity && minarity <= maxarity && maxarity <= 30) { + panic(fmt.Sprintf("invalid arity for %q: %d, %d", name, minarity, maxarity)) + } + argcount := 1<<(maxarity+1) - 1< 0 { + return nil, l.err + } + return l.result, nil +} + +func reverseFuncDef(xs []*FuncDef) []*FuncDef { + for i, j := 0, len(xs)-1; i < j; i, j = i+1, j-1 { + xs[i], xs[j] = xs[j], xs[i] + } + return xs +} + +func prependFuncDef(xs []*FuncDef, x *FuncDef) []*FuncDef { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} + +//line parser.go.y:33 +type yySymType struct { + yys int + value interface{} + token string + operator Operator +} + +const tokAltOp = 57346 +const tokUpdateOp = 57347 +const tokDestAltOp = 57348 +const tokOrOp = 57349 +const tokAndOp = 57350 +const tokCompareOp = 57351 +const tokModule = 57352 +const tokImport = 57353 +const tokInclude = 57354 +const tokDef = 57355 +const tokAs = 57356 +const tokLabel = 57357 +const tokBreak = 57358 +const tokNull = 57359 +const tokTrue = 57360 +const tokFalse = 57361 +const tokIdent = 57362 +const tokVariable = 57363 +const tokModuleIdent = 57364 +const tokModuleVariable = 57365 +const tokIndex = 57366 +const tokNumber = 57367 +const tokFormat = 57368 +const tokString = 57369 +const tokStringStart = 57370 +const tokStringQuery = 57371 +const tokStringEnd = 57372 +const tokIf = 57373 +const tokThen = 57374 +const tokElif = 57375 +const tokElse = 57376 +const tokEnd = 57377 +const tokTry = 57378 +const tokCatch = 57379 +const tokReduce = 57380 +const tokForeach = 57381 +const tokRecurse = 57382 +const tokFuncDefPost = 57383 +const tokTermPost = 57384 +const tokEmptyCatch = 57385 +const tokInvalid = 57386 +const tokInvalidEscapeSequence = 57387 +const tokUnterminatedString = 57388 + +var yyToknames = [...]string{ + "$end", + "error", + "$unk", + "tokAltOp", + "tokUpdateOp", + "tokDestAltOp", + "tokOrOp", + "tokAndOp", + "tokCompareOp", + "tokModule", + "tokImport", + "tokInclude", + "tokDef", + "tokAs", + "tokLabel", + "tokBreak", + "tokNull", + "tokTrue", + "tokFalse", + "tokIdent", + "tokVariable", + "tokModuleIdent", + "tokModuleVariable", + "tokIndex", + "tokNumber", + "tokFormat", + "tokString", + "tokStringStart", + "tokStringQuery", + "tokStringEnd", + "tokIf", + "tokThen", + "tokElif", + "tokElse", + "tokEnd", + "tokTry", + "tokCatch", + "tokReduce", + "tokForeach", + "tokRecurse", + "tokFuncDefPost", + "tokTermPost", + "tokEmptyCatch", + "tokInvalid", + "tokInvalidEscapeSequence", + "tokUnterminatedString", + "'|'", + "','", + "'+'", + "'-'", + "'*'", + "'/'", + "'%'", + "'.'", + "'?'", + "'['", + "';'", + "':'", + "'('", + "')'", + "']'", + "'{'", + "'}'", +} + +var yyStatenames = [...]string{} + +const yyEofCode = 1 +const yyErrCode = 2 +const yyInitialStackSize = 16 + +//line parser.go.y:693 + +//line yacctab:1 +var yyExca = [...]int{ + -1, 1, + 1, -1, + -2, 0, + -1, 97, + 55, 0, + -2, 104, + -1, 130, + 5, 0, + -2, 32, + -1, 133, + 9, 0, + -2, 35, + -1, 194, + 58, 114, + -2, 54, +} + +const yyPrivate = 57344 + +const yyLast = 1127 + +var yyAct = [...]int{ + 86, 214, 174, 112, 12, 203, 9, 175, 111, 31, + 190, 6, 156, 140, 117, 47, 95, 97, 93, 94, + 89, 141, 49, 7, 179, 180, 181, 240, 246, 264, + 239, 103, 177, 106, 178, 227, 164, 119, 107, 108, + 105, 245, 102, 75, 76, 113, 77, 78, 79, 123, + 226, 163, 211, 225, 259, 210, 142, 179, 180, 181, + 158, 159, 143, 182, 122, 177, 224, 178, 219, 7, + 235, 234, 104, 127, 243, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 72, 74, 80, 81, + 82, 83, 84, 147, 73, 88, 182, 196, 73, 229, + 195, 145, 7, 150, 228, 161, 166, 165, 157, 126, + 125, 124, 144, 88, 258, 167, 80, 81, 82, 83, + 84, 206, 73, 44, 242, 91, 90, 92, 183, 184, + 82, 83, 84, 154, 73, 153, 267, 186, 49, 173, + 42, 43, 100, 91, 90, 92, 99, 191, 120, 197, + 256, 257, 200, 192, 201, 202, 188, 75, 76, 207, + 77, 78, 79, 198, 199, 209, 42, 43, 216, 92, + 215, 215, 218, 213, 113, 98, 75, 76, 185, 77, + 78, 79, 204, 205, 101, 221, 222, 170, 155, 171, + 169, 3, 28, 27, 230, 96, 220, 232, 176, 46, + 223, 11, 80, 81, 82, 83, 84, 11, 73, 78, + 79, 157, 241, 110, 8, 152, 237, 255, 236, 72, + 74, 80, 81, 82, 83, 84, 85, 73, 79, 278, + 160, 191, 277, 121, 189, 253, 254, 192, 248, 247, + 187, 139, 249, 250, 208, 262, 260, 261, 215, 263, + 80, 81, 82, 83, 84, 149, 73, 268, 269, 10, + 270, 5, 4, 2, 1, 88, 272, 273, 80, 81, + 82, 83, 84, 0, 73, 279, 0, 0, 271, 280, + 51, 52, 0, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 115, 116, 91, 90, 92, 0, 0, + 42, 43, 0, 87, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 88, 0, 20, 0, 17, 37, 24, + 25, 26, 38, 40, 39, 41, 23, 29, 30, 42, + 43, 0, 114, 15, 0, 0, 212, 0, 16, 0, + 13, 14, 22, 91, 90, 92, 0, 0, 0, 0, + 0, 33, 34, 0, 0, 0, 21, 0, 36, 0, + 148, 32, 0, 146, 35, 51, 52, 0, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 115, 116, + 0, 0, 0, 0, 0, 42, 43, 0, 0, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 18, 19, + 20, 0, 17, 37, 24, 25, 26, 38, 40, 39, + 41, 23, 29, 30, 42, 43, 0, 114, 15, 0, + 0, 109, 0, 16, 0, 13, 14, 22, 0, 0, + 0, 0, 0, 0, 0, 0, 33, 34, 0, 0, + 0, 21, 0, 36, 0, 0, 32, 0, 20, 35, + 17, 37, 24, 25, 26, 38, 40, 39, 41, 23, + 29, 30, 42, 43, 0, 0, 15, 0, 0, 0, + 0, 16, 0, 13, 14, 22, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 34, 0, 0, 0, 21, + 0, 36, 0, 0, 32, 0, 231, 35, 20, 0, + 17, 37, 24, 25, 26, 38, 40, 39, 41, 23, + 29, 30, 42, 43, 0, 0, 15, 0, 0, 0, + 0, 16, 0, 13, 14, 22, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 34, 0, 0, 0, 21, + 0, 36, 0, 0, 32, 0, 118, 35, 20, 0, + 17, 37, 24, 25, 26, 38, 40, 39, 41, 23, + 29, 30, 42, 43, 0, 0, 15, 0, 77, 78, + 79, 16, 0, 13, 14, 22, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 34, 0, 0, 0, 21, + 0, 36, 0, 0, 32, 51, 52, 35, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 48, 0, + 80, 81, 82, 83, 84, 50, 73, 0, 0, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 51, 52, + 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 48, 0, 0, 0, 0, 0, 0, 50, 0, + 0, 172, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 51, 52, 0, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 115, 194, 0, 0, 0, 0, + 0, 42, 43, 0, 45, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 37, 24, 25, 26, 38, 40, + 39, 41, 23, 29, 30, 42, 43, 75, 76, 0, + 77, 78, 79, 193, 0, 0, 0, 0, 22, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 34, 0, + 0, 0, 21, 0, 36, 0, 0, 32, 75, 76, + 35, 77, 78, 79, 0, 0, 0, 0, 0, 0, + 72, 74, 80, 81, 82, 83, 84, 0, 73, 0, + 0, 0, 75, 76, 252, 77, 78, 79, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 72, 74, 80, 81, 82, 83, 84, 0, 73, + 0, 0, 0, 75, 76, 233, 77, 78, 79, 0, + 0, 0, 0, 0, 0, 72, 74, 80, 81, 82, + 83, 84, 0, 73, 0, 0, 0, 75, 76, 168, + 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 72, 74, 80, 81, + 82, 83, 84, 0, 73, 0, 0, 75, 76, 281, + 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, + 72, 74, 80, 81, 82, 83, 84, 0, 73, 0, + 0, 75, 76, 276, 77, 78, 79, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 74, 80, 81, 82, 83, 84, 0, 73, 0, + 0, 75, 76, 251, 77, 78, 79, 0, 0, 0, + 0, 0, 0, 0, 72, 74, 80, 81, 82, 83, + 84, 0, 73, 0, 0, 75, 76, 244, 77, 78, + 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 74, 80, 81, 82, 83, + 84, 0, 73, 0, 0, 75, 76, 217, 77, 78, + 79, 0, 0, 0, 0, 0, 0, 0, 72, 74, + 80, 81, 82, 83, 84, 0, 73, 0, 0, 75, + 76, 162, 77, 78, 79, 0, 0, 0, 0, 0, + 75, 76, 0, 77, 78, 79, 0, 0, 72, 74, + 80, 81, 82, 83, 84, 0, 73, 0, 275, 75, + 76, 0, 77, 78, 79, 0, 0, 0, 0, 0, + 0, 0, 72, 74, 80, 81, 82, 83, 84, 0, + 73, 0, 266, 72, 74, 80, 81, 82, 83, 84, + 0, 73, 0, 265, 75, 76, 0, 77, 78, 79, + 0, 0, 72, 74, 80, 81, 82, 83, 84, 0, + 73, 0, 238, 0, 0, 0, 75, 76, 0, 77, + 78, 79, 274, 0, 0, 75, 76, 0, 77, 78, + 79, 0, 0, 0, 0, 0, 0, 72, 74, 80, + 81, 82, 83, 84, 151, 73, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 74, 80, 81, 82, 83, 84, 0, 73, 72, 74, + 80, 81, 82, 83, 84, 0, 73, +} + +var yyPact = [...]int{ + 181, -1000, -1000, -39, -1000, 387, 66, 621, -1000, 1071, + -1000, 535, 289, 678, 678, 535, 535, 154, 119, 115, + 164, 113, -1000, -1000, -1000, -1000, -1000, 13, -1000, -1000, + 139, -1000, 535, 678, 678, 358, 485, 127, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 1, -1000, 53, 52, + 51, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 535, -1000, 535, 535, 535, 535, 535, 535, + 535, 535, 535, 535, 535, -1000, 1071, 0, -1000, -1000, + -1000, 113, 302, 241, 89, 1062, 535, 98, 86, 174, + -39, 2, -1000, -1000, 535, -1000, 921, 71, 71, -1000, + -12, -1000, 49, 48, 535, -1000, -1000, -1000, -1000, 758, + -1000, 160, -1000, 588, 40, 40, 40, 1071, 153, 153, + 561, 201, 219, 67, 79, 79, 43, 43, 43, 131, + -1000, -1000, 0, 654, -1000, -1000, -1000, 39, 535, 0, + 0, 535, -1000, 535, 535, 162, 64, -1000, 535, 162, + -5, 1071, -1000, -1000, 273, 678, 678, 897, -1000, -1000, + -1000, 535, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 7, -1000, -1000, 535, 0, 5, -1000, -13, + -1000, 46, 41, 535, -1000, -1000, 435, 734, 12, 11, + 1071, -1000, 1071, -39, -1000, -1000, -1000, 1005, -30, -1000, + -1000, 535, -1000, -1000, 77, 71, 77, 16, 867, -1000, + -20, -1000, 1071, -1000, -1000, 0, -1000, 654, 0, 0, + 843, -1000, 703, -1000, 535, 535, 117, 57, -1000, -4, + 162, 1071, 678, 678, -1000, -1000, 40, -1000, -1000, -1000, + -1000, -29, -1000, 986, 975, 101, 535, 535, -1000, 535, + -1000, 71, 77, -1000, 0, 535, 535, -1000, 1040, 1071, + 951, -1000, 813, 172, 535, -1000, -1000, -1000, 535, 1071, + 789, -1000, +} + +var yyPgo = [...]int{ + 0, 264, 263, 262, 261, 259, 12, 214, 195, 244, + 0, 241, 13, 240, 234, 10, 4, 9, 233, 20, + 230, 218, 217, 215, 213, 8, 1, 2, 7, 199, + 15, 198, 196, 5, 193, 192, 14, 3, +} + +var yyR1 = [...]int{ + 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, + 6, 6, 7, 7, 8, 8, 9, 9, 33, 33, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, + 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 17, 17, 18, 18, 18, 34, + 34, 35, 35, 19, 19, 19, 19, 19, 20, 20, + 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, + 25, 25, 25, 37, 37, 37, 26, 26, 27, 27, + 27, 27, 27, 27, 27, 28, 28, 28, 29, 29, + 30, 30, 30, 31, 31, 32, 32, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, +} + +var yyR2 = [...]int{ + 0, 2, 0, 3, 2, 2, 0, 2, 6, 4, + 0, 1, 0, 2, 5, 8, 1, 3, 1, 1, + 2, 3, 5, 9, 9, 11, 7, 3, 4, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 1, 3, 1, 3, 3, 1, 3, 1, + 3, 3, 3, 5, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 1, 4, 1, 1, 1, 2, 1, + 3, 2, 2, 2, 3, 4, 2, 3, 2, 2, + 2, 2, 3, 3, 1, 3, 0, 2, 4, 1, + 1, 1, 1, 2, 3, 4, 4, 5, 1, 3, + 0, 5, 0, 2, 0, 2, 1, 3, 3, 3, + 5, 1, 1, 1, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 2, 3, 4, 1, 3, + 3, 3, 3, 2, 3, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +} + +var yyChk = [...]int{ + -1000, -1, -2, 10, -3, -4, -28, 62, -7, -10, + -5, -8, -16, 38, 39, 31, 36, 15, 11, 12, + 13, 54, 40, 24, 17, 18, 19, -34, -35, 25, + 26, -17, 59, 49, 50, 62, 56, 16, 20, 22, + 21, 23, 27, 28, 57, 63, -29, -30, 20, -36, + 27, 7, 8, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 47, 55, 48, 4, 5, 7, 8, 9, + 49, 50, 51, 52, 53, -7, -10, 14, 24, -19, + 55, 54, 56, -16, -16, -10, -8, -10, 21, 27, + 27, 20, -19, -17, 59, -17, -10, -16, -16, 63, + -24, -25, -37, -17, 59, 20, 21, -36, 61, -10, + 21, -18, 63, 48, 58, 58, 58, -10, -10, -10, + -10, -10, -10, -10, -10, -10, -10, -10, -10, -11, + -12, 21, 56, 62, -19, -17, 61, -10, 58, 14, + 14, 32, -23, 37, 47, 14, -6, -28, 58, 59, + -20, -10, 60, 63, 48, 58, 58, -10, 61, 30, + 27, 29, 63, -30, -27, -28, -31, 25, 27, 17, + 18, 19, 56, -27, -27, 47, 6, -13, -12, -14, + -15, -37, -17, 59, 21, 61, 58, -10, -12, -12, + -10, -10, -10, -33, 20, 21, 57, -10, -9, -33, + 60, 57, 63, -25, -26, -16, -26, 60, -10, 61, + -32, -27, -10, -12, 61, 48, 63, 48, 58, 58, + -10, 61, -10, 61, 59, 59, -21, -6, 57, 60, + 57, -10, 47, 58, 60, 61, 48, -12, -15, -12, + -12, 60, 61, -10, -10, -22, 33, 34, 57, 58, + -33, -16, -26, -27, 58, 57, 57, 35, -10, -10, + -10, -12, -10, -10, 32, 57, 60, 60, 57, -10, + -10, 60, +} + +var yyDef = [...]int{ + 2, -2, 6, 0, 1, 12, 0, 0, 4, 5, + 7, 12, 41, 0, 0, 0, 0, 0, 0, 0, + 0, 55, 56, 57, 60, 61, 62, 63, 65, 66, + 67, 69, 0, 0, 0, 0, 0, 0, 89, 90, + 91, 92, 84, 86, 3, 125, 0, 128, 0, 0, + 0, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 0, 29, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 20, 0, 79, 80, + 81, 0, 0, 0, 0, 0, 0, -2, 0, 0, + 10, 0, 58, 59, 0, 68, 0, 71, 72, 73, + 0, 106, 111, 112, 0, 113, 114, 115, 76, 0, + 78, 0, 126, 0, 0, 0, 0, 21, 30, 31, + -2, 33, 34, -2, 36, 37, 38, 39, 40, 0, + 42, 44, 0, 0, 82, 83, 93, 0, 0, 0, + 0, 0, 27, 0, 0, 0, 0, 11, 0, 0, + 0, 98, 70, 74, 0, 0, 0, 0, 77, 85, + 87, 0, 127, 129, 130, 118, 119, 120, 121, 122, + 123, 124, 0, 131, 132, 0, 0, 0, 47, 0, + 49, 0, 0, 0, -2, 94, 0, 0, 0, 0, + 100, 105, 28, 10, 18, 19, 9, 0, 0, 16, + 64, 0, 75, 107, 108, 116, 109, 0, 0, 133, + 0, 135, 22, 43, 45, 0, 46, 0, 0, 0, + 0, 95, 0, 96, 0, 0, 102, 0, 14, 0, + 0, 99, 0, 0, 88, 134, 0, 48, 50, 51, + 52, 0, 97, 0, 0, 0, 0, 0, 8, 0, + 17, 117, 110, 136, 0, 0, 0, 26, 0, 103, + 0, 53, 0, 0, 0, 15, 23, 24, 0, 101, + 0, 25, +} + +var yyTok1 = [...]int{ + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 53, 3, 3, + 59, 60, 51, 49, 48, 50, 54, 52, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 58, 57, + 3, 3, 3, 55, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 56, 3, 61, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 62, 47, 63, +} + +var yyTok2 = [...]int{ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, +} + +var yyTok3 = [...]int{ + 0, +} + +var yyErrorMessages = [...]struct { + state int + token int + msg string +}{} + +//line yaccpar:1 + +/* parser for yacc output */ + +var ( + yyDebug = 0 + yyErrorVerbose = false +) + +type yyLexer interface { + Lex(lval *yySymType) int + Error(s string) +} + +type yyParser interface { + Parse(yyLexer) int + Lookahead() int +} + +type yyParserImpl struct { + lval yySymType + stack [yyInitialStackSize]yySymType + char int +} + +func (p *yyParserImpl) Lookahead() int { + return p.char +} + +func yyNewParser() yyParser { + return &yyParserImpl{} +} + +const yyFlag = -1000 + +func yyTokname(c int) string { + if c >= 1 && c-1 < len(yyToknames) { + if yyToknames[c-1] != "" { + return yyToknames[c-1] + } + } + return __yyfmt__.Sprintf("tok-%v", c) +} + +func yyStatname(s int) string { + if s >= 0 && s < len(yyStatenames) { + if yyStatenames[s] != "" { + return yyStatenames[s] + } + } + return __yyfmt__.Sprintf("state-%v", s) +} + +func yyErrorMessage(state, lookAhead int) string { + const TOKSTART = 4 + + if !yyErrorVerbose { + return "syntax error" + } + + for _, e := range yyErrorMessages { + if e.state == state && e.token == lookAhead { + return "syntax error: " + e.msg + } + } + + res := "syntax error: unexpected " + yyTokname(lookAhead) + + // To match Bison, suggest at most four expected tokens. + expected := make([]int, 0, 4) + + // Look for shiftable tokens. + base := yyPact[state] + for tok := TOKSTART; tok-1 < len(yyToknames); tok++ { + if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok { + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + } + + if yyDef[state] == -2 { + i := 0 + for yyExca[i] != -1 || yyExca[i+1] != state { + i += 2 + } + + // Look for tokens that we accept or reduce. + for i += 2; yyExca[i] >= 0; i += 2 { + tok := yyExca[i] + if tok < TOKSTART || yyExca[i+1] == 0 { + continue + } + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + + // If the default action is to accept or reduce, give up. + if yyExca[i+1] != 0 { + return res + } + } + + for i, tok := range expected { + if i == 0 { + res += ", expecting " + } else { + res += " or " + } + res += yyTokname(tok) + } + return res +} + +func yylex1(lex yyLexer, lval *yySymType) (char, token int) { + token = 0 + char = lex.Lex(lval) + if char <= 0 { + token = yyTok1[0] + goto out + } + if char < len(yyTok1) { + token = yyTok1[char] + goto out + } + if char >= yyPrivate { + if char < yyPrivate+len(yyTok2) { + token = yyTok2[char-yyPrivate] + goto out + } + } + for i := 0; i < len(yyTok3); i += 2 { + token = yyTok3[i+0] + if token == char { + token = yyTok3[i+1] + goto out + } + } + +out: + if token == 0 { + token = yyTok2[1] /* unknown char */ + } + if yyDebug >= 3 { + __yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char)) + } + return char, token +} + +func yyParse(yylex yyLexer) int { + return yyNewParser().Parse(yylex) +} + +func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int { + var yyn int + var yyVAL yySymType + var yyDollar []yySymType + _ = yyDollar // silence set and not used + yyS := yyrcvr.stack[:] + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + yystate := 0 + yyrcvr.char = -1 + yytoken := -1 // yyrcvr.char translated into internal numbering + defer func() { + // Make sure we report no lookahead when not parsing. + yystate = -1 + yyrcvr.char = -1 + yytoken = -1 + }() + yyp := -1 + goto yystack + +ret0: + return 0 + +ret1: + return 1 + +yystack: + /* put a state and value onto the stack */ + if yyDebug >= 4 { + __yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate)) + } + + yyp++ + if yyp >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyS[yyp] = yyVAL + yyS[yyp].yys = yystate + +yynewstate: + yyn = yyPact[yystate] + if yyn <= yyFlag { + goto yydefault /* simple state */ + } + if yyrcvr.char < 0 { + yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) + } + yyn += yytoken + if yyn < 0 || yyn >= yyLast { + goto yydefault + } + yyn = yyAct[yyn] + if yyChk[yyn] == yytoken { /* valid shift */ + yyrcvr.char = -1 + yytoken = -1 + yyVAL = yyrcvr.lval + yystate = yyn + if Errflag > 0 { + Errflag-- + } + goto yystack + } + +yydefault: + /* default state action */ + yyn = yyDef[yystate] + if yyn == -2 { + if yyrcvr.char < 0 { + yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) + } + + /* look through exception table */ + xi := 0 + for { + if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { + break + } + xi += 2 + } + for xi += 2; ; xi += 2 { + yyn = yyExca[xi+0] + if yyn < 0 || yyn == yytoken { + break + } + } + yyn = yyExca[xi+1] + if yyn < 0 { + goto ret0 + } + } + if yyn == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + yylex.Error(yyErrorMessage(yystate, yytoken)) + Nerrs++ + if yyDebug >= 1 { + __yyfmt__.Printf("%s", yyStatname(yystate)) + __yyfmt__.Printf(" saw %s\n", yyTokname(yytoken)) + } + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for yyp >= 0 { + yyn = yyPact[yyS[yyp].yys] + yyErrCode + if yyn >= 0 && yyn < yyLast { + yystate = yyAct[yyn] /* simulate a shift of "error" */ + if yyChk[yystate] == yyErrCode { + goto yystack + } + } + + /* the current p has no shift on "error", pop stack */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) + } + yyp-- + } + /* there is no state on the stack with an error shift ... abort */ + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken)) + } + if yytoken == yyEofCode { + goto ret1 + } + yyrcvr.char = -1 + yytoken = -1 + goto yynewstate /* try again in the same state */ + } + } + + /* reduction by production yyn */ + if yyDebug >= 2 { + __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) + } + + yynt := yyn + yypt := yyp + _ = yypt // guard against "declared and not used" + + yyp -= yyR2[yyn] + // yyp is now the index of $0. Perform the default action. Iff the + // reduced production is ε, $1 is possibly out of range. + if yyp+1 >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyVAL = yyS[yyp+1] + + /* consult goto table to find next state */ + yyn = yyR1[yyn] + yyg := yyPgo[yyn] + yyj := yyg + yyS[yyp].yys + 1 + + if yyj >= yyLast { + yystate = yyAct[yyg] + } else { + yystate = yyAct[yyj] + if yyChk[yystate] != -yyn { + yystate = yyAct[yyg] + } + } + // dummy call; replaced with literal code + switch yynt { + + case 1: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:73 + { + if yyDollar[1].value != nil { + yyDollar[2].value.(*Query).Meta = yyDollar[1].value.(*ConstObject) + } + yylex.(*lexer).result = yyDollar[2].value.(*Query) + } + case 2: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:80 + { + yyVAL.value = nil + } + case 3: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:84 + { + yyVAL.value = yyDollar[2].value + } + case 4: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:90 + { + yyVAL.value = &Query{Imports: yyDollar[1].value.([]*Import), FuncDefs: reverseFuncDef(yyDollar[2].value.([]*FuncDef)), Term: &Term{Type: TermTypeIdentity}} + } + case 5: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:94 + { + if yyDollar[1].value != nil { + yyDollar[2].value.(*Query).Imports = yyDollar[1].value.([]*Import) + } + yyVAL.value = yyDollar[2].value + } + case 6: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:101 + { + yyVAL.value = []*Import(nil) + } + case 7: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:105 + { + yyVAL.value = append(yyDollar[1].value.([]*Import), yyDollar[2].value.(*Import)) + } + case 8: + yyDollar = yyS[yypt-6 : yypt+1] +//line parser.go.y:111 + { + yyVAL.value = &Import{ImportPath: yyDollar[2].token, ImportAlias: yyDollar[4].token, Meta: yyDollar[5].value.(*ConstObject)} + } + case 9: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:115 + { + yyVAL.value = &Import{IncludePath: yyDollar[2].token, Meta: yyDollar[3].value.(*ConstObject)} + } + case 10: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:121 + { + yyVAL.value = (*ConstObject)(nil) + } + case 11: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:124 + { + } + case 12: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:128 + { + yyVAL.value = []*FuncDef(nil) + } + case 13: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:132 + { + yyVAL.value = append(yyDollar[2].value.([]*FuncDef), yyDollar[1].value.(*FuncDef)) + } + case 14: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:138 + { + yyVAL.value = &FuncDef{Name: yyDollar[2].token, Body: yyDollar[4].value.(*Query)} + } + case 15: + yyDollar = yyS[yypt-8 : yypt+1] +//line parser.go.y:142 + { + yyVAL.value = &FuncDef{yyDollar[2].token, yyDollar[4].value.([]string), yyDollar[7].value.(*Query)} + } + case 16: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:148 + { + yyVAL.value = []string{yyDollar[1].token} + } + case 17: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:152 + { + yyVAL.value = append(yyDollar[1].value.([]string), yyDollar[3].token) + } + case 18: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:157 + { + } + case 19: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:158 + { + } + case 20: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:162 + { + yyDollar[2].value.(*Query).FuncDefs = prependFuncDef(yyDollar[2].value.(*Query).FuncDefs, yyDollar[1].value.(*FuncDef)) + yyVAL.value = yyDollar[2].value + } + case 21: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:167 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpPipe, Right: yyDollar[3].value.(*Query)} + } + case 22: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:171 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Bind: &Bind{yyDollar[3].value.([]*Pattern), yyDollar[5].value.(*Query)}}) + yyVAL.value = &Query{Term: yyDollar[1].value.(*Term)} + } + case 23: + yyDollar = yyS[yypt-9 : yypt+1] +//line parser.go.y:176 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{yyDollar[2].value.(*Term), yyDollar[4].value.(*Pattern), yyDollar[6].value.(*Query), yyDollar[8].value.(*Query)}}} + } + case 24: + yyDollar = yyS[yypt-9 : yypt+1] +//line parser.go.y:180 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{yyDollar[2].value.(*Term), yyDollar[4].value.(*Pattern), yyDollar[6].value.(*Query), yyDollar[8].value.(*Query), nil}}} + } + case 25: + yyDollar = yyS[yypt-11 : yypt+1] +//line parser.go.y:184 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{yyDollar[2].value.(*Term), yyDollar[4].value.(*Pattern), yyDollar[6].value.(*Query), yyDollar[8].value.(*Query), yyDollar[10].value.(*Query)}}} + } + case 26: + yyDollar = yyS[yypt-7 : yypt+1] +//line parser.go.y:188 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeIf, If: &If{yyDollar[2].value.(*Query), yyDollar[4].value.(*Query), yyDollar[5].value.([]*IfElif), yyDollar[6].value.(*Query)}}} + } + case 27: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:192 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeTry, Try: &Try{yyDollar[2].value.(*Query), yyDollar[3].value.(*Query)}}} + } + case 28: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:196 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{yyDollar[2].token, yyDollar[4].value.(*Query)}}} + } + case 29: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:200 + { + if t := yyDollar[1].value.(*Query).Term; t != nil { + t.SuffixList = append(t.SuffixList, &Suffix{Optional: true}) + } else { + yyVAL.value = &Query{Term: &Term{Type: TermTypeQuery, Query: yyDollar[1].value.(*Query), SuffixList: []*Suffix{{Optional: true}}}} + } + } + case 30: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:208 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpComma, Right: yyDollar[3].value.(*Query)} + } + case 31: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:212 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: yyDollar[2].operator, Right: yyDollar[3].value.(*Query)} + } + case 32: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:216 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: yyDollar[2].operator, Right: yyDollar[3].value.(*Query)} + } + case 33: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:220 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpOr, Right: yyDollar[3].value.(*Query)} + } + case 34: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:224 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpAnd, Right: yyDollar[3].value.(*Query)} + } + case 35: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:228 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: yyDollar[2].operator, Right: yyDollar[3].value.(*Query)} + } + case 36: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:232 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpAdd, Right: yyDollar[3].value.(*Query)} + } + case 37: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:236 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpSub, Right: yyDollar[3].value.(*Query)} + } + case 38: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:240 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpMul, Right: yyDollar[3].value.(*Query)} + } + case 39: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:244 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpDiv, Right: yyDollar[3].value.(*Query)} + } + case 40: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:248 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpMod, Right: yyDollar[3].value.(*Query)} + } + case 41: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:252 + { + yyVAL.value = &Query{Term: yyDollar[1].value.(*Term)} + } + case 42: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:258 + { + yyVAL.value = []*Pattern{yyDollar[1].value.(*Pattern)} + } + case 43: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:262 + { + yyVAL.value = append(yyDollar[1].value.([]*Pattern), yyDollar[3].value.(*Pattern)) + } + case 44: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:268 + { + yyVAL.value = &Pattern{Name: yyDollar[1].token} + } + case 45: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:272 + { + yyVAL.value = &Pattern{Array: yyDollar[2].value.([]*Pattern)} + } + case 46: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:276 + { + yyVAL.value = &Pattern{Object: yyDollar[2].value.([]*PatternObject)} + } + case 47: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:282 + { + yyVAL.value = []*Pattern{yyDollar[1].value.(*Pattern)} + } + case 48: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:286 + { + yyVAL.value = append(yyDollar[1].value.([]*Pattern), yyDollar[3].value.(*Pattern)) + } + case 49: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:292 + { + yyVAL.value = []*PatternObject{yyDollar[1].value.(*PatternObject)} + } + case 50: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:296 + { + yyVAL.value = append(yyDollar[1].value.([]*PatternObject), yyDollar[3].value.(*PatternObject)) + } + case 51: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:302 + { + yyVAL.value = &PatternObject{Key: yyDollar[1].token, Val: yyDollar[3].value.(*Pattern)} + } + case 52: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:306 + { + yyVAL.value = &PatternObject{KeyString: yyDollar[1].value.(*String), Val: yyDollar[3].value.(*Pattern)} + } + case 53: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:310 + { + yyVAL.value = &PatternObject{KeyQuery: yyDollar[2].value.(*Query), Val: yyDollar[5].value.(*Pattern)} + } + case 54: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:314 + { + yyVAL.value = &PatternObject{Key: yyDollar[1].token} + } + case 55: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:320 + { + yyVAL.value = &Term{Type: TermTypeIdentity} + } + case 56: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:324 + { + yyVAL.value = &Term{Type: TermTypeRecurse} + } + case 57: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:328 + { + yyVAL.value = &Term{Type: TermTypeIndex, Index: &Index{Name: yyDollar[1].token}} + } + case 58: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:332 + { + if yyDollar[2].value.(*Suffix).Iter { + yyVAL.value = &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{yyDollar[2].value.(*Suffix)}} + } else { + yyVAL.value = &Term{Type: TermTypeIndex, Index: yyDollar[2].value.(*Suffix).Index} + } + } + case 59: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:340 + { + yyVAL.value = &Term{Type: TermTypeIndex, Index: &Index{Str: yyDollar[2].value.(*String)}} + } + case 60: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:344 + { + yyVAL.value = &Term{Type: TermTypeNull} + } + case 61: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:348 + { + yyVAL.value = &Term{Type: TermTypeTrue} + } + case 62: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:352 + { + yyVAL.value = &Term{Type: TermTypeFalse} + } + case 63: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:356 + { + yyVAL.value = &Term{Type: TermTypeFunc, Func: &Func{Name: yyDollar[1].token}} + } + case 64: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:360 + { + yyVAL.value = &Term{Type: TermTypeFunc, Func: &Func{Name: yyDollar[1].token, Args: yyDollar[3].value.([]*Query)}} + } + case 65: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:364 + { + yyVAL.value = &Term{Type: TermTypeFunc, Func: &Func{Name: yyDollar[1].token}} + } + case 66: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:368 + { + yyVAL.value = &Term{Type: TermTypeNumber, Number: yyDollar[1].token} + } + case 67: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:372 + { + yyVAL.value = &Term{Type: TermTypeFormat, Format: yyDollar[1].token} + } + case 68: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:376 + { + yyVAL.value = &Term{Type: TermTypeFormat, Format: yyDollar[1].token, Str: yyDollar[2].value.(*String)} + } + case 69: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:380 + { + yyVAL.value = &Term{Type: TermTypeString, Str: yyDollar[1].value.(*String)} + } + case 70: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:384 + { + yyVAL.value = &Term{Type: TermTypeQuery, Query: yyDollar[2].value.(*Query)} + } + case 71: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:388 + { + yyVAL.value = &Term{Type: TermTypeUnary, Unary: &Unary{OpAdd, yyDollar[2].value.(*Term)}} + } + case 72: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:392 + { + yyVAL.value = &Term{Type: TermTypeUnary, Unary: &Unary{OpSub, yyDollar[2].value.(*Term)}} + } + case 73: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:396 + { + yyVAL.value = &Term{Type: TermTypeObject, Object: &Object{}} + } + case 74: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:400 + { + yyVAL.value = &Term{Type: TermTypeObject, Object: &Object{yyDollar[2].value.([]*ObjectKeyVal)}} + } + case 75: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:404 + { + yyVAL.value = &Term{Type: TermTypeObject, Object: &Object{yyDollar[2].value.([]*ObjectKeyVal)}} + } + case 76: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:408 + { + yyVAL.value = &Term{Type: TermTypeArray, Array: &Array{}} + } + case 77: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:412 + { + yyVAL.value = &Term{Type: TermTypeArray, Array: &Array{yyDollar[2].value.(*Query)}} + } + case 78: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:416 + { + yyVAL.value = &Term{Type: TermTypeBreak, Break: yyDollar[2].token} + } + case 79: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:420 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Index: &Index{Name: yyDollar[2].token}}) + } + case 80: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:424 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, yyDollar[2].value.(*Suffix)) + } + case 81: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:428 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Optional: true}) + } + case 82: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:432 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, yyDollar[3].value.(*Suffix)) + } + case 83: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:436 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Index: &Index{Str: yyDollar[3].value.(*String)}}) + } + case 84: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:442 + { + yyVAL.value = &String{Str: yyDollar[1].token} + } + case 85: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:446 + { + yyVAL.value = &String{Queries: yyDollar[2].value.([]*Query)} + } + case 86: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:452 + { + yyVAL.value = []*Query{} + } + case 87: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:456 + { + yyVAL.value = append(yyDollar[1].value.([]*Query), &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: yyDollar[2].token}}}) + } + case 88: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:460 + { + yylex.(*lexer).inString = true + yyVAL.value = append(yyDollar[1].value.([]*Query), &Query{Term: &Term{Type: TermTypeQuery, Query: yyDollar[3].value.(*Query)}}) + } + case 89: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:466 + { + } + case 90: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:467 + { + } + case 91: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:470 + { + } + case 92: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:471 + { + } + case 93: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:475 + { + yyVAL.value = &Suffix{Iter: true} + } + case 94: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:479 + { + yyVAL.value = &Suffix{Index: &Index{Start: yyDollar[2].value.(*Query)}} + } + case 95: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:483 + { + yyVAL.value = &Suffix{Index: &Index{Start: yyDollar[2].value.(*Query), IsSlice: true}} + } + case 96: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:487 + { + yyVAL.value = &Suffix{Index: &Index{End: yyDollar[3].value.(*Query), IsSlice: true}} + } + case 97: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:491 + { + yyVAL.value = &Suffix{Index: &Index{Start: yyDollar[2].value.(*Query), End: yyDollar[4].value.(*Query), IsSlice: true}} + } + case 98: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:497 + { + yyVAL.value = []*Query{yyDollar[1].value.(*Query)} + } + case 99: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:501 + { + yyVAL.value = append(yyDollar[1].value.([]*Query), yyDollar[3].value.(*Query)) + } + case 100: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:507 + { + yyVAL.value = []*IfElif(nil) + } + case 101: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:511 + { + yyVAL.value = append(yyDollar[1].value.([]*IfElif), &IfElif{yyDollar[3].value.(*Query), yyDollar[5].value.(*Query)}) + } + case 102: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:517 + { + yyVAL.value = (*Query)(nil) + } + case 103: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:521 + { + yyVAL.value = yyDollar[2].value + } + case 104: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:527 + { + yyVAL.value = (*Query)(nil) + } + case 105: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:531 + { + yyVAL.value = yyDollar[2].value + } + case 106: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:537 + { + yyVAL.value = []*ObjectKeyVal{yyDollar[1].value.(*ObjectKeyVal)} + } + case 107: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:541 + { + yyVAL.value = append(yyDollar[1].value.([]*ObjectKeyVal), yyDollar[3].value.(*ObjectKeyVal)) + } + case 108: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:547 + { + yyVAL.value = &ObjectKeyVal{Key: yyDollar[1].token, Val: yyDollar[3].value.(*ObjectVal)} + } + case 109: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:551 + { + yyVAL.value = &ObjectKeyVal{KeyString: yyDollar[1].value.(*String), Val: yyDollar[3].value.(*ObjectVal)} + } + case 110: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:555 + { + yyVAL.value = &ObjectKeyVal{KeyQuery: yyDollar[2].value.(*Query), Val: yyDollar[5].value.(*ObjectVal)} + } + case 111: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:559 + { + yyVAL.value = &ObjectKeyVal{Key: yyDollar[1].token} + } + case 112: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:563 + { + yyVAL.value = &ObjectKeyVal{KeyString: yyDollar[1].value.(*String)} + } + case 113: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:568 + { + } + case 114: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:569 + { + } + case 115: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:570 + { + } + case 116: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:574 + { + yyVAL.value = &ObjectVal{[]*Query{{Term: yyDollar[1].value.(*Term)}}} + } + case 117: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:578 + { + yyVAL.value = &ObjectVal{append(yyDollar[1].value.(*ObjectVal).Queries, &Query{Term: yyDollar[3].value.(*Term)})} + } + case 118: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:584 + { + yyVAL.value = &ConstTerm{Object: yyDollar[1].value.(*ConstObject)} + } + case 119: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:588 + { + yyVAL.value = &ConstTerm{Array: yyDollar[1].value.(*ConstArray)} + } + case 120: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:592 + { + yyVAL.value = &ConstTerm{Number: yyDollar[1].token} + } + case 121: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:596 + { + yyVAL.value = &ConstTerm{Str: yyDollar[1].token} + } + case 122: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:600 + { + yyVAL.value = &ConstTerm{Null: true} + } + case 123: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:604 + { + yyVAL.value = &ConstTerm{True: true} + } + case 124: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:608 + { + yyVAL.value = &ConstTerm{False: true} + } + case 125: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:614 + { + yyVAL.value = &ConstObject{} + } + case 126: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:618 + { + yyVAL.value = &ConstObject{yyDollar[2].value.([]*ConstObjectKeyVal)} + } + case 127: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:622 + { + yyVAL.value = &ConstObject{yyDollar[2].value.([]*ConstObjectKeyVal)} + } + case 128: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:628 + { + yyVAL.value = []*ConstObjectKeyVal{yyDollar[1].value.(*ConstObjectKeyVal)} + } + case 129: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:632 + { + yyVAL.value = append(yyDollar[1].value.([]*ConstObjectKeyVal), yyDollar[3].value.(*ConstObjectKeyVal)) + } + case 130: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:638 + { + yyVAL.value = &ConstObjectKeyVal{Key: yyDollar[1].token, Val: yyDollar[3].value.(*ConstTerm)} + } + case 131: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:642 + { + yyVAL.value = &ConstObjectKeyVal{Key: yyDollar[1].token, Val: yyDollar[3].value.(*ConstTerm)} + } + case 132: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:646 + { + yyVAL.value = &ConstObjectKeyVal{KeyString: yyDollar[1].token, Val: yyDollar[3].value.(*ConstTerm)} + } + case 133: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:652 + { + yyVAL.value = &ConstArray{} + } + case 134: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:656 + { + yyVAL.value = &ConstArray{yyDollar[2].value.([]*ConstTerm)} + } + case 135: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:662 + { + yyVAL.value = []*ConstTerm{yyDollar[1].value.(*ConstTerm)} + } + case 136: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:666 + { + yyVAL.value = append(yyDollar[1].value.([]*ConstTerm), yyDollar[3].value.(*ConstTerm)) + } + case 137: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:671 + { + } + case 138: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:672 + { + } + case 139: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:673 + { + } + case 140: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:674 + { + } + case 141: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:675 + { + } + case 142: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:676 + { + } + case 143: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:677 + { + } + case 144: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:678 + { + } + case 145: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:679 + { + } + case 146: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:680 + { + } + case 147: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:681 + { + } + case 148: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:682 + { + } + case 149: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:683 + { + } + case 150: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:684 + { + } + case 151: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:685 + { + } + case 152: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:686 + { + } + case 153: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:687 + { + } + case 154: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:688 + { + } + case 155: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:689 + { + } + case 156: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:690 + { + } + case 157: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:691 + { + } + } + goto yystack /* stack new state and value */ +} diff --git a/vendor/github.com/itchyny/gojq/parser.go.y b/vendor/github.com/itchyny/gojq/parser.go.y new file mode 100644 index 00000000..e03b14bc --- /dev/null +++ b/vendor/github.com/itchyny/gojq/parser.go.y @@ -0,0 +1,693 @@ +%{ +package gojq + +// Parse a query string, and returns the query struct. +// +// If parsing failed, the returned error has the method Token() (string, int), +// which reports the invalid token and the byte offset in the query string. The +// token is empty if the error occurred after scanning the entire query string. +// The byte offset is the scanned bytes when the error occurred. +func Parse(src string) (*Query, error) { + l := newLexer(src) + if yyParse(l) > 0 { + return nil, l.err + } + return l.result, nil +} + +func reverseFuncDef(xs []*FuncDef) []*FuncDef { + for i, j := 0, len(xs)-1; i < j; i, j = i+1, j-1 { + xs[i], xs[j] = xs[j], xs[i] + } + return xs +} + +func prependFuncDef(xs []*FuncDef, x *FuncDef) []*FuncDef { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} +%} + +%union { + value interface{} + token string + operator Operator +} + +%type program moduleheader programbody imports import metaopt funcdefs funcdef funcdefargs query +%type bindpatterns pattern arraypatterns objectpatterns objectpattern +%type term string stringparts suffix args ifelifs ifelse trycatch +%type objectkeyvals objectkeyval objectval +%type constterm constobject constobjectkeyvals constobjectkeyval constarray constarrayelems +%type tokIdentVariable tokIdentModuleIdent tokVariableModuleVariable tokKeyword objectkey +%token tokAltOp tokUpdateOp tokDestAltOp tokOrOp tokAndOp tokCompareOp +%token tokModule tokImport tokInclude tokDef tokAs tokLabel tokBreak +%token tokNull tokTrue tokFalse +%token tokIdent tokVariable tokModuleIdent tokModuleVariable +%token tokIndex tokNumber tokFormat +%token tokString tokStringStart tokStringQuery tokStringEnd +%token tokIf tokThen tokElif tokElse tokEnd +%token tokTry tokCatch tokReduce tokForeach +%token tokRecurse tokFuncDefPost tokTermPost tokEmptyCatch +%token tokInvalid tokInvalidEscapeSequence tokUnterminatedString + +%nonassoc tokFuncDefPost tokTermPost +%right '|' +%left ',' +%right tokAltOp +%nonassoc tokUpdateOp +%left tokOrOp +%left tokAndOp +%nonassoc tokCompareOp +%left '+' '-' +%left '*' '/' '%' +%nonassoc tokAs tokIndex '.' '?' tokEmptyCatch +%nonassoc '[' tokTry tokCatch + +%% + +program + : moduleheader programbody + { + if $1 != nil { $2.(*Query).Meta = $1.(*ConstObject) } + yylex.(*lexer).result = $2.(*Query) + } + +moduleheader + : + { + $$ = nil + } + | tokModule constobject ';' + { + $$ = $2; + } + +programbody + : imports funcdefs + { + $$ = &Query{Imports: $1.([]*Import), FuncDefs: reverseFuncDef($2.([]*FuncDef)), Term: &Term{Type: TermTypeIdentity}} + } + | imports query + { + if $1 != nil { $2.(*Query).Imports = $1.([]*Import) } + $$ = $2 + } + +imports + : + { + $$ = []*Import(nil) + } + | imports import + { + $$ = append($1.([]*Import), $2.(*Import)) + } + +import + : tokImport tokString tokAs tokIdentVariable metaopt ';' + { + $$ = &Import{ImportPath: $2, ImportAlias: $4, Meta: $5.(*ConstObject)} + } + | tokInclude tokString metaopt ';' + { + $$ = &Import{IncludePath: $2, Meta: $3.(*ConstObject)} + } + +metaopt + : + { + $$ = (*ConstObject)(nil) + } + | constobject {} + +funcdefs + : + { + $$ = []*FuncDef(nil) + } + | funcdef funcdefs + { + $$ = append($2.([]*FuncDef), $1.(*FuncDef)) + } + +funcdef + : tokDef tokIdent ':' query ';' + { + $$ = &FuncDef{Name: $2, Body: $4.(*Query)} + } + | tokDef tokIdent '(' funcdefargs ')' ':' query ';' + { + $$ = &FuncDef{$2, $4.([]string), $7.(*Query)} + } + +funcdefargs + : tokIdentVariable + { + $$ = []string{$1} + } + | funcdefargs ';' tokIdentVariable + { + $$ = append($1.([]string), $3) + } + +tokIdentVariable + : tokIdent {} + | tokVariable {} + +query + : funcdef query %prec tokFuncDefPost + { + $2.(*Query).FuncDefs = prependFuncDef($2.(*Query).FuncDefs, $1.(*FuncDef)) + $$ = $2 + } + | query '|' query + { + $$ = &Query{Left: $1.(*Query), Op: OpPipe, Right: $3.(*Query)} + } + | term tokAs bindpatterns '|' query + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Bind: &Bind{$3.([]*Pattern), $5.(*Query)}}) + $$ = &Query{Term: $1.(*Term)} + } + | tokReduce term tokAs pattern '(' query ';' query ')' + { + $$ = &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{$2.(*Term), $4.(*Pattern), $6.(*Query), $8.(*Query)}}} + } + | tokForeach term tokAs pattern '(' query ';' query ')' + { + $$ = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{$2.(*Term), $4.(*Pattern), $6.(*Query), $8.(*Query), nil}}} + } + | tokForeach term tokAs pattern '(' query ';' query ';' query ')' + { + $$ = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{$2.(*Term), $4.(*Pattern), $6.(*Query), $8.(*Query), $10.(*Query)}}} + } + | tokIf query tokThen query ifelifs ifelse tokEnd + { + $$ = &Query{Term: &Term{Type: TermTypeIf, If: &If{$2.(*Query), $4.(*Query), $5.([]*IfElif), $6.(*Query)}}} + } + | tokTry query trycatch + { + $$ = &Query{Term: &Term{Type: TermTypeTry, Try: &Try{$2.(*Query), $3.(*Query)}}} + } + | tokLabel tokVariable '|' query + { + $$ = &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{$2, $4.(*Query)}}} + } + | query '?' + { + if t := $1.(*Query).Term; t != nil { + t.SuffixList = append(t.SuffixList, &Suffix{Optional: true}) + } else { + $$ = &Query{Term: &Term{Type: TermTypeQuery, Query: $1.(*Query), SuffixList: []*Suffix{{Optional: true}}}} + } + } + | query ',' query + { + $$ = &Query{Left: $1.(*Query), Op: OpComma, Right: $3.(*Query)} + } + | query tokAltOp query + { + $$ = &Query{Left: $1.(*Query), Op: $2, Right: $3.(*Query)} + } + | query tokUpdateOp query + { + $$ = &Query{Left: $1.(*Query), Op: $2, Right: $3.(*Query)} + } + | query tokOrOp query + { + $$ = &Query{Left: $1.(*Query), Op: OpOr, Right: $3.(*Query)} + } + | query tokAndOp query + { + $$ = &Query{Left: $1.(*Query), Op: OpAnd, Right: $3.(*Query)} + } + | query tokCompareOp query + { + $$ = &Query{Left: $1.(*Query), Op: $2, Right: $3.(*Query)} + } + | query '+' query + { + $$ = &Query{Left: $1.(*Query), Op: OpAdd, Right: $3.(*Query)} + } + | query '-' query + { + $$ = &Query{Left: $1.(*Query), Op: OpSub, Right: $3.(*Query)} + } + | query '*' query + { + $$ = &Query{Left: $1.(*Query), Op: OpMul, Right: $3.(*Query)} + } + | query '/' query + { + $$ = &Query{Left: $1.(*Query), Op: OpDiv, Right: $3.(*Query)} + } + | query '%' query + { + $$ = &Query{Left: $1.(*Query), Op: OpMod, Right: $3.(*Query)} + } + | term %prec tokTermPost + { + $$ = &Query{Term: $1.(*Term)} + } + +bindpatterns + : pattern + { + $$ = []*Pattern{$1.(*Pattern)} + } + | bindpatterns tokDestAltOp pattern + { + $$ = append($1.([]*Pattern), $3.(*Pattern)) + } + +pattern + : tokVariable + { + $$ = &Pattern{Name: $1} + } + | '[' arraypatterns ']' + { + $$ = &Pattern{Array: $2.([]*Pattern)} + } + | '{' objectpatterns '}' + { + $$ = &Pattern{Object: $2.([]*PatternObject)} + } + +arraypatterns + : pattern + { + $$ = []*Pattern{$1.(*Pattern)} + } + | arraypatterns ',' pattern + { + $$ = append($1.([]*Pattern), $3.(*Pattern)) + } + +objectpatterns + : objectpattern + { + $$ = []*PatternObject{$1.(*PatternObject)} + } + | objectpatterns ',' objectpattern + { + $$ = append($1.([]*PatternObject), $3.(*PatternObject)) + } + +objectpattern + : objectkey ':' pattern + { + $$ = &PatternObject{Key: $1, Val: $3.(*Pattern)} + } + | string ':' pattern + { + $$ = &PatternObject{KeyString: $1.(*String), Val: $3.(*Pattern)} + } + | '(' query ')' ':' pattern + { + $$ = &PatternObject{KeyQuery: $2.(*Query), Val: $5.(*Pattern)} + } + | tokVariable + { + $$ = &PatternObject{Key: $1} + } + +term + : '.' + { + $$ = &Term{Type: TermTypeIdentity} + } + | tokRecurse + { + $$ = &Term{Type: TermTypeRecurse} + } + | tokIndex + { + $$ = &Term{Type: TermTypeIndex, Index: &Index{Name: $1}} + } + | '.' suffix + { + if $2.(*Suffix).Iter { + $$ = &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{$2.(*Suffix)}} + } else { + $$ = &Term{Type: TermTypeIndex, Index: $2.(*Suffix).Index} + } + } + | '.' string + { + $$ = &Term{Type: TermTypeIndex, Index: &Index{Str: $2.(*String)}} + } + | tokNull + { + $$ = &Term{Type: TermTypeNull} + } + | tokTrue + { + $$ = &Term{Type: TermTypeTrue} + } + | tokFalse + { + $$ = &Term{Type: TermTypeFalse} + } + | tokIdentModuleIdent + { + $$ = &Term{Type: TermTypeFunc, Func: &Func{Name: $1}} + } + | tokIdentModuleIdent '(' args ')' + { + $$ = &Term{Type: TermTypeFunc, Func: &Func{Name: $1, Args: $3.([]*Query)}} + } + | tokVariableModuleVariable + { + $$ = &Term{Type: TermTypeFunc, Func: &Func{Name: $1}} + } + | tokNumber + { + $$ = &Term{Type: TermTypeNumber, Number: $1} + } + | tokFormat + { + $$ = &Term{Type: TermTypeFormat, Format: $1} + } + | tokFormat string + { + $$ = &Term{Type: TermTypeFormat, Format: $1, Str: $2.(*String)} + } + | string + { + $$ = &Term{Type: TermTypeString, Str: $1.(*String)} + } + | '(' query ')' + { + $$ = &Term{Type: TermTypeQuery, Query: $2.(*Query)} + } + | '+' term + { + $$ = &Term{Type: TermTypeUnary, Unary: &Unary{OpAdd, $2.(*Term)}} + } + | '-' term + { + $$ = &Term{Type: TermTypeUnary, Unary: &Unary{OpSub, $2.(*Term)}} + } + | '{' '}' + { + $$ = &Term{Type: TermTypeObject, Object: &Object{}} + } + | '{' objectkeyvals '}' + { + $$ = &Term{Type: TermTypeObject, Object: &Object{$2.([]*ObjectKeyVal)}} + } + | '{' objectkeyvals ',' '}' + { + $$ = &Term{Type: TermTypeObject, Object: &Object{$2.([]*ObjectKeyVal)}} + } + | '[' ']' + { + $$ = &Term{Type: TermTypeArray, Array: &Array{}} + } + | '[' query ']' + { + $$ = &Term{Type: TermTypeArray, Array: &Array{$2.(*Query)}} + } + | tokBreak tokVariable + { + $$ = &Term{Type: TermTypeBreak, Break: $2} + } + | term tokIndex + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Index: &Index{Name: $2}}) + } + | term suffix + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, $2.(*Suffix)) + } + | term '?' + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Optional: true}) + } + | term '.' suffix + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, $3.(*Suffix)) + } + | term '.' string + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Index: &Index{Str: $3.(*String)}}) + } + +string + : tokString + { + $$ = &String{Str: $1} + } + | tokStringStart stringparts tokStringEnd + { + $$ = &String{Queries: $2.([]*Query)} + } + +stringparts + : + { + $$ = []*Query{} + } + | stringparts tokString + { + $$ = append($1.([]*Query), &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: $2}}}) + } + | stringparts tokStringQuery query ')' + { + yylex.(*lexer).inString = true + $$ = append($1.([]*Query), &Query{Term: &Term{Type: TermTypeQuery, Query: $3.(*Query)}}) + } + +tokIdentModuleIdent + : tokIdent {} + | tokModuleIdent {} + +tokVariableModuleVariable + : tokVariable {} + | tokModuleVariable {} + +suffix + : '[' ']' + { + $$ = &Suffix{Iter: true} + } + | '[' query ']' + { + $$ = &Suffix{Index: &Index{Start: $2.(*Query)}} + } + | '[' query ':' ']' + { + $$ = &Suffix{Index: &Index{Start: $2.(*Query), IsSlice: true}} + } + | '[' ':' query ']' + { + $$ = &Suffix{Index: &Index{End: $3.(*Query), IsSlice: true}} + } + | '[' query ':' query ']' + { + $$ = &Suffix{Index: &Index{Start: $2.(*Query), End: $4.(*Query), IsSlice: true}} + } + +args + : query + { + $$ = []*Query{$1.(*Query)} + } + | args ';' query + { + $$ = append($1.([]*Query), $3.(*Query)) + } + +ifelifs + : + { + $$ = []*IfElif(nil) + } + | ifelifs tokElif query tokThen query + { + $$ = append($1.([]*IfElif), &IfElif{$3.(*Query), $5.(*Query)}) + } + +ifelse + : + { + $$ = (*Query)(nil) + } + | tokElse query + { + $$ = $2 + } + +trycatch + : %prec tokEmptyCatch + { + $$ = (*Query)(nil) + } + | tokCatch query + { + $$ = $2 + } + +objectkeyvals + : objectkeyval + { + $$ = []*ObjectKeyVal{$1.(*ObjectKeyVal)} + } + | objectkeyvals ',' objectkeyval + { + $$ = append($1.([]*ObjectKeyVal), $3.(*ObjectKeyVal)) + } + +objectkeyval + : objectkey ':' objectval + { + $$ = &ObjectKeyVal{Key: $1, Val: $3.(*ObjectVal)} + } + | string ':' objectval + { + $$ = &ObjectKeyVal{KeyString: $1.(*String), Val: $3.(*ObjectVal)} + } + | '(' query ')' ':' objectval + { + $$ = &ObjectKeyVal{KeyQuery: $2.(*Query), Val: $5.(*ObjectVal)} + } + | objectkey + { + $$ = &ObjectKeyVal{Key: $1} + } + | string + { + $$ = &ObjectKeyVal{KeyString: $1.(*String)} + } + +objectkey + : tokIdent {} + | tokVariable {} + | tokKeyword {} + +objectval + : term + { + $$ = &ObjectVal{[]*Query{{Term: $1.(*Term)}}} + } + | objectval '|' term + { + $$ = &ObjectVal{append($1.(*ObjectVal).Queries, &Query{Term: $3.(*Term)})} + } + +constterm + : constobject + { + $$ = &ConstTerm{Object: $1.(*ConstObject)} + } + | constarray + { + $$ = &ConstTerm{Array: $1.(*ConstArray)} + } + | tokNumber + { + $$ = &ConstTerm{Number: $1} + } + | tokString + { + $$ = &ConstTerm{Str: $1} + } + | tokNull + { + $$ = &ConstTerm{Null: true} + } + | tokTrue + { + $$ = &ConstTerm{True: true} + } + | tokFalse + { + $$ = &ConstTerm{False: true} + } + +constobject + : '{' '}' + { + $$ = &ConstObject{} + } + | '{' constobjectkeyvals '}' + { + $$ = &ConstObject{$2.([]*ConstObjectKeyVal)} + } + | '{' constobjectkeyvals ',' '}' + { + $$ = &ConstObject{$2.([]*ConstObjectKeyVal)} + } + +constobjectkeyvals + : constobjectkeyval + { + $$ = []*ConstObjectKeyVal{$1.(*ConstObjectKeyVal)} + } + | constobjectkeyvals ',' constobjectkeyval + { + $$ = append($1.([]*ConstObjectKeyVal), $3.(*ConstObjectKeyVal)) + } + +constobjectkeyval + : tokIdent ':' constterm + { + $$ = &ConstObjectKeyVal{Key: $1, Val: $3.(*ConstTerm)} + } + | tokKeyword ':' constterm + { + $$ = &ConstObjectKeyVal{Key: $1, Val: $3.(*ConstTerm)} + } + | tokString ':' constterm + { + $$ = &ConstObjectKeyVal{KeyString: $1, Val: $3.(*ConstTerm)} + } + +constarray + : '[' ']' + { + $$ = &ConstArray{} + } + | '[' constarrayelems ']' + { + $$ = &ConstArray{$2.([]*ConstTerm)} + } + +constarrayelems + : constterm + { + $$ = []*ConstTerm{$1.(*ConstTerm)} + } + | constarrayelems ',' constterm + { + $$ = append($1.([]*ConstTerm), $3.(*ConstTerm)) + } + +tokKeyword + : tokOrOp {} + | tokAndOp {} + | tokModule {} + | tokImport {} + | tokInclude {} + | tokDef {} + | tokAs {} + | tokLabel {} + | tokBreak {} + | tokNull {} + | tokTrue {} + | tokFalse {} + | tokIf {} + | tokThen {} + | tokElif {} + | tokElse {} + | tokEnd {} + | tokTry {} + | tokCatch {} + | tokReduce {} + | tokForeach {} + +%% diff --git a/vendor/github.com/itchyny/gojq/preview.go b/vendor/github.com/itchyny/gojq/preview.go new file mode 100644 index 00000000..728669b6 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/preview.go @@ -0,0 +1,77 @@ +package gojq + +import "unicode/utf8" + +// Preview returns the preview string of v. The preview string is basically the +// same as the jq-flavored JSON encoding returned by Marshal, but is truncated +// by 30 bytes, and more efficient than truncating the result of Marshal. +// +// This method is used by error messages of built-in operators and functions, +// and accepts only limited types (nil, bool, int, float64, *big.Int, string, +// []interface{}, and map[string]interface{}). Note that the maximum width and +// trailing strings on truncation may be changed in the future. +func Preview(v interface{}) string { + bs := jsonLimitedMarshal(v, 32) + if l := 30; len(bs) > l { + var trailing string + switch v.(type) { + case string: + trailing = ` ..."` + case []interface{}: + trailing = " ...]" + case map[string]interface{}: + trailing = " ...}" + default: + trailing = " ..." + } + for len(bs) > l-len(trailing) { + _, size := utf8.DecodeLastRune(bs) + bs = bs[:len(bs)-size] + } + bs = append(bs, trailing...) + } + return string(bs) +} + +func jsonLimitedMarshal(v interface{}, n int) (bs []byte) { + w := &limitedWriter{buf: make([]byte, n)} + defer func() { + _ = recover() + bs = w.Bytes() + }() + (&encoder{w: w}).encode(v) + return +} + +type limitedWriter struct { + buf []byte + off int +} + +func (w *limitedWriter) Write(bs []byte) (int, error) { + n := copy(w.buf[w.off:], bs) + if w.off += n; w.off == len(w.buf) { + panic(nil) + } + return n, nil +} + +func (w *limitedWriter) WriteByte(b byte) error { + w.buf[w.off] = b + if w.off++; w.off == len(w.buf) { + panic(nil) + } + return nil +} + +func (w *limitedWriter) WriteString(s string) (int, error) { + n := copy(w.buf[w.off:], s) + if w.off += n; w.off == len(w.buf) { + panic(nil) + } + return n, nil +} + +func (w *limitedWriter) Bytes() []byte { + return w.buf[:w.off] +} diff --git a/vendor/github.com/itchyny/gojq/query.go b/vendor/github.com/itchyny/gojq/query.go new file mode 100644 index 00000000..863fba8f --- /dev/null +++ b/vendor/github.com/itchyny/gojq/query.go @@ -0,0 +1,1170 @@ +package gojq + +import ( + "context" + "strings" +) + +// Query represents the abstract syntax tree of a jq query. +type Query struct { + Meta *ConstObject + Imports []*Import + FuncDefs []*FuncDef + Term *Term + Left *Query + Op Operator + Right *Query + Func string +} + +// Run the query. +// +// It is safe to call this method of a *Query in multiple goroutines. +func (e *Query) Run(v interface{}) Iter { + return e.RunWithContext(context.Background(), v) +} + +// RunWithContext runs the query with context. +func (e *Query) RunWithContext(ctx context.Context, v interface{}) Iter { + code, err := Compile(e) + if err != nil { + return NewIter(err) + } + return code.RunWithContext(ctx, v) +} + +func (e *Query) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Query) writeTo(s *strings.Builder) { + if e.Meta != nil { + s.WriteString("module ") + e.Meta.writeTo(s) + s.WriteString(";\n") + } + for _, im := range e.Imports { + im.writeTo(s) + } + for i, fd := range e.FuncDefs { + if i > 0 { + s.WriteByte(' ') + } + fd.writeTo(s) + } + if len(e.FuncDefs) > 0 { + s.WriteByte(' ') + } + if e.Func != "" { + s.WriteString(e.Func) + } else if e.Term != nil { + e.Term.writeTo(s) + } else if e.Right != nil { + e.Left.writeTo(s) + if e.Op == OpComma { + s.WriteString(", ") + } else { + s.WriteByte(' ') + s.WriteString(e.Op.String()) + s.WriteByte(' ') + } + e.Right.writeTo(s) + } +} + +func (e *Query) minify() { + for _, e := range e.FuncDefs { + e.Minify() + } + if e.Term != nil { + if name := e.Term.toFunc(); name != "" { + e.Term = nil + e.Func = name + } else { + e.Term.minify() + } + } else if e.Right != nil { + e.Left.minify() + e.Right.minify() + } +} + +func (e *Query) toIndexKey() interface{} { + if e.Term == nil { + return nil + } + return e.Term.toIndexKey() +} + +func (e *Query) toIndices(xs []interface{}) []interface{} { + if e.Term == nil { + return nil + } + return e.Term.toIndices(xs) +} + +// Import ... +type Import struct { + ImportPath string + ImportAlias string + IncludePath string + Meta *ConstObject +} + +func (e *Import) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Import) writeTo(s *strings.Builder) { + if e.ImportPath != "" { + s.WriteString("import ") + jsonEncodeString(s, e.ImportPath) + s.WriteString(" as ") + s.WriteString(e.ImportAlias) + } else { + s.WriteString("include ") + jsonEncodeString(s, e.IncludePath) + } + if e.Meta != nil { + s.WriteByte(' ') + e.Meta.writeTo(s) + } + s.WriteString(";\n") +} + +// FuncDef ... +type FuncDef struct { + Name string + Args []string + Body *Query +} + +func (e *FuncDef) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *FuncDef) writeTo(s *strings.Builder) { + s.WriteString("def ") + s.WriteString(e.Name) + if len(e.Args) > 0 { + s.WriteByte('(') + for i, e := range e.Args { + if i > 0 { + s.WriteString("; ") + } + s.WriteString(e) + } + s.WriteByte(')') + } + s.WriteString(": ") + e.Body.writeTo(s) + s.WriteByte(';') +} + +// Minify ... +func (e *FuncDef) Minify() { + e.Body.minify() +} + +// Term ... +type Term struct { + Type TermType + Index *Index + Func *Func + Object *Object + Array *Array + Number string + Unary *Unary + Format string + Str *String + If *If + Try *Try + Reduce *Reduce + Foreach *Foreach + Label *Label + Break string + Query *Query + SuffixList []*Suffix +} + +func (e *Term) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Term) writeTo(s *strings.Builder) { + switch e.Type { + case TermTypeIdentity: + s.WriteByte('.') + case TermTypeRecurse: + s.WriteString("..") + case TermTypeNull: + s.WriteString("null") + case TermTypeTrue: + s.WriteString("true") + case TermTypeFalse: + s.WriteString("false") + case TermTypeIndex: + e.Index.writeTo(s) + case TermTypeFunc: + e.Func.writeTo(s) + case TermTypeObject: + e.Object.writeTo(s) + case TermTypeArray: + e.Array.writeTo(s) + case TermTypeNumber: + s.WriteString(e.Number) + case TermTypeUnary: + e.Unary.writeTo(s) + case TermTypeFormat: + s.WriteString(e.Format) + if e.Str != nil { + s.WriteByte(' ') + e.Str.writeTo(s) + } + case TermTypeString: + e.Str.writeTo(s) + case TermTypeIf: + e.If.writeTo(s) + case TermTypeTry: + e.Try.writeTo(s) + case TermTypeReduce: + e.Reduce.writeTo(s) + case TermTypeForeach: + e.Foreach.writeTo(s) + case TermTypeLabel: + e.Label.writeTo(s) + case TermTypeBreak: + s.WriteString("break ") + s.WriteString(e.Break) + case TermTypeQuery: + s.WriteByte('(') + e.Query.writeTo(s) + s.WriteByte(')') + } + for _, e := range e.SuffixList { + e.writeTo(s) + } +} + +func (e *Term) minify() { + switch e.Type { + case TermTypeIndex: + e.Index.minify() + case TermTypeFunc: + e.Func.minify() + case TermTypeObject: + e.Object.minify() + case TermTypeArray: + e.Array.minify() + case TermTypeUnary: + e.Unary.minify() + case TermTypeFormat: + if e.Str != nil { + e.Str.minify() + } + case TermTypeString: + e.Str.minify() + case TermTypeIf: + e.If.minify() + case TermTypeTry: + e.Try.minify() + case TermTypeReduce: + e.Reduce.minify() + case TermTypeForeach: + e.Foreach.minify() + case TermTypeLabel: + e.Label.minify() + case TermTypeQuery: + e.Query.minify() + } + for _, e := range e.SuffixList { + e.minify() + } +} + +func (e *Term) toFunc() string { + if len(e.SuffixList) != 0 { + return "" + } + // ref: compiler#compileQuery + switch e.Type { + case TermTypeIdentity: + return "." + case TermTypeRecurse: + return ".." + case TermTypeNull: + return "null" + case TermTypeTrue: + return "true" + case TermTypeFalse: + return "false" + case TermTypeFunc: + return e.Func.toFunc() + default: + return "" + } +} + +func (e *Term) toIndexKey() interface{} { + switch e.Type { + case TermTypeNumber: + return toNumber(e.Number) + case TermTypeUnary: + return e.Unary.toNumber() + case TermTypeString: + if e.Str.Queries == nil { + return e.Str.Str + } + return nil + default: + return nil + } +} + +func (e *Term) toIndices(xs []interface{}) []interface{} { + switch e.Type { + case TermTypeIndex: + if xs = e.Index.toIndices(xs); xs == nil { + return nil + } + case TermTypeQuery: + if xs = e.Query.toIndices(xs); xs == nil { + return nil + } + default: + return nil + } + for _, s := range e.SuffixList { + if xs = s.toIndices(xs); xs == nil { + return nil + } + } + return xs +} + +func (e *Term) toNumber() interface{} { + if e.Type == TermTypeNumber { + return toNumber(e.Number) + } + return nil +} + +// Unary ... +type Unary struct { + Op Operator + Term *Term +} + +func (e *Unary) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Unary) writeTo(s *strings.Builder) { + s.WriteString(e.Op.String()) + e.Term.writeTo(s) +} + +func (e *Unary) minify() { + e.Term.minify() +} + +func (e *Unary) toNumber() interface{} { + v := e.Term.toNumber() + if v != nil && e.Op == OpSub { + v = funcOpNegate(v) + } + return v +} + +// Pattern ... +type Pattern struct { + Name string + Array []*Pattern + Object []*PatternObject +} + +func (e *Pattern) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Pattern) writeTo(s *strings.Builder) { + if e.Name != "" { + s.WriteString(e.Name) + } else if len(e.Array) > 0 { + s.WriteByte('[') + for i, e := range e.Array { + if i > 0 { + s.WriteString(", ") + } + e.writeTo(s) + } + s.WriteByte(']') + } else if len(e.Object) > 0 { + s.WriteByte('{') + for i, e := range e.Object { + if i > 0 { + s.WriteString(", ") + } + e.writeTo(s) + } + s.WriteByte('}') + } +} + +// PatternObject ... +type PatternObject struct { + Key string + KeyString *String + KeyQuery *Query + Val *Pattern +} + +func (e *PatternObject) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *PatternObject) writeTo(s *strings.Builder) { + if e.Key != "" { + s.WriteString(e.Key) + } else if e.KeyString != nil { + e.KeyString.writeTo(s) + } else if e.KeyQuery != nil { + s.WriteByte('(') + e.KeyQuery.writeTo(s) + s.WriteByte(')') + } + if e.Val != nil { + s.WriteString(": ") + e.Val.writeTo(s) + } +} + +// Index ... +type Index struct { + Name string + Str *String + Start *Query + End *Query + IsSlice bool +} + +func (e *Index) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Index) writeTo(s *strings.Builder) { + if l := s.Len(); l > 0 { + // ". .x" != "..x" and "0 .x" != "0.x" + if c := s.String()[l-1]; c == '.' || '0' <= c && c <= '9' { + s.WriteByte(' ') + } + } + s.WriteByte('.') + e.writeSuffixTo(s) +} + +func (e *Index) writeSuffixTo(s *strings.Builder) { + if e.Name != "" { + s.WriteString(e.Name) + } else if e.Str != nil { + e.Str.writeTo(s) + } else { + s.WriteByte('[') + if e.IsSlice { + if e.Start != nil { + e.Start.writeTo(s) + } + s.WriteByte(':') + if e.End != nil { + e.End.writeTo(s) + } + } else { + e.Start.writeTo(s) + } + s.WriteByte(']') + } +} + +func (e *Index) minify() { + if e.Str != nil { + e.Str.minify() + } + if e.Start != nil { + e.Start.minify() + } + if e.End != nil { + e.End.minify() + } +} + +func (e *Index) toIndexKey() interface{} { + if e.Name != "" { + return e.Name + } else if e.Str != nil { + if e.Str.Queries == nil { + return e.Str.Str + } + } else if !e.IsSlice { + return e.Start.toIndexKey() + } else { + var start, end interface{} + ok := true + if e.Start != nil { + start = e.Start.toIndexKey() + ok = start != nil + } + if e.End != nil && ok { + end = e.End.toIndexKey() + ok = end != nil + } + if ok { + return map[string]interface{}{"start": start, "end": end} + } + } + return nil +} + +func (e *Index) toIndices(xs []interface{}) []interface{} { + if k := e.toIndexKey(); k != nil { + return append(xs, k) + } + return nil +} + +// Func ... +type Func struct { + Name string + Args []*Query +} + +func (e *Func) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Func) writeTo(s *strings.Builder) { + s.WriteString(e.Name) + if len(e.Args) > 0 { + s.WriteByte('(') + for i, e := range e.Args { + if i > 0 { + s.WriteString("; ") + } + e.writeTo(s) + } + s.WriteByte(')') + } +} + +func (e *Func) minify() { + for _, x := range e.Args { + x.minify() + } +} + +func (e *Func) toFunc() string { + if len(e.Args) != 0 { + return "" + } + return e.Name +} + +// String ... +type String struct { + Str string + Queries []*Query +} + +func (e *String) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *String) writeTo(s *strings.Builder) { + if e.Queries == nil { + jsonEncodeString(s, e.Str) + return + } + s.WriteByte('"') + for _, e := range e.Queries { + if e.Term.Str == nil { + s.WriteString(`\`) + e.writeTo(s) + } else { + es := e.String() + s.WriteString(es[1 : len(es)-1]) + } + } + s.WriteByte('"') +} + +func (e *String) minify() { + for _, e := range e.Queries { + e.minify() + } +} + +// Object ... +type Object struct { + KeyVals []*ObjectKeyVal +} + +func (e *Object) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Object) writeTo(s *strings.Builder) { + if len(e.KeyVals) == 0 { + s.WriteString("{}") + return + } + s.WriteString("{ ") + for i, kv := range e.KeyVals { + if i > 0 { + s.WriteString(", ") + } + kv.writeTo(s) + } + s.WriteString(" }") +} + +func (e *Object) minify() { + for _, e := range e.KeyVals { + e.minify() + } +} + +// ObjectKeyVal ... +type ObjectKeyVal struct { + Key string + KeyString *String + KeyQuery *Query + Val *ObjectVal +} + +func (e *ObjectKeyVal) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *ObjectKeyVal) writeTo(s *strings.Builder) { + if e.Key != "" { + s.WriteString(e.Key) + } else if e.KeyString != nil { + e.KeyString.writeTo(s) + } else if e.KeyQuery != nil { + s.WriteByte('(') + e.KeyQuery.writeTo(s) + s.WriteByte(')') + } + if e.Val != nil { + s.WriteString(": ") + e.Val.writeTo(s) + } +} + +func (e *ObjectKeyVal) minify() { + if e.KeyString != nil { + e.KeyString.minify() + } else if e.KeyQuery != nil { + e.KeyQuery.minify() + } + if e.Val != nil { + e.Val.minify() + } +} + +// ObjectVal ... +type ObjectVal struct { + Queries []*Query +} + +func (e *ObjectVal) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *ObjectVal) writeTo(s *strings.Builder) { + for i, e := range e.Queries { + if i > 0 { + s.WriteString(" | ") + } + e.writeTo(s) + } +} + +func (e *ObjectVal) minify() { + for _, e := range e.Queries { + e.minify() + } +} + +// Array ... +type Array struct { + Query *Query +} + +func (e *Array) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Array) writeTo(s *strings.Builder) { + s.WriteByte('[') + if e.Query != nil { + e.Query.writeTo(s) + } + s.WriteByte(']') +} + +func (e *Array) minify() { + if e.Query != nil { + e.Query.minify() + } +} + +// Suffix ... +type Suffix struct { + Index *Index + Iter bool + Optional bool + Bind *Bind +} + +func (e *Suffix) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Suffix) writeTo(s *strings.Builder) { + if e.Index != nil { + if e.Index.Name != "" || e.Index.Str != nil { + e.Index.writeTo(s) + } else { + e.Index.writeSuffixTo(s) + } + } else if e.Iter { + s.WriteString("[]") + } else if e.Optional { + s.WriteByte('?') + } else if e.Bind != nil { + e.Bind.writeTo(s) + } +} + +func (e *Suffix) minify() { + if e.Index != nil { + e.Index.minify() + } else if e.Bind != nil { + e.Bind.minify() + } +} + +func (e *Suffix) toTerm() *Term { + if e.Index != nil { + return &Term{Type: TermTypeIndex, Index: e.Index} + } else if e.Iter { + return &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}} + } else { + return nil + } +} + +func (e *Suffix) toIndices(xs []interface{}) []interface{} { + if e.Index == nil { + return nil + } + return e.Index.toIndices(xs) +} + +// Bind ... +type Bind struct { + Patterns []*Pattern + Body *Query +} + +func (e *Bind) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Bind) writeTo(s *strings.Builder) { + for i, p := range e.Patterns { + if i == 0 { + s.WriteString(" as ") + p.writeTo(s) + s.WriteByte(' ') + } else { + s.WriteString("?// ") + p.writeTo(s) + s.WriteByte(' ') + } + } + s.WriteString("| ") + e.Body.writeTo(s) +} + +func (e *Bind) minify() { + e.Body.minify() +} + +// If ... +type If struct { + Cond *Query + Then *Query + Elif []*IfElif + Else *Query +} + +func (e *If) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *If) writeTo(s *strings.Builder) { + s.WriteString("if ") + e.Cond.writeTo(s) + s.WriteString(" then ") + e.Then.writeTo(s) + for _, e := range e.Elif { + s.WriteByte(' ') + e.writeTo(s) + } + if e.Else != nil { + s.WriteString(" else ") + e.Else.writeTo(s) + } + s.WriteString(" end") +} + +func (e *If) minify() { + e.Cond.minify() + e.Then.minify() + for _, x := range e.Elif { + x.minify() + } + if e.Else != nil { + e.Else.minify() + } +} + +// IfElif ... +type IfElif struct { + Cond *Query + Then *Query +} + +func (e *IfElif) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *IfElif) writeTo(s *strings.Builder) { + s.WriteString("elif ") + e.Cond.writeTo(s) + s.WriteString(" then ") + e.Then.writeTo(s) +} + +func (e *IfElif) minify() { + e.Cond.minify() + e.Then.minify() +} + +// Try ... +type Try struct { + Body *Query + Catch *Query +} + +func (e *Try) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Try) writeTo(s *strings.Builder) { + s.WriteString("try ") + e.Body.writeTo(s) + if e.Catch != nil { + s.WriteString(" catch ") + e.Catch.writeTo(s) + } +} + +func (e *Try) minify() { + e.Body.minify() + if e.Catch != nil { + e.Catch.minify() + } +} + +// Reduce ... +type Reduce struct { + Term *Term + Pattern *Pattern + Start *Query + Update *Query +} + +func (e *Reduce) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Reduce) writeTo(s *strings.Builder) { + s.WriteString("reduce ") + e.Term.writeTo(s) + s.WriteString(" as ") + e.Pattern.writeTo(s) + s.WriteString(" (") + e.Start.writeTo(s) + s.WriteString("; ") + e.Update.writeTo(s) + s.WriteByte(')') +} + +func (e *Reduce) minify() { + e.Term.minify() + e.Start.minify() + e.Update.minify() +} + +// Foreach ... +type Foreach struct { + Term *Term + Pattern *Pattern + Start *Query + Update *Query + Extract *Query +} + +func (e *Foreach) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Foreach) writeTo(s *strings.Builder) { + s.WriteString("foreach ") + e.Term.writeTo(s) + s.WriteString(" as ") + e.Pattern.writeTo(s) + s.WriteString(" (") + e.Start.writeTo(s) + s.WriteString("; ") + e.Update.writeTo(s) + if e.Extract != nil { + s.WriteString("; ") + e.Extract.writeTo(s) + } + s.WriteByte(')') +} + +func (e *Foreach) minify() { + e.Term.minify() + e.Start.minify() + e.Update.minify() + if e.Extract != nil { + e.Extract.minify() + } +} + +// Label ... +type Label struct { + Ident string + Body *Query +} + +func (e *Label) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *Label) writeTo(s *strings.Builder) { + s.WriteString("label ") + s.WriteString(e.Ident) + s.WriteString(" | ") + e.Body.writeTo(s) +} + +func (e *Label) minify() { + e.Body.minify() +} + +// ConstTerm ... +type ConstTerm struct { + Object *ConstObject + Array *ConstArray + Number string + Str string + Null bool + True bool + False bool +} + +func (e *ConstTerm) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *ConstTerm) writeTo(s *strings.Builder) { + if e.Object != nil { + e.Object.writeTo(s) + } else if e.Array != nil { + e.Array.writeTo(s) + } else if e.Number != "" { + s.WriteString(e.Number) + } else if e.Null { + s.WriteString("null") + } else if e.True { + s.WriteString("true") + } else if e.False { + s.WriteString("false") + } else { + jsonEncodeString(s, e.Str) + } +} + +func (e *ConstTerm) toValue() interface{} { + if e.Object != nil { + return e.Object.ToValue() + } else if e.Array != nil { + return e.Array.toValue() + } else if e.Number != "" { + return toNumber(e.Number) + } else if e.Null { + return nil + } else if e.True { + return true + } else if e.False { + return false + } else { + return e.Str + } +} + +// ConstObject ... +type ConstObject struct { + KeyVals []*ConstObjectKeyVal +} + +func (e *ConstObject) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *ConstObject) writeTo(s *strings.Builder) { + if len(e.KeyVals) == 0 { + s.WriteString("{}") + return + } + s.WriteString("{ ") + for i, kv := range e.KeyVals { + if i > 0 { + s.WriteString(", ") + } + kv.writeTo(s) + } + s.WriteString(" }") +} + +// ToValue converts the object to map[string]interface{}. +func (e *ConstObject) ToValue() map[string]interface{} { + if e == nil { + return nil + } + v := make(map[string]interface{}, len(e.KeyVals)) + for _, e := range e.KeyVals { + key := e.Key + if key == "" { + key = e.KeyString + } + v[key] = e.Val.toValue() + } + return v +} + +// ConstObjectKeyVal ... +type ConstObjectKeyVal struct { + Key string + KeyString string + Val *ConstTerm +} + +func (e *ConstObjectKeyVal) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *ConstObjectKeyVal) writeTo(s *strings.Builder) { + if e.Key != "" { + s.WriteString(e.Key) + } else { + s.WriteString(e.KeyString) + } + s.WriteString(": ") + e.Val.writeTo(s) +} + +// ConstArray ... +type ConstArray struct { + Elems []*ConstTerm +} + +func (e *ConstArray) String() string { + var s strings.Builder + e.writeTo(&s) + return s.String() +} + +func (e *ConstArray) writeTo(s *strings.Builder) { + s.WriteByte('[') + for i, e := range e.Elems { + if i > 0 { + s.WriteString(", ") + } + e.writeTo(s) + } + s.WriteByte(']') +} + +func (e *ConstArray) toValue() []interface{} { + v := make([]interface{}, len(e.Elems)) + for i, e := range e.Elems { + v[i] = e.toValue() + } + return v +} diff --git a/vendor/github.com/itchyny/gojq/release.go b/vendor/github.com/itchyny/gojq/release.go new file mode 100644 index 00000000..1144485e --- /dev/null +++ b/vendor/github.com/itchyny/gojq/release.go @@ -0,0 +1,16 @@ +//go:build !gojq_debug +// +build !gojq_debug + +package gojq + +type codeinfo struct{} + +func (c *compiler) appendCodeInfo(interface{}) {} + +func (c *compiler) deleteCodeInfo(string) {} + +func (env *env) debugCodes() {} + +func (env *env) debugState(int, bool) {} + +func (env *env) debugForks(int, string) {} diff --git a/vendor/github.com/itchyny/gojq/scope_stack.go b/vendor/github.com/itchyny/gojq/scope_stack.go new file mode 100644 index 00000000..e140ca15 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/scope_stack.go @@ -0,0 +1,52 @@ +package gojq + +type scopeStack struct { + data []scopeBlock + index int + limit int +} + +type scopeBlock struct { + value scope + next int +} + +func newScopeStack() *scopeStack { + return &scopeStack{index: -1, limit: -1} +} + +func (s *scopeStack) push(v scope) { + b := scopeBlock{v, s.index} + i := s.index + 1 + if i <= s.limit { + i = s.limit + 1 + } + s.index = i + if i < len(s.data) { + s.data[i] = b + } else { + s.data = append(s.data, b) + } +} + +func (s *scopeStack) pop() scope { + b := s.data[s.index] + s.index = b.next + return b.value +} + +func (s *scopeStack) empty() bool { + return s.index < 0 +} + +func (s *scopeStack) save() (index, limit int) { + index, limit = s.index, s.limit + if s.index > s.limit { + s.limit = s.index + } + return +} + +func (s *scopeStack) restore(index, limit int) { + s.index, s.limit = index, limit +} diff --git a/vendor/github.com/itchyny/gojq/stack.go b/vendor/github.com/itchyny/gojq/stack.go new file mode 100644 index 00000000..50445fc2 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/stack.go @@ -0,0 +1,56 @@ +package gojq + +type stack struct { + data []block + index int + limit int +} + +type block struct { + value interface{} + next int +} + +func newStack() *stack { + return &stack{index: -1, limit: -1} +} + +func (s *stack) push(v interface{}) { + b := block{v, s.index} + i := s.index + 1 + if i <= s.limit { + i = s.limit + 1 + } + s.index = i + if i < len(s.data) { + s.data[i] = b + } else { + s.data = append(s.data, b) + } +} + +func (s *stack) pop() interface{} { + b := s.data[s.index] + s.index = b.next + return b.value +} + +func (s *stack) top() interface{} { + return s.data[s.index].value +} + +func (s *stack) empty() bool { + return s.index < 0 +} + +func (s *stack) save() (index, limit int) { + index, limit = s.index, s.limit + if s.index > s.limit { + s.limit = s.index + } + return +} + +func (s *stack) restore(index, limit int) { + s.index, s.limit = index, limit +} diff --git a/vendor/github.com/itchyny/gojq/term_type.go b/vendor/github.com/itchyny/gojq/term_type.go new file mode 100644 index 00000000..1670948c --- /dev/null +++ b/vendor/github.com/itchyny/gojq/term_type.go @@ -0,0 +1,77 @@ +package gojq + +// TermType represents the type of Term. +type TermType int + +// TermType list. +const ( + TermTypeIdentity TermType = iota + 1 + TermTypeRecurse + TermTypeNull + TermTypeTrue + TermTypeFalse + TermTypeIndex + TermTypeFunc + TermTypeObject + TermTypeArray + TermTypeNumber + TermTypeUnary + TermTypeFormat + TermTypeString + TermTypeIf + TermTypeTry + TermTypeReduce + TermTypeForeach + TermTypeLabel + TermTypeBreak + TermTypeQuery +) + +// GoString implements GoStringer. +func (termType TermType) GoString() (str string) { + defer func() { str = "gojq." + str }() + switch termType { + case TermTypeIdentity: + return "TermTypeIdentity" + case TermTypeRecurse: + return "TermTypeRecurse" + case TermTypeNull: + return "TermTypeNull" + case TermTypeTrue: + return "TermTypeTrue" + case TermTypeFalse: + return "TermTypeFalse" + case TermTypeIndex: + return "TermTypeIndex" + case TermTypeFunc: + return "TermTypeFunc" + case TermTypeObject: + return "TermTypeObject" + case TermTypeArray: + return "TermTypeArray" + case TermTypeNumber: + return "TermTypeNumber" + case TermTypeUnary: + return "TermTypeUnary" + case TermTypeFormat: + return "TermTypeFormat" + case TermTypeString: + return "TermTypeString" + case TermTypeIf: + return "TermTypeIf" + case TermTypeTry: + return "TermTypeTry" + case TermTypeReduce: + return "TermTypeReduce" + case TermTypeForeach: + return "TermTypeForeach" + case TermTypeLabel: + return "TermTypeLabel" + case TermTypeBreak: + return "TermTypeBreak" + case TermTypeQuery: + return "TermTypeQuery" + default: + panic(termType) + } +} diff --git a/vendor/github.com/itchyny/gojq/type.go b/vendor/github.com/itchyny/gojq/type.go new file mode 100644 index 00000000..578a6f4c --- /dev/null +++ b/vendor/github.com/itchyny/gojq/type.go @@ -0,0 +1,30 @@ +package gojq + +import ( + "fmt" + "math/big" +) + +// TypeOf returns the jq-flavored type name of v. +// +// This method is used by built-in type/0 function, and accepts only limited +// types (nil, bool, int, float64, *big.Int, string, []interface{}, +// and map[string]interface{}). +func TypeOf(v interface{}) string { + switch v.(type) { + case nil: + return "null" + case bool: + return "boolean" + case int, float64, *big.Int: + return "number" + case string: + return "string" + case []interface{}: + return "array" + case map[string]interface{}: + return "object" + default: + panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v)) + } +} diff --git a/vendor/github.com/itchyny/timefmt-go/CHANGELOG.md b/vendor/github.com/itchyny/timefmt-go/CHANGELOG.md new file mode 100644 index 00000000..52b37d05 --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog +## [v0.1.3](https://github.com/itchyny/timefmt-go/compare/v0.1.2..v0.1.3) (2021-04-14) +* implement `ParseInLocation` for configuring the default location + +## [v0.1.2](https://github.com/itchyny/timefmt-go/compare/v0.1.1..v0.1.2) (2021-02-22) +* implement parsing/formatting time zone offset with colons (`%:z`, `%::z`, `%:::z`) +* recognize `Z` as UTC on parsing time zone offset (`%z`) +* fix padding on formatting time zone offset (`%z`) + +## [v0.1.1](https://github.com/itchyny/timefmt-go/compare/v0.1.0..v0.1.1) (2020-09-01) +* fix overflow check in 32-bit architecture + +## [v0.1.0](https://github.com/itchyny/timefmt-go/compare/2c02364..v0.1.0) (2020-08-16) +* initial implementation diff --git a/vendor/github.com/itchyny/timefmt-go/LICENSE b/vendor/github.com/itchyny/timefmt-go/LICENSE new file mode 100644 index 00000000..4d650fa8 --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020,2021 itchyny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/itchyny/timefmt-go/Makefile b/vendor/github.com/itchyny/timefmt-go/Makefile new file mode 100644 index 00000000..bacef7bf --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/Makefile @@ -0,0 +1,21 @@ +GOBIN ?= $(shell go env GOPATH)/bin +export GO111MODULE=on + +.PHONY: all +all: test + +.PHONY: test +test: + go test -v ./... + +.PHONY: lint +lint: $(GOBIN)/golint + go vet ./... + golint -set_exit_status ./... + +$(GOBIN)/golint: + cd && go get golang.org/x/lint/golint + +.PHONY: clean +clean: + go clean diff --git a/vendor/github.com/itchyny/timefmt-go/README.md b/vendor/github.com/itchyny/timefmt-go/README.md new file mode 100644 index 00000000..078b1e1a --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/README.md @@ -0,0 +1,68 @@ +# timefmt-go +[![CI Status](https://github.com/itchyny/timefmt-go/workflows/CI/badge.svg)](https://github.com/itchyny/timefmt-go/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/itchyny/timefmt-go)](https://goreportcard.com/report/github.com/itchyny/timefmt-go) +[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/itchyny/timefmt-go/blob/main/LICENSE) +[![release](https://img.shields.io/github/release/itchyny/timefmt-go/all.svg)](https://github.com/itchyny/timefmt-go/releases) +[![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/timefmt-go)](https://pkg.go.dev/github.com/itchyny/timefmt-go) + +### Efficient time formatting library (strftime, strptime) for Golang +This is a Go language package for formatting and parsing date time strings. + +```go +package main + +import ( + "fmt" + "log" + + "github.com/itchyny/timefmt-go" +) + +func main() { + t, err := timefmt.Parse("2020/07/24 09:07:29", "%Y/%m/%d %H:%M:%S") + if err != nil { + log.Fatal(err) + } + fmt.Println(t) // 2020-07-24 09:07:29 +0000 UTC + + str := timefmt.Format(t, "%Y/%m/%d %H:%M:%S") + fmt.Println(str) // 2020/07/24 09:07:29 + + str = timefmt.Format(t, "%a, %d %b %Y %T %z") + fmt.Println(str) // Fri, 24 Jul 2020 09:07:29 +0000 +} +``` + +Please refer to [`man 3 strftime`](https://linux.die.net/man/3/strftime) and +[`man 3 strptime`](https://linux.die.net/man/3/strptime) for formatters. +Note that `E` and `O` modifier characters are not supported. + +## Comparison to other libraries +- This library + - provides both formatting and parsing functions in pure Go language, + - depends only on the Go standard libraries not to grows up the module file. +- `Format` (`strftime`) implements glibc extensions including + - width specifier like `%10A, %10B %2k:%M`, + - omitting padding modifier like `%-y-%-m-%-d`, + - space padding modifier like `%_y-%_m-%_d`, + - upper case modifier like `%^a %^b`, + - swapping case modifier like `%#Z`, + - time zone offset modifier like `%:z %::z %:::z`, + - and its performance is very good. +- `AppendFormat` is provided for reducing allocations. +- `Parse` (`strptime`) allows to parse + - composed directives like `%F %T`, + - century years like `%C %y`, + - week names like `%A` `%a` (parsed results are discarded). +- `ParseInLocation` is provided for configuring the default location. + +![](https://user-images.githubusercontent.com/375258/88606920-de475c80-d0b8-11ea-8d40-cbfee9e35c2e.jpg) + +## Bug Tracker +Report bug at [Issues・itchyny/timefmt-go - GitHub](https://github.com/itchyny/timefmt-go/issues). + +## Author +itchyny (https://github.com/itchyny) + +## License +This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/itchyny/timefmt-go/format.go b/vendor/github.com/itchyny/timefmt-go/format.go new file mode 100644 index 00000000..1d9b3672 --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/format.go @@ -0,0 +1,537 @@ +package timefmt + +import ( + "strconv" + "time" +) + +// Format time to string using the format. +func Format(t time.Time, format string) string { + return string(AppendFormat(make([]byte, 0, 64), t, format)) +} + +// AppendFormat appends formatted time to the bytes. +// You can use this method to reduce allocations. +func AppendFormat(buf []byte, t time.Time, format string) []byte { + year, month, day := t.Date() + hour, min, sec := t.Clock() + var width, colons int + var padding byte + var pending string + var upper, swap bool + for i := 0; i < len(format); i++ { + if b := format[i]; b == '%' { + if i++; i == len(format) { + buf = append(buf, '%') + break + } + b, width, padding, upper, swap = format[i], 0, '0', false, false + L: + switch b { + case '-': + if pending != "" { + buf = append(buf, '-') + break + } + if i++; i == len(format) { + goto K + } + padding = ^paddingMask + b = format[i] + goto L + case '_': + if i++; i == len(format) { + goto K + } + padding = ' ' | ^paddingMask + b = format[i] + goto L + case '^': + if i++; i == len(format) { + goto K + } + upper = true + b = format[i] + goto L + case '#': + if i++; i == len(format) { + goto K + } + swap = true + b = format[i] + goto L + case '0': + if i++; i == len(format) { + goto K + } + padding = '0' | ^paddingMask + b = format[i] + goto L + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + width = int(b & 0x0F) + const maxWidth = 1024 + for i++; i < len(format); i++ { + b = format[i] + if b <= '9' && '0' <= b { + width = width*10 + int(b&0x0F) + if width >= int((^uint(0)>>1)/10) { + width = maxWidth + } + } else { + break + } + } + if width > maxWidth { + width = maxWidth + } + if padding == ^paddingMask { + padding = ' ' | ^paddingMask + } + if i == len(format) { + goto K + } + goto L + case 'Y': + if width == 0 { + width = 4 + } + buf = appendInt(buf, year, width, padding) + case 'y': + if width < 2 { + width = 2 + } + buf = appendInt(buf, year%100, width, padding) + case 'C': + if width < 2 { + width = 2 + } + buf = appendInt(buf, year/100, width, padding) + case 'g': + if width < 2 { + width = 2 + } + year, _ := t.ISOWeek() + buf = appendInt(buf, year%100, width, padding) + case 'G': + if width == 0 { + width = 4 + } + year, _ := t.ISOWeek() + buf = appendInt(buf, year, width, padding) + case 'm': + if width < 2 { + width = 2 + } + buf = appendInt(buf, int(month), width, padding) + case 'B': + buf = appendString(buf, longMonthNames[month-1], width, padding, upper, swap) + case 'b', 'h': + buf = appendString(buf, shortMonthNames[month-1], width, padding, upper, swap) + case 'A': + buf = appendString(buf, longWeekNames[t.Weekday()], width, padding, upper, swap) + case 'a': + buf = appendString(buf, shortWeekNames[t.Weekday()], width, padding, upper, swap) + case 'w': + for ; width > 1; width-- { + buf = append(buf, padding&paddingMask) + } + buf = append(buf, '0'+byte(t.Weekday())) + case 'u': + w := int(t.Weekday()) + if w == 0 { + w = 7 + } + for ; width > 1; width-- { + buf = append(buf, padding&paddingMask) + } + buf = append(buf, '0'+byte(w)) + case 'V': + if width < 2 { + width = 2 + } + _, week := t.ISOWeek() + buf = appendInt(buf, week, width, padding) + case 'U': + if width < 2 { + width = 2 + } + week := (t.YearDay() + 6 - int(t.Weekday())) / 7 + buf = appendInt(buf, week, width, padding) + case 'W': + if width < 2 { + width = 2 + } + week := t.YearDay() + if int(t.Weekday()) > 0 { + week -= int(t.Weekday()) - 7 + } + week /= 7 + buf = appendInt(buf, week, width, padding) + case 'e': + if padding < ^paddingMask { + padding = ' ' + } + fallthrough + case 'd': + if width < 2 { + width = 2 + } + buf = appendInt(buf, day, width, padding) + case 'j': + if width < 3 { + width = 3 + } + buf = appendInt(buf, t.YearDay(), width, padding) + case 'k': + if padding < ^paddingMask { + padding = ' ' + } + fallthrough + case 'H': + if width < 2 { + width = 2 + } + buf = appendInt(buf, hour, width, padding) + case 'l': + if width < 2 { + width = 2 + } + if padding < ^paddingMask { + padding = ' ' + } + h := hour + if h > 12 { + h -= 12 + } + buf = appendInt(buf, h, width, padding) + case 'I': + if width < 2 { + width = 2 + } + h := hour + if h > 12 { + h -= 12 + } else if h == 0 { + h = 12 + } + buf = appendInt(buf, h, width, padding) + case 'p': + if hour < 12 { + buf = appendString(buf, "AM", width, padding, upper, swap) + } else { + buf = appendString(buf, "PM", width, padding, upper, swap) + } + case 'P': + if hour < 12 { + buf = appendString(buf, "am", width, padding, upper, swap) + } else { + buf = appendString(buf, "pm", width, padding, upper, swap) + } + case 'M': + if width < 2 { + width = 2 + } + buf = appendInt(buf, min, width, padding) + case 'S': + if width < 2 { + width = 2 + } + buf = appendInt(buf, sec, width, padding) + case 's': + if padding < ^paddingMask { + padding = ' ' + } + buf = appendInt(buf, int(t.Unix()), width, padding) + case 'f': + if width == 0 { + width = 6 + } + buf = appendInt(buf, t.Nanosecond()/1000, width, padding) + case 'Z', 'z': + name, offset := t.Zone() + if b == 'Z' && name != "" { + buf = appendString(buf, name, width, padding, upper, swap) + break + } + i := len(buf) + if padding != ^paddingMask { + for ; width > 1; width-- { + buf = append(buf, padding&paddingMask) + } + } + j := len(buf) + if offset < 0 { + buf = append(buf, '-') + offset = -offset + } else { + buf = append(buf, '+') + } + k := len(buf) + buf = appendInt(buf, offset/3600, 2, padding) + if buf[k] == ' ' { + buf[k-1], buf[k] = buf[k], buf[k-1] + } + if k = offset % 3600; colons <= 2 || k != 0 { + if colons != 0 { + buf = append(buf, ':') + } + buf = appendInt(buf, k/60, 2, '0') + if k %= 60; colons == 2 || colons == 3 && k != 0 { + buf = append(buf, ':') + buf = appendInt(buf, k, 2, '0') + } + } + colons = 0 + if i != j { + l := len(buf) + k = j + 1 - (l - j) + if k < i { + l = j + 1 + i - k + k = i + } else { + l = j + 1 + } + copy(buf[k:], buf[j:]) + buf = buf[:l] + if padding&paddingMask == '0' { + for ; k > i; k-- { + buf[k-1], buf[k] = buf[k], buf[k-1] + } + } + } + case ':': + if pending != "" { + buf = append(buf, ':') + } else { + colons = 1 + M: + for i++; i < len(format); i++ { + switch format[i] { + case ':': + colons++ + case 'z': + if colons > 3 { + i++ + break M + } + b = 'z' + goto L + default: + break M + } + } + buf = appendLast(buf, format[:i], width, padding) + i-- + colons = 0 + } + case 't': + buf = appendString(buf, "\t", width, padding, false, false) + case 'n': + buf = appendString(buf, "\n", width, padding, false, false) + case '%': + buf = appendString(buf, "%", width, padding, false, false) + default: + if pending == "" { + var ok bool + if pending, ok = compositions[b]; ok { + swap = false + break + } + buf = appendLast(buf, format[:i], width-1, padding) + } + buf = append(buf, b) + } + if pending != "" { + b, pending, width, padding = pending[0], pending[1:], 0, '0' + goto L + } + } else { + buf = append(buf, b) + } + } + return buf +K: + return appendLast(buf, format, width, padding) +} + +func appendInt(buf []byte, num, width int, padding byte) []byte { + if padding != ^paddingMask { + padding &= paddingMask + switch width { + case 2: + if num < 10 { + buf = append(buf, padding) + goto L1 + } else if num < 100 { + goto L2 + } else if num < 1000 { + goto L3 + } else if num < 10000 { + goto L4 + } + case 4: + if num < 1000 { + buf = append(buf, padding) + if num < 100 { + buf = append(buf, padding) + if num < 10 { + buf = append(buf, padding) + goto L1 + } + goto L2 + } + goto L3 + } else if num < 10000 { + goto L4 + } + default: + i := len(buf) + for ; width > 1; width-- { + buf = append(buf, padding) + } + j := len(buf) + buf = strconv.AppendInt(buf, int64(num), 10) + l := len(buf) + if j+1 == l || i == j { + return buf + } + k := j + 1 - (l - j) + if k < i { + l = j + 1 + i - k + k = i + } else { + l = j + 1 + } + copy(buf[k:], buf[j:]) + return buf[:l] + } + } + if num < 100 { + if num < 10 { + goto L1 + } + goto L2 + } else if num < 10000 { + if num < 1000 { + goto L3 + } + goto L4 + } + return strconv.AppendInt(buf, int64(num), 10) +L4: + buf = append(buf, byte(num/1000)|'0') + num %= 1000 +L3: + buf = append(buf, byte(num/100)|'0') + num %= 100 +L2: + buf = append(buf, byte(num/10)|'0') + num %= 10 +L1: + return append(buf, byte(num)|'0') +} + +func appendString(buf []byte, str string, width int, padding byte, upper, swap bool) []byte { + if width > len(str) && padding != ^paddingMask { + if padding < ^paddingMask { + padding = ' ' + } else { + padding &= paddingMask + } + for width -= len(str); width > 0; width-- { + buf = append(buf, padding) + } + } + switch { + case swap: + if str[len(str)-1] < 'a' { + for _, b := range []byte(str) { + buf = append(buf, b|0x20) + } + break + } + fallthrough + case upper: + for _, b := range []byte(str) { + buf = append(buf, b&0x5F) + } + default: + buf = append(buf, str...) + } + return buf +} + +func appendLast(buf []byte, format string, width int, padding byte) []byte { + for i := len(format) - 1; i >= 0; i-- { + if format[i] == '%' { + buf = appendString(buf, format[i:], width, padding, false, false) + break + } + } + return buf +} + +const paddingMask byte = 0x7F + +var longMonthNames = []string{ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +} + +var shortMonthNames = []string{ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", +} + +var longWeekNames = []string{ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +} + +var shortWeekNames = []string{ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", +} + +var compositions = map[byte]string{ + 'c': "a b e H:M:S Y", + '+': "a b e H:M:S Z Y", + 'F': "Y-m-d", + 'D': "m/d/y", + 'x': "m/d/y", + 'v': "e-b-Y", + 'T': "H:M:S", + 'X': "H:M:S", + 'r': "I:M:S p", + 'R': "H:M", +} diff --git a/vendor/github.com/itchyny/timefmt-go/parse.go b/vendor/github.com/itchyny/timefmt-go/parse.go new file mode 100644 index 00000000..2d2b5f4d --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/parse.go @@ -0,0 +1,392 @@ +package timefmt + +import ( + "errors" + "fmt" + "time" +) + +// Parse time string using the format. +func Parse(source, format string) (t time.Time, err error) { + return parse(source, format, time.UTC, time.Local) +} + +// ParseInLocation parses time string with the default location. +// The location is also used to parse the time zone name (%Z). +func ParseInLocation(source, format string, loc *time.Location) (t time.Time, err error) { + return parse(source, format, loc, loc) +} + +func parse(source, format string, loc, base *time.Location) (t time.Time, err error) { + year, month, day, hour, min, sec, nsec := 1900, 1, 1, 0, 0, 0, 0 + defer func() { + if err != nil { + err = fmt.Errorf("failed to parse %q with %q: %w", source, format, err) + } + }() + var j, century, yday, colons int + var pm bool + var pending string + for i, l := 0, len(source); i < len(format); i++ { + if b := format[i]; b == '%' { + i++ + if i == len(format) { + err = errors.New("stray %") + return + } + b = format[i] + L: + switch b { + case 'Y': + if year, j, err = parseNumber(source, j, 4, 'Y'); err != nil { + return + } + case 'y': + if year, j, err = parseNumber(source, j, 2, 'y'); err != nil { + return + } + if year < 69 { + year += 2000 + } else { + year += 1900 + } + case 'C': + if century, j, err = parseNumber(source, j, 2, 'C'); err != nil { + return + } + case 'g': + if year, j, err = parseNumber(source, j, 2, b); err != nil { + return + } + year += 2000 + case 'G': + if year, j, err = parseNumber(source, j, 4, b); err != nil { + return + } + case 'm': + if month, j, err = parseNumber(source, j, 2, 'm'); err != nil { + return + } + case 'B': + if month, j, err = lookup(source, j, longMonthNames, 'B'); err != nil { + return + } + case 'b', 'h': + if month, j, err = lookup(source, j, shortMonthNames, b); err != nil { + return + } + case 'A': + if _, j, err = lookup(source, j, longWeekNames, 'A'); err != nil { + return + } + case 'a': + if _, j, err = lookup(source, j, shortWeekNames, 'a'); err != nil { + return + } + case 'w': + if j >= l || source[j] < '0' || '6' < source[j] { + err = parseFormatError(b) + return + } + j++ + case 'u': + if j >= l || source[j] < '1' || '7' < source[j] { + err = parseFormatError(b) + return + } + j++ + case 'V', 'U', 'W': + if _, j, err = parseNumber(source, j, 2, b); err != nil { + return + } + case 'e': + if j < l && source[j] == ' ' { + j++ + } + fallthrough + case 'd': + if day, j, err = parseNumber(source, j, 2, b); err != nil { + return + } + case 'j': + if yday, j, err = parseNumber(source, j, 3, 'j'); err != nil { + return + } + case 'k': + if j < l && source[j] == ' ' { + j++ + } + fallthrough + case 'H': + if hour, j, err = parseNumber(source, j, 2, b); err != nil { + return + } + case 'l': + if j < l && source[j] == ' ' { + j++ + } + fallthrough + case 'I': + if hour, j, err = parseNumber(source, j, 2, b); err != nil { + return + } + if hour == 12 { + hour = 0 + } + case 'p', 'P': + var ampm int + if ampm, j, err = lookup(source, j, []string{"AM", "PM"}, 'p'); err != nil { + return + } + pm = ampm == 2 + case 'M': + if min, j, err = parseNumber(source, j, 2, 'M'); err != nil { + return + } + case 'S': + if sec, j, err = parseNumber(source, j, 2, 'S'); err != nil { + return + } + case 's': + var unix int + if unix, j, err = parseNumber(source, j, 10, 's'); err != nil { + return + } + t = time.Unix(int64(unix), 0).In(time.UTC) + var mon time.Month + year, mon, day = t.Date() + hour, min, sec = t.Clock() + month = int(mon) + case 'f': + var msec, k, d int + if msec, k, err = parseNumber(source, j, 6, 'f'); err != nil { + return + } + nsec = msec * 1000 + for j, d = k, k-j; d < 6; d++ { + nsec *= 10 + } + case 'Z': + k := j + for ; k < l; k++ { + if c := source[k]; c < 'A' || 'Z' < c { + break + } + } + t, err = time.ParseInLocation("MST", source[j:k], base) + if err != nil { + err = fmt.Errorf(`cannot parse %q with "%%Z"`, source[j:k]) + return + } + loc = t.Location() + j = k + case 'z': + if j >= l { + err = parseZFormatError(colons) + return + } + sign := 1 + switch source[j] { + case '-': + sign = -1 + fallthrough + case '+': + var hour, min, sec, k int + if hour, k, _ = parseNumber(source, j+1, 2, 'z'); k != j+3 { + err = parseZFormatError(colons) + return + } + if j = k; j >= l || source[j] != ':' { + switch colons { + case 1: + err = errors.New("expected ':' for %:z") + return + case 2: + err = errors.New("expected ':' for %::z") + return + } + } else if j++; colons == 0 { + colons = 4 + } + if min, k, _ = parseNumber(source, j, 2, 'z'); k != j+2 { + if colons == 0 { + k = j + } else { + err = parseZFormatError(colons & 3) + return + } + } + if j = k; colons > 1 { + if j >= l || source[j] != ':' { + if colons == 2 { + err = errors.New("expected ':' for %::z") + return + } + } else if sec, k, _ = parseNumber(source, j+1, 2, 'z'); k != j+3 { + if colons == 2 { + err = parseZFormatError(colons) + return + } + } else { + j = k + } + } + loc, colons = time.FixedZone("", sign*((hour*60+min)*60+sec)), 0 + case 'Z': + loc, colons, j = time.UTC, 0, j+1 + default: + err = parseZFormatError(colons) + return + } + case ':': + if pending != "" { + if j >= l || source[j] != b { + err = expectedFormatError(b) + return + } + j++ + } else { + if i++; i == len(format) { + err = errors.New(`expected 'z' after "%:"`) + return + } else if b = format[i]; b == 'z' { + colons = 1 + } else if b != ':' { + err = errors.New(`expected 'z' after "%:"`) + return + } else if i++; i == len(format) { + err = errors.New(`expected 'z' after "%::"`) + return + } else if b = format[i]; b == 'z' { + colons = 2 + } else { + err = errors.New(`expected 'z' after "%::"`) + return + } + goto L + } + case 't', 'n': + k := j + K: + for ; k < l; k++ { + switch source[k] { + case ' ', '\t', '\n', '\v', '\f', '\r': + default: + break K + } + } + if k == j { + err = fmt.Errorf("expected a space for %%%c", b) + return + } + j = k + case '%': + if j >= l || source[j] != b { + err = expectedFormatError(b) + return + } + j++ + default: + if pending == "" { + var ok bool + if pending, ok = compositions[b]; ok { + break + } + err = fmt.Errorf(`unexpected format: "%%%c"`, b) + return + } + if j >= l || source[j] != b { + err = expectedFormatError(b) + return + } + j++ + } + if pending != "" { + b, pending = pending[0], pending[1:] + goto L + } + } else if j >= len(source) || source[j] != b { + err = expectedFormatError(b) + return + } else { + j++ + } + } + if j < len(source) { + err = fmt.Errorf("unconverted string: %q", source[j:]) + return + } + if pm { + hour += 12 + } + if century > 0 { + year = century*100 + year%100 + } + if yday > 0 { + return time.Date(year, time.January, 1, hour, min, sec, nsec, loc).AddDate(0, 0, yday-1), nil + } + return time.Date(year, time.Month(month), day, hour, min, sec, nsec, loc), nil +} + +type parseFormatError byte + +func (err parseFormatError) Error() string { + return fmt.Sprintf("cannot parse %%%c", byte(err)) +} + +type expectedFormatError byte + +func (err expectedFormatError) Error() string { + return fmt.Sprintf("expected %q", byte(err)) +} + +type parseZFormatError int + +func (err parseZFormatError) Error() string { + switch int(err) { + case 0: + return "cannot parse %z" + case 1: + return "cannot parse %:z" + default: + return "cannot parse %::z" + } +} + +func parseNumber(source string, min, size int, format byte) (int, int, error) { + var val int + if l := len(source); min+size > l { + size = l + } else { + size += min + } + i := min + for ; i < size; i++ { + if b := source[i]; '0' <= b && b <= '9' { + val = val*10 + int(b&0x0F) + } else { + break + } + } + if i == min { + return 0, 0, parseFormatError(format) + } + return val, i, nil +} + +func lookup(source string, min int, candidates []string, format byte) (int, int, error) { +L: + for i, xs := range candidates { + j := min + for k := 0; k < len(xs); k, j = k+1, j+1 { + if j >= len(source) { + continue L + } + if x, y := xs[k], source[j]; x != y && x|('a'-'A') != y|('a'-'A') { + continue L + } + } + return i + 1, j, nil + } + return 0, 0, parseFormatError(format) +} diff --git a/vendor/github.com/openshift/assisted-service/api/common/zz_generated.deepcopy.go b/vendor/github.com/openshift/assisted-service/api/common/zz_generated.deepcopy.go index 47033984..5eb27ce2 100644 --- a/vendor/github.com/openshift/assisted-service/api/common/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/assisted-service/api/common/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright 2020. @@ -67,7 +66,8 @@ func (in ValidationsStatus) DeepCopyInto(out *ValidationsStatus) { if val == nil { (*out)[key] = nil } else { - in, out := &val, &outVal + inVal := (*in)[key] + in, out := &inVal, &outVal *out = make(ValidationResults, len(*in)) copy(*out, *in) } diff --git a/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/agentclusterinstall_types.go b/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/agentclusterinstall_types.go index ed63f0b8..69fe63c7 100644 --- a/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/agentclusterinstall_types.go +++ b/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/agentclusterinstall_types.go @@ -8,11 +8,11 @@ import ( ) const ( - ClusterSpecSyncedCondition string = "SpecSynced" + ClusterSpecSyncedCondition hivev1.ClusterInstallConditionType = "SpecSynced" - ClusterCompletedCondition string = hivev1.ClusterInstallCompleted + ClusterCompletedCondition = hivev1.ClusterInstallCompleted - ClusterRequirementsMetCondition string = hivev1.ClusterInstallRequirementsMet + ClusterRequirementsMetCondition = hivev1.ClusterInstallRequirementsMet ClusterReadyReason string = "ClusterIsReady" ClusterReadyMsg string = "The cluster is ready to begin the installation" ClusterNotReadyReason string = "ClusterNotReady" @@ -22,27 +22,25 @@ const ( ClusterInstallationStoppedReason string = "ClusterInstallationStopped" ClusterInstallationStoppedMsg string = "The cluster installation stopped" ClusterInsufficientAgentsReason string = "InsufficientAgents" - ClusterInsufficientAgentsMsg string = "The cluster currently requires %d agents but only %d have registered" + ClusterInsufficientAgentsMsg string = "The cluster currently requires exactly %d master agents, %d arbiter agents and %d worker agents, but currently registered %d master agents, %d arbiter agents and %d worker agents" ClusterUnapprovedAgentsReason string = "UnapprovedAgents" ClusterUnapprovedAgentsMsg string = "The installation is pending on the approval of %d agents" ClusterUnsyncedAgentsReason string = "UnsyncedAgents" ClusterUnsyncedAgentsMsg string = "The cluster currently has %d agents with spec error" - ClusterAdditionalAgentsReason string = "AdditionalAgents" - ClusterAdditionalAgentsMsg string = "The cluster currently requires exactly %d agents but have %d registered" - ClusterValidatedCondition string = "Validated" - ClusterValidationsOKMsg string = "The cluster's validations are passing" - ClusterValidationsUnknownMsg string = "The cluster's validations have not yet been calculated" - ClusterValidationsFailingMsg string = "The cluster's validations are failing:" - ClusterValidationsUserPendingMsg string = "The cluster's validations are pending for user:" + ClusterValidatedCondition hivev1.ClusterInstallConditionType = "Validated" + ClusterValidationsOKMsg string = "The cluster's validations are passing" + ClusterValidationsUnknownMsg string = "The cluster's validations have not yet been calculated" + ClusterValidationsFailingMsg string = "The cluster's validations are failing:" + ClusterValidationsUserPendingMsg string = "The cluster's validations are pending for user:" - ClusterFailedCondition string = hivev1.ClusterInstallFailed + ClusterFailedCondition = hivev1.ClusterInstallFailed ClusterFailedReason string = "InstallationFailed" ClusterFailedMsg string = "The installation failed:" ClusterNotFailedReason string = "InstallationNotFailed" ClusterNotFailedMsg string = "The installation has not failed" - ClusterStoppedCondition string = hivev1.ClusterInstallStopped + ClusterStoppedCondition = hivev1.ClusterInstallStopped ClusterStoppedFailedReason string = "InstallationFailed" ClusterStoppedFailedMsg string = "The installation has stopped due to error" ClusterStoppedCanceledReason string = "InstallationCancelled" @@ -80,10 +78,12 @@ const ( ClusterInputErrorReason string = "InputError" ClusterInputErrorMsg string = "The Spec could not be synced due to an input error:" - ClusterLastInstallationPreparationFailedOKReason string = "There is no failing prior preparation attempt" - ClusterLastInstallationPreparationFailedErrorReason string = "The last installation preparation failed" - ClusterLastInstallationPreparationPending string = "Cluster preparation has never been performed for this cluster" - ClusterLastInstallationPreparationFailedCondition string = "LastInstallationPreparationFailed" + ClusterLastInstallationPreparationFailedOKReason string = "There is no failing prior preparation attempt" + ClusterLastInstallationPreparationFailedErrorReason string = "The last installation preparation failed" + ClusterLastInstallationPreparationPending string = "Cluster preparation has never been performed for this cluster" + ClusterLastInstallationPreparationFailedCondition hivev1.ClusterInstallConditionType = "LastInstallationPreparationFailed" + + ClusterConsumerLabel string = "agentclusterinstalls.agent-install.openshift.io/consumer" ) // +genclient @@ -151,6 +151,11 @@ type AgentClusterInstallSpec struct { // +optional Compute []AgentMachinePool `json:"compute,omitempty"` + // Arbiter is the configuration for the machines that have the + // arbiter role. + // +optional + Arbiter *AgentMachinePool `json:"arbiter,omitempty"` + // APIVIP is the virtual IP used to reach the OpenShift cluster's API. // +optional APIVIP string `json:"apiVIP,omitempty"` @@ -205,6 +210,16 @@ type AgentClusterInstallSpec struct { // Set to true to allow control plane nodes to be schedulable // +optional MastersSchedulable bool `json:"mastersSchedulable,omitempty"` + + // MirrorRegistryRef is a reference to ClusterMirrorRegistry ConfigMap that holds the registries toml + // data + // Set per cluster mirror registry + // +optional + MirrorRegistryRef *MirrorRegistryConfigMapReference `json:"mirrorRegistryRef,omitempty"` + + // LoadBalancer defines the load balancer used by the cluster for ingress traffic. + // +optional + LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty"` } // IgnitionEndpoint stores the data to of the custom ignition endpoint. @@ -355,7 +370,7 @@ type ClusterNetworkEntry struct { type ProvisionRequirements struct { // ControlPlaneAgents is the number of matching approved and ready Agents with the control plane role - // required to launch the install. Must be either 1 or 3. + // required to launch the install. Must be either 1 or 3-5. ControlPlaneAgents int `json:"controlPlaneAgents"` // WorkerAgents is the minimum number of matching approved and ready Agents with the worker role @@ -363,6 +378,12 @@ type ProvisionRequirements struct { // +kubebuilder:validation:Minimum=0 // +optional WorkerAgents int `json:"workerAgents,omitempty"` + + // ArbiterAgents is the minimum number of matching approved and ready Agents with the arbiter role + // required to launch the install. + // +kubebuilder:validation:Minimum=0 + // +optional + ArbiterAgents int `json:"arbiterAgents,omitempty"` } // HyperthreadingMode is the mode of hyperthreading for a machine. @@ -377,8 +398,9 @@ const ( ) const ( - MasterAgentMachinePool string = "master" - WorkerAgentMachinePool string = "worker" + MasterAgentMachinePool string = "master" + ArbiterAgentMachinePool string = "arbiter" + WorkerAgentMachinePool string = "worker" ) // PlatformType is a specific supported infrastructure provider. @@ -452,7 +474,7 @@ type DiskEncryption struct { // Enable/disable disk encryption on master nodes, worker nodes, or all nodes. // // +kubebuilder:default=none - // +kubebuilder:validation:Enum=none;all;masters;workers + // +kubebuilder:validation:Enum=none;all;masters;arbiters;workers;"masters,arbiters";"masters,workers";"arbiters,workers";"masters,arbiters,workers" EnableOn *string `json:"enableOn,omitempty"` // The disk encryption mode to use. @@ -502,6 +524,41 @@ type ManifestsConfigMapReference struct { Name string `json:"name"` } +// LoadBalancer defines the load balancer used by the cluster. +// +union +type LoadBalancer struct { + // Type defines the type of load balancer used by the cluster, which can be managed by the user or by the + // cluster. The default value is ClusterManaged. + // +default="ClusterManaged" + // +kubebuilder:default:="ClusterManaged" + // +kubebuilder:validation:Enum:="ClusterManaged";"UserManaged" + // +optional + // +unionDiscriminator + Type LoadBalancerType `json:"type,omitempty"` +} + +// LoadBalancerType defines the type of load balancer used by the cluster. +type LoadBalancerType string + +const ( + // LoadBalancerTypeClusterManaged is a load balancer with virtual IP addresses managed internally by the + // cluster. + LoadBalancerTypeClusterManaged LoadBalancerType = "ClusterManaged" + + // LoadBalancerTypeUserManaged is a load balancer managed outside of the cluster by the customer. When this is + // used no virtual IP addresses should be specified. Note that this is only allowed for the bare metal and + // vSphere platforms. + LoadBalancerTypeUserManaged LoadBalancerType = "UserManaged" +) + func init() { SchemeBuilder.Register(&AgentClusterInstall{}, &AgentClusterInstallList{}) } + +// MirrorRegistryConfigMapReference contains reference to a ConfigMap for mirror registry +type MirrorRegistryConfigMapReference struct { + // Name is the name of the ConfigMap that this refers to + Name string `json:"name"` + // Namespace of the ConfigMap + Namespace string `json:"namespace"` +} diff --git a/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/zz_generated.deepcopy.go index b26699ae..99420e92 100644 --- a/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/assisted-service/api/hiveextension/v1beta1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright 2020. @@ -123,6 +122,11 @@ func (in *AgentClusterInstallSpec) DeepCopyInto(out *AgentClusterInstallSpec) { *out = make([]AgentMachinePool, len(*in)) copy(*out, *in) } + if in.Arbiter != nil { + in, out := &in.Arbiter, &out.Arbiter + *out = new(AgentMachinePool) + **out = **in + } if in.APIVIPs != nil { in, out := &in.APIVIPs, &out.APIVIPs *out = make([]string, len(*in)) @@ -153,6 +157,16 @@ func (in *AgentClusterInstallSpec) DeepCopyInto(out *AgentClusterInstallSpec) { *out = new(ExternalPlatformSpec) **out = **in } + if in.MirrorRegistryRef != nil { + in, out := &in.MirrorRegistryRef, &out.MirrorRegistryRef + *out = new(MirrorRegistryConfigMapReference) + **out = **in + } + if in.LoadBalancer != nil { + in, out := &in.LoadBalancer, &out.LoadBalancer + *out = new(LoadBalancer) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentClusterInstallSpec. @@ -205,7 +219,8 @@ func (in *AgentClusterInstallStatus) DeepCopyInto(out *AgentClusterInstallStatus if val == nil { (*out)[key] = nil } else { - in, out := &val, &outVal + inVal := (*in)[key] + in, out := &inVal, &outVal *out = make(common.ValidationResults, len(*in)) copy(*out, *in) } @@ -359,6 +374,21 @@ func (in *IgnitionEndpoint) DeepCopy() *IgnitionEndpoint { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancer. +func (in *LoadBalancer) DeepCopy() *LoadBalancer { + if in == nil { + return nil + } + out := new(LoadBalancer) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineNetworkEntry) DeepCopyInto(out *MachineNetworkEntry) { *out = *in @@ -389,6 +419,21 @@ func (in *ManifestsConfigMapReference) DeepCopy() *ManifestsConfigMapReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MirrorRegistryConfigMapReference) DeepCopyInto(out *MirrorRegistryConfigMapReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MirrorRegistryConfigMapReference. +func (in *MirrorRegistryConfigMapReference) DeepCopy() *MirrorRegistryConfigMapReference { + if in == nil { + return nil + } + out := new(MirrorRegistryConfigMapReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Networking) DeepCopyInto(out *Networking) { *out = *in diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_types.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_types.go index e9ffd11b..2d773602 100644 --- a/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_types.go +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_types.go @@ -155,6 +155,7 @@ type HostDisk struct { type HostBoot struct { CurrentBootMode string `json:"currentBootMode,omitempty"` PxeInterface string `json:"pxeInterface,omitempty"` + DeviceType string `json:"deviceType,omitempty"` } type HostSystemVendor struct { @@ -227,6 +228,13 @@ type HostNTPSources struct { SourceState models.SourceState `json:"sourceState,omitempty"` } +type AgentDeprovisionInfo struct { + ClusterName string `json:"cluster_name,omitempty"` + ClusterNamespace string `json:"cluster_namespace,omitempty"` + NodeName string `json:"node_name,omitempty"` + Message string `json:"message,omitempty"` +} + // AgentStatus defines the observed state of Agent type AgentStatus struct { Bootstrap bool `json:"bootstrap,omitempty"` @@ -247,6 +255,19 @@ type AgentStatus struct { // InstallationDiskID is the disk that will be used for the installation. // +optional InstallationDiskID string `json:"installation_disk_id,omitempty"` + + // DeprovisionInfo stores data related to the agent's previous cluster binding in order to clean up when the agent re-registers + // +optional + DeprovisionInfo *AgentDeprovisionInfo `json:"deprovision_info,omitempty"` + + // CSRStatus tracks the status of CSR approvals for the agent + CSRStatus CSRStatus `json:"csrStatus,omitempty"` + + // Kind corresponds to the same field in the model Host. It indicates the type of cluster the host is + // being installed to; either an existing cluster (day-2) or a new cluster (day-1). + // Value is one of: "AddToExistingClusterHost" (day-2) or "Host" (day-1) + // +optional + Kind string `json:"kind,omitempty"` } type DebugInfo struct { @@ -264,6 +285,30 @@ type DebugInfo struct { StateInfo string `json:"stateInfo,omitempty"` } +// CSRType represents the type of CSR +type CSRType string + +const ( + CSRTypeClient CSRType = "client" + CSRTypeServing CSRType = "serving" +) + +// CSRInfo tracks information about an approved CSR +type CSRInfo struct { + Name string `json:"name"` + Type CSRType `json:"type"` + ApprovedAt metav1.Time `json:"approvedAt"` +} + +// CSRStatus tracks the status of CSR approvals for the agent +type CSRStatus struct { + // CSRs that have been approved for the agent by the assisted-service + ApprovedCSRs []CSRInfo `json:"approvedCSRs,omitempty"` + + // Last time we attempted a CSR approval + LastApprovalAttempt metav1.Time `json:"lastApprovalAttempt,omitempty"` +} + // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".spec.clusterDeploymentName.name",description="The name of the cluster the Agent registered to." diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_webhook.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_webhook.go new file mode 100644 index 00000000..fa7fce31 --- /dev/null +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/agent_webhook.go @@ -0,0 +1,88 @@ +/* +Copyright 2020. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + "github.com/openshift/assisted-service/models" + "github.com/thoas/go-funk" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var agentlog = logf.Log.WithName("agent-resource") + +// SetupWebhookWithManager will setup the manager to manage the webhooks +func (r *Agent) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-agent-install-openshift-io-v1beta1-agent,mutating=false,failurePolicy=fail,sideEffects=None,groups=agent-install.openshift.io,resources=agents,verbs=create;update,versions=v1beta1,name=vagent.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &Agent{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Agent) ValidateCreate() (admission.Warnings, error) { + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Agent) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + agentlog.Info("validate update", "name", r.Name) + oldObject, ok := old.(*Agent) + if !ok { + return nil, fmt.Errorf("old object is not an Agent") + } + if !areClusterRefsEqual(oldObject.Spec.ClusterDeploymentName, r.Spec.ClusterDeploymentName) { + installingStatuses := []string{ + models.HostStatusPreparingForInstallation, + models.HostStatusPreparingFailed, + models.HostStatusPreparingSuccessful, + models.HostStatusInstalling, + models.HostStatusInstallingInProgress, + models.HostStatusInstallingPendingUserAction, + } + if funk.ContainsString(installingStatuses, r.Status.DebugInfo.State) { + err := fmt.Errorf("Failed validation: Attempted to change Spec.ClusterDeploymentName which is immutable during Agent installation.") + agentlog.Info(err.Error()) + return nil, err + } + } + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Agent) ValidateDelete() (admission.Warnings, error) { + return nil, nil +} + +func areClusterRefsEqual(clusterRef1 *ClusterReference, clusterRef2 *ClusterReference) bool { + if clusterRef1 == nil && clusterRef2 == nil { + return true + } else if clusterRef1 != nil && clusterRef2 != nil { + return (clusterRef1.Name == clusterRef2.Name && clusterRef1.Namespace == clusterRef2.Namespace) + } else { + return false + } +} diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/agentclassification_webhook.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/agentclassification_webhook.go new file mode 100644 index 00000000..f2ab4d06 --- /dev/null +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/agentclassification_webhook.go @@ -0,0 +1,98 @@ +/* +Copyright 2020. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + "strings" + + "github.com/itchyny/gojq" + + "k8s.io/apimachinery/pkg/apis/meta/v1/validation" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +const ( + ClassificationLabelPrefix = "agentclassification." + Group + "/" +) + +// log is for logging in this package. +var agentclassificationlog = logf.Log.WithName("agentclassification-resource") + +// SetupWebhookWithManager will setup the manager to manage the webhooks +func (r *AgentClassification) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-agent-install-openshift-io-v1beta1-agentclassification,mutating=false,failurePolicy=fail,sideEffects=None,groups=agent-install.openshift.io,resources=agentclassifications,verbs=create;update,versions=v1beta1,name=vagentclassification.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &AgentClassification{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *AgentClassification) ValidateCreate() (admission.Warnings, error) { + agentclassificationlog.Info("validate create", "name", r.Name) + f := field.NewPath("spec") + errs := validation.ValidateLabels(map[string]string{ClassificationLabelPrefix + r.Spec.LabelKey: r.Spec.LabelValue}, f) + if strings.HasPrefix(r.Spec.LabelValue, "QUERYERROR") { + errs = append(errs, field.Invalid(f, r.Spec.LabelValue, "label must not start with QUERYERROR as this is reserved")) + } + + // Validate that we can parse the specified query + _, err := gojq.Parse(r.Spec.Query) + if err != nil { + errs = append(errs, field.Invalid(f, r.Spec.Query, err.Error())) + } + + if len(errs) > 0 { + err := fmt.Errorf("Validation failed: %s", errs.ToAggregate().Error()) + return nil, err + } + + agentclassificationlog.Info("Successful validation") + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *AgentClassification) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + agentclassificationlog.Info("validate update", "name", r.Name) + + oldAgentClassification, ok := old.(*AgentClassification) + if !ok { + return nil, fmt.Errorf("old object is not an AgentClassification") + } + + // Validate that the label key and value haven't changed + if (oldAgentClassification.Spec.LabelKey != r.Spec.LabelKey) || (oldAgentClassification.Spec.LabelValue != r.Spec.LabelValue) { + return nil, fmt.Errorf("Label modified: the specified label may not be modified after creation") + } + + // If we get here, then all checks passed, so the object is valid. + agentclassificationlog.Info("Successful validation") + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *AgentClassification) ValidateDelete() (admission.Warnings, error) { + return nil, nil +} diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/agentserviceconfig_types.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/agentserviceconfig_types.go index a127cbc5..4c201832 100644 --- a/vendor/github.com/openshift/assisted-service/api/v1beta1/agentserviceconfig_types.go +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/agentserviceconfig_types.go @@ -104,7 +104,7 @@ type AgentServiceConfigSpec struct { IPXEHTTPRoute string `json:"iPXEHTTPRoute,omitempty"` // UnauthenticatedRegistries is a list of registries from which container images can be pulled // without authentication. They will be appended to the default list (quay.io, - // registry.svc.ci.openshift.org). Any registry on this list will not require credentials + // registry.ci.openshift.org). Any registry on this list will not require credentials // to be in the pull secret validated by the assisted-service. //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="List of container registries without authentication" // +optional @@ -122,8 +122,37 @@ type AgentServiceConfigSpec struct { // +optional OSImageAdditionalParamsRef *corev1.LocalObjectReference `json:"OSImageAdditionalParamsRef,omitempty"` + // Ingress contains configuration for the ingress resources. + // Has no effect when running on an OpenShift cluster. + //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Ingress" + // +optional + Ingress *Ingress `json:"ingress,omitempty"` +} + +type Ingress struct { + // AssistedServiceHostname is the hostname to be assigned to the assisted-service ingress. + // Has no effect when running on an OpenShift cluster. + //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Assisted Service hostname" + AssistedServiceHostname string `json:"assistedServiceHostname"` + + // ImageServiceHostname is the hostname to be assigned to the assisted-image-service ingress. + // Has no effect when running on an OpenShift cluster. + //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Assisted Image Service hostname" + ImageServiceHostname string `json:"imageServiceHostname"` + + // ClassName is the name of the ingress class to be used when configuring ingress resources. + // Has no effect when running on an OpenShift cluster. + //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Class Name" + // +optional + ClassName *string `json:"className,omitempty"` } +// Annotations +const ( + PVCPrefixAnnotation = "unsupported.agent-install.openshift.io/assisted-service-pvc-prefix" + SecretsPrefixAnnotation = "unsupported.agent-install.openshift.io/assisted-service-secrets-prefix" +) + // ConditionType related to our reconcile loop in addition to all the reasons // why ConditionStatus could be true or false. const ( @@ -133,7 +162,8 @@ const ( ConditionReconcileCompleted conditionsv1.ConditionType = "ReconcileCompleted" // ConditionDeploymentsHealthy reports whether deployments are healthy. ConditionDeploymentsHealthy conditionsv1.ConditionType = "DeploymentsHealthy" - + // ReasonLocalClusterImportNotEnabled when the import of local cluster is not enabled. + ReasonLocalClusterImportNotEnabled string = "Local cluster import is not enabled" // ReasonLocalClusterEntitiesCreated when the local cluster is managed. ReasonLocalClusterManaged string = "Local cluster is managed." // ReasonLocalClusterEntitiesRemoved when the local cluster is not managed. @@ -204,6 +234,14 @@ const ( ReasonKonnectivityAgentFailure string = "KonnectivityAgentFailure" // ReasonOSImageCACertRefFailure when there has been a failure resolving the OS image CA using OSImageCACertRef. ReasonOSImageCACertRefFailure string = "OSImageCACertRefFailure" + // ReasonOSImagesShouldBeEmptyFailure when OSImages are not empty but image service is disabled. + ReasonOSImagesShouldBeEmptyFailure string = "OSImagesShouldBeEmptyFailure" + // ReasonMonitoringFailure indicates there was a failure monitoring operand status + ReasonMonitoringFailure string = "MonitoringFailure" + // ReasonKubernetesIngressMissing indicates the user has not provided the required configuration for kubernetes ingress + ReasonKubernetesIngressMissing string = "KubernetesIngressConfigMissing" + // ReasonCertificateFailure indicates that the required certificates could not be created + ReasonCertificateFailure string = "CertificateConfigurationFailure" // IPXEHTTPRouteEnabled is expected value in IPXEHTTPRoute to enable the route IPXEHTTPRouteEnabled string = "enabled" @@ -211,11 +249,14 @@ const ( IPXEHTTPRouteDisabled string = "disabled" // ReasonOSImageAdditionalParamsRefFailure when there has been a failure resolving the OS image additional params secret using OSImageAdditionalParamsRef. ReasonOSImageAdditionalParamsRefFailure string = "ReasonOSImageAdditionalParamsRefFailure" + // ReasonImmutableAnnotationFailure when there has been a failure validating immutable annotations. + ReasonImmutableAnnotationFailure string = "ImmutableAnnotationFailure" ) // AgentServiceConfigStatus defines the observed state of AgentServiceConfig type AgentServiceConfigStatus struct { Conditions []conditionsv1.Condition `json:"conditions,omitempty"` + ImmutableAnnotations map[string]string `json:"immutableAnnotations,omitempty"` } // +kubebuilder:object:root=true diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_types.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_types.go index aeb28a5d..776af089 100644 --- a/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_types.go +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_types.go @@ -17,17 +17,23 @@ limitations under the License. package v1beta1 import ( + "github.com/openshift/assisted-service/api/hiveextension/v1beta1" + "github.com/openshift/assisted-service/models" conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( - ImageCreatedReason = "ImageCreated" - ImageStateCreated = "Image has been created" - ImageCreationErrorReason = "ImageCreationError" - ImageStateFailedToCreate = "Failed to create image" - InfraEnvNameLabel = "infraenvs.agent-install.openshift.io" + ImageCreatedReason = "ImageCreated" + ImageStateCreated = "Image has been created" + ImageCreationErrorReason = "ImageCreationError" + ImageStateFailedToCreate = "Failed to create image" + InfraEnvNameLabel = "infraenvs.agent-install.openshift.io" + MissingClusterDeploymentReason = "MissingClusterDeployment" + MissingClusterDeploymentReference = "ClusterDeployment is missing" + InfraEnvAvailableReason = "InfraEnvAvailable" + InfraEnvAvailableMessage = "InfraEnv is available" ) // ClusterReference represents a Cluster Reference. It has enough information to retrieve cluster @@ -42,7 +48,9 @@ type ClusterReference struct { } const ( - ImageCreatedCondition conditionsv1.ConditionType = "ImageCreated" + ImageCreatedCondition conditionsv1.ConditionType = "ImageCreated" + ClusterDeploymentReference conditionsv1.ConditionType = "ClusterDeploymentReference" + ) type InfraEnvSpec struct { @@ -114,9 +122,20 @@ type InfraEnvSpec struct { // OSImageVersion is the version of OS image to use when generating the InfraEnv. // The version should refer to an OSImage specified in the AgentServiceConfig // (i.e. OSImageVersion should equal to an OpenshiftVersion in OSImages list). - // Note: OSImageVersion can't be specified along with ClusterRef. + // Note: OSImageVersion can't be specified along with ClusterRef. // +optional OSImageVersion string `json:"osImageVersion,omitempty"` + + // MirrorRegistryRef is a reference to a given MirrorRegistry ConfigMap that holds the registries toml data + // +optional + MirrorRegistryRef *v1beta1.MirrorRegistryConfigMapReference `json:"mirrorRegistryRef,omitempty"` + + // ImageType specifies the type of discovery ISO to be generated by the Assisted Installer. + // Supported values include: + // - full-iso: A complete Red Hat CoreOS (RHCOS) ISO, customized with a specific ignition file. + // - minimal-iso: A lightweight ISO that retrieves the remainder of the RHCOS root file system (rootfs) dynamically from the Internet + // +optional + ImageType models.ImageType `json:"imageType,omitempty"` } type KernelArgument struct { @@ -189,6 +208,9 @@ type BootArtifacts struct { // IpxeScriptURL specifies an HTTP/S URL that contains the iPXE script // +optional IpxeScriptURL string `json:"ipxeScript"` + // DiscoveryIgnitionURL specifies an HTTP/S URL that contains the discovery ignition + // +optional + DiscoveryIgnitionURL string `json:"discoveryIgnitionURL"` } // +kubebuilder:object:root=true diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_webhook.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_webhook.go new file mode 100644 index 00000000..04e1696c --- /dev/null +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/infraenv_webhook.go @@ -0,0 +1,73 @@ +/* +Copyright 2020. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var infraenvlog = logf.Log.WithName("infraenv-resource") + +// SetupWebhookWithManager will setup the manager to manage the webhooks +func (r *InfraEnv) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-agent-install-openshift-io-v1beta1-infraenv,mutating=false,failurePolicy=fail,sideEffects=None,groups=agent-install.openshift.io,resources=infraenvs,verbs=create;update,versions=v1beta1,name=vinfraenv.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &InfraEnv{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *InfraEnv) ValidateCreate() (admission.Warnings, error) { + infraenvlog.Info("validate create", "name", r.Name) + if r.Spec.ClusterRef != nil && r.Spec.OSImageVersion != "" { + err := fmt.Errorf("Failed validation: Either Spec.ClusterRef or Spec.OSImageVersion should be specified (not both).") + infraenvlog.Info(err.Error()) + return nil, err + } + infraenvlog.Info("Successful validation") + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *InfraEnv) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + infraenvlog.Info("validate update", "name", r.Name) + oldInfraEnv, ok := old.(*InfraEnv) + if !ok { + return nil, fmt.Errorf("old object is not an InfraEnv") + } + if !areClusterRefsEqual(oldInfraEnv.Spec.ClusterRef, r.Spec.ClusterRef) { + err := fmt.Errorf("Failed validation: Attempted to change Spec.ClusterRef which is immutable after InfraEnv creation.") + return nil, err + } + infraenvlog.Info("Successful validation") + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *InfraEnv) ValidateDelete() (admission.Warnings, error) { + return nil, nil +} diff --git a/vendor/github.com/openshift/assisted-service/api/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/openshift/assisted-service/api/v1beta1/zz_generated.deepcopy.go index 700602f9..b07dd6dc 100644 --- a/vendor/github.com/openshift/assisted-service/api/v1beta1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/assisted-service/api/v1beta1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright 2020. @@ -23,10 +22,11 @@ package v1beta1 import ( "github.com/openshift/assisted-service/api/common" + hiveextensionv1beta1 "github.com/openshift/assisted-service/api/hiveextension/v1beta1" "github.com/openshift/assisted-service/models" "github.com/openshift/custom-resource-status/conditions/v1" corev1 "k8s.io/api/core/v1" - runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -152,6 +152,21 @@ func (in *AgentClassificationStatus) DeepCopy() *AgentClassificationStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AgentDeprovisionInfo) DeepCopyInto(out *AgentDeprovisionInfo) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentDeprovisionInfo. +func (in *AgentDeprovisionInfo) DeepCopy() *AgentDeprovisionInfo { + if in == nil { + return nil + } + out := new(AgentDeprovisionInfo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AgentList) DeepCopyInto(out *AgentList) { *out = *in @@ -283,6 +298,11 @@ func (in *AgentServiceConfigSpec) DeepCopyInto(out *AgentServiceConfigSpec) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(Ingress) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentServiceConfigSpec. @@ -305,6 +325,13 @@ func (in *AgentServiceConfigStatus) DeepCopyInto(out *AgentServiceConfigStatus) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ImmutableAnnotations != nil { + in, out := &in.ImmutableAnnotations, &out.ImmutableAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentServiceConfigStatus. @@ -382,13 +409,20 @@ func (in *AgentStatus) DeepCopyInto(out *AgentStatus) { if val == nil { (*out)[key] = nil } else { - in, out := &val, &outVal + inVal := (*in)[key] + in, out := &inVal, &outVal *out = make(common.ValidationResults, len(*in)) copy(*out, *in) } (*out)[key] = outVal } } + if in.DeprovisionInfo != nil { + in, out := &in.DeprovisionInfo, &out.DeprovisionInfo + *out = new(AgentDeprovisionInfo) + **out = **in + } + in.CSRStatus.DeepCopyInto(&out.CSRStatus) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentStatus. @@ -416,6 +450,45 @@ func (in *BootArtifacts) DeepCopy() *BootArtifacts { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CSRInfo) DeepCopyInto(out *CSRInfo) { + *out = *in + in.ApprovedAt.DeepCopyInto(&out.ApprovedAt) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSRInfo. +func (in *CSRInfo) DeepCopy() *CSRInfo { + if in == nil { + return nil + } + out := new(CSRInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CSRStatus) DeepCopyInto(out *CSRStatus) { + *out = *in + if in.ApprovedCSRs != nil { + in, out := &in.ApprovedCSRs, &out.ApprovedCSRs + *out = make([]CSRInfo, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.LastApprovalAttempt.DeepCopyInto(&out.LastApprovalAttempt) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSRStatus. +func (in *CSRStatus) DeepCopy() *CSRStatus { + if in == nil { + return nil + } + out := new(CSRStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterReference) DeepCopyInto(out *ClusterReference) { *out = *in @@ -896,6 +969,11 @@ func (in *InfraEnvSpec) DeepCopyInto(out *InfraEnvSpec) { *out = make([]KernelArgument, len(*in)) copy(*out, *in) } + if in.MirrorRegistryRef != nil { + in, out := &in.MirrorRegistryRef, &out.MirrorRegistryRef + *out = new(hiveextensionv1beta1.MirrorRegistryConfigMapReference) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfraEnvSpec. @@ -937,6 +1015,26 @@ func (in *InfraEnvStatus) DeepCopy() *InfraEnvStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Ingress) DeepCopyInto(out *Ingress) { + *out = *in + if in.ClassName != nil { + in, out := &in.ClassName, &out.ClassName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Ingress. +func (in *Ingress) DeepCopy() *Ingress { + if in == nil { + return nil + } + out := new(Ingress) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Interface) DeepCopyInto(out *Interface) { *out = *in diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go index bbeee804..7f98c60a 100644 --- a/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go +++ b/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go @@ -8,7 +8,8 @@ import ( ) // SetStatusCondition sets the corresponding condition in conditions to newCondition. -func SetStatusCondition(conditions *[]Condition, newCondition Condition) { +// The return value indicates if this resulted in any changes *other than* LastHeartbeatTime. +func SetStatusCondition(conditions *[]Condition, newCondition Condition) bool { if conditions == nil { conditions = &[]Condition{} } @@ -17,22 +18,18 @@ func SetStatusCondition(conditions *[]Condition, newCondition Condition) { newCondition.LastTransitionTime = metav1.NewTime(time.Now()) newCondition.LastHeartbeatTime = metav1.NewTime(time.Now()) *conditions = append(*conditions, newCondition) - return - } - - if existingCondition.Status != newCondition.Status { - existingCondition.Status = newCondition.Status - existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) + return true } - existingCondition.Reason = newCondition.Reason - existingCondition.Message = newCondition.Message + changed := updateCondition(existingCondition, newCondition) existingCondition.LastHeartbeatTime = metav1.NewTime(time.Now()) + return changed } // SetStatusConditionNoHearbeat sets the corresponding condition in conditions to newCondition // without setting lastHeartbeatTime. -func SetStatusConditionNoHeartbeat(conditions *[]Condition, newCondition Condition) { +// The return value indicates if this resulted in any changes. +func SetStatusConditionNoHeartbeat(conditions *[]Condition, newCondition Condition) bool { if conditions == nil { conditions = &[]Condition{} } @@ -40,16 +37,10 @@ func SetStatusConditionNoHeartbeat(conditions *[]Condition, newCondition Conditi if existingCondition == nil { newCondition.LastTransitionTime = metav1.NewTime(time.Now()) *conditions = append(*conditions, newCondition) - return + return true } - if existingCondition.Status != newCondition.Status { - existingCondition.Status = newCondition.Status - existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) - } - - existingCondition.Reason = newCondition.Reason - existingCondition.Message = newCondition.Message + return updateCondition(existingCondition, newCondition) } // RemoveStatusCondition removes the corresponding conditionType from conditions. @@ -67,6 +58,25 @@ func RemoveStatusCondition(conditions *[]Condition, conditionType ConditionType) *conditions = newConditions } +func updateCondition(existingCondition *Condition, newCondition Condition) bool { + changed := false + if existingCondition.Status != newCondition.Status { + changed = true + existingCondition.Status = newCondition.Status + existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) + } + + if existingCondition.Reason != newCondition.Reason { + changed = true + existingCondition.Reason = newCondition.Reason + } + if existingCondition.Message != newCondition.Message { + changed = true + existingCondition.Message = newCondition.Message + } + return changed +} + // FindStatusCondition finds the conditionType in conditions. func FindStatusCondition(conditions []Condition, conditionType ConditionType) *Condition { for i := range conditions { diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/doc.go new file mode 100644 index 00000000..4ec0d37d --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/doc.go @@ -0,0 +1,4 @@ +// Package alibabacloud contains API Schema definitions for Alibaba Cloud cluster. +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +package alibabacloud diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/machinepool.go b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/machinepool.go new file mode 100644 index 00000000..bdc9d89f --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/machinepool.go @@ -0,0 +1,41 @@ +package alibabacloud + +// DiskCategory is the category of the ECS disk. Supported disk category: +// cloud_essd(ESSD disk), cloud_efficiency(ultra disk). +// +// +kubebuilder:validation:Enum="";cloud_efficiency;cloud_essd +type DiskCategory string + +// MachinePool stores the configuration for a machine pool installed +// on Alibaba Cloud. +type MachinePool struct { + // Zones is list of availability zones that can be used. + // eg. ["cn-hangzhou-i", "cn-hangzhou-h", "cn-hangzhou-j"] + // + // +optional + Zones []string `json:"zones,omitempty"` + + // InstanceType defines the ECS instance type. + // eg. ecs.g6.large + // + // +optional + InstanceType string `json:"instanceType,omitempty"` + + // SystemDiskCategory defines the category of the system disk. + // + // +optional + SystemDiskCategory DiskCategory `json:"systemDiskCategory,omitempty"` + + // SystemDiskSize defines the size of the system disk in gibibytes (GiB). + // + // +kubebuilder:validation:Type=integer + // +kubebuilder:validation:Minimum=120 + // +optional + SystemDiskSize int `json:"systemDiskSize,omitempty"` + + // ImageID is the Image ID that should be used to create ECS instance. + // If set, the ImageID should belong to the same region as the cluster. + // + // +optional + ImageID string `json:"imageID,omitempty"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/platform.go new file mode 100644 index 00000000..b38a7982 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/platform.go @@ -0,0 +1,16 @@ +package alibabacloud + +import ( + corev1 "k8s.io/api/core/v1" +) + +// Platform stores all the global configuration that all machinesets use. +type Platform struct { + // CredentialsSecretRef refers to a secret that contains Alibaba Cloud account access + // credentials. + CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` + + // Region specifies the Alibaba Cloud region where the cluster will be + // created. + Region string `json:"region"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/zz_generated.deepcopy.go new file mode 100644 index 00000000..d86041ab --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/alibabacloud/zz_generated.deepcopy.go @@ -0,0 +1,44 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package alibabacloud + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachinePool) DeepCopyInto(out *MachinePool) { + *out = *in + if in.Zones != nil { + in, out := &in.Zones, &out.Zones + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachinePool. +func (in *MachinePool) DeepCopy() *MachinePool { + if in == nil { + return nil + } + out := new(MachinePool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Platform) DeepCopyInto(out *Platform) { + *out = *in + out.CredentialsSecretRef = in.CredentialsSecretRef + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Platform. +func (in *Platform) DeepCopy() *Platform { + if in == nil { + return nil + } + out := new(Platform) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/aws/machinepool.go b/vendor/github.com/openshift/hive/apis/hive/v1/aws/machinepool.go index 603aaeca..5ae50257 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/aws/machinepool.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/aws/machinepool.go @@ -6,9 +6,14 @@ type MachinePoolPlatform struct { // Zones is list of availability zones that can be used. Zones []string `json:"zones,omitempty"` - // Subnets is the list of subnets to which to attach the machines. - // There must be exactly one private subnet for each availability zone used. - // If public subnets are specified, there must be exactly one private and one public subnet specified for each availability zone. + // Subnets is the list of IDs of subnets to which to attach the machines. + // There must be exactly one subnet for each availability zone used. + // These subnets may be public or private. + // As a special case, for consistency with install-config, you may specify exactly one + // private and one public subnet for each availability zone. In this case, the public + // subnets will be filtered out and only the private subnets will be used. + // If empty/omitted, we will look for subnets in each availability zone tagged with + // Name=-private-. Subnets []string `json:"subnets,omitempty"` // InstanceType defines the ec2 instance type. @@ -21,6 +26,16 @@ type MachinePoolPlatform struct { // SpotMarketOptions allows users to configure instances to be run using AWS Spot instances. // +optional SpotMarketOptions *SpotMarketOptions `json:"spotMarketOptions,omitempty"` + + // EC2MetadataOptions defines metadata service interaction options for EC2 instances in the machine pool. + // +optional + EC2Metadata *EC2Metadata `json:"metadataService,omitempty"` + + // AdditionalSecurityGroupIDs contains IDs of additional security groups for machines, where each ID + // is presented in the format sg-xxxx. + // + // +optional + AdditionalSecurityGroupIDs []string `json:"additionalSecurityGroupIDs,omitempty"` } // SpotMarketOptions defines the options available to a user when configuring @@ -36,7 +51,8 @@ type SpotMarketOptions struct { // EC2RootVolume defines the storage for an ec2 instance. type EC2RootVolume struct { // IOPS defines the iops for the storage. - IOPS int `json:"iops"` + // +optional + IOPS int `json:"iops,omitempty"` // Size defines the size of the storage. Size int `json:"size"` // Type defines the type of the storage. @@ -47,3 +63,16 @@ type EC2RootVolume struct { // +optional KMSKeyARN string `json:"kmsKeyARN,omitempty"` } + +// EC2Metadata defines the metadata service interaction options for an ec2 instance. +// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html +type EC2Metadata struct { + // Authentication determines whether or not the host requires the use of authentication when interacting with the metadata service. + // When using authentication, this enforces v2 interaction method (IMDSv2) with the metadata service. + // When omitted, this means the user has no opinion and the value is left to the platform to choose a good + // default, which is subject to change over time. The current default is optional. + // At this point this field represents `HttpTokens` parameter from `InstanceMetadataOptionsRequest` structure in AWS EC2 API + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InstanceMetadataOptionsRequest.html + // +optional + Authentication string `json:"authentication,omitempty"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go b/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go new file mode 100644 index 00000000..efbb50e5 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go @@ -0,0 +1,8 @@ +package aws + +// Metadata contains AWS metadata (e.g. for uninstalling the cluster). +type Metadata struct { + // HostedZoneRole is the role to assume when performing operations + // on a hosted zone owned by another account. + HostedZoneRole *string `json:"hostedZoneRole,omitempty"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/aws/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/aws/platform.go index 399e8214..9b71df8c 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/aws/platform.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/aws/platform.go @@ -39,6 +39,13 @@ type PlatformStatus struct { // PrivateLinkAccess configures access to the cluster API using AWS PrivateLink type PrivateLinkAccess struct { Enabled bool `json:"enabled"` + + // AdditionalAllowedPrincipals is a list of additional allowed principal ARNs to be configured + // for the Private Link cluster's VPC Endpoint Service. + // ARNs provided as AdditionalAllowedPrincipals will be configured for the cluster's VPC Endpoint + // Service in addition to the IAM entity used by Hive. + // +optional + AdditionalAllowedPrincipals *[]string `json:"additionalAllowedPrincipals,omitempty"` } // PrivateLinkAccessStatus contains the observed state for PrivateLinkAccess resources. @@ -54,6 +61,15 @@ type PrivateLinkAccessStatus struct { type VPCEndpointService struct { Name string `json:"name,omitempty"` ID string `json:"id,omitempty"` + // DefaultAllowedPrincipal is the ARN of the IAM entity used by Hive as configured for the Private + // Link cluster's VPC Endpoint Service. + // +optional + DefaultAllowedPrincipal *string `json:"defaultAllowedPrincipal,omitempty"` + // AdditionalAllowedPrincipals is a list of additional allowed principal ARNs that have been configured + // for the Private Link cluster's VPC Endpoint Service. This list in Status is used to determine if a sync + // of Allowed Principals is needed outside of the regular reconcile period of 2hrs. + // +optional + AdditionalAllowedPrincipals *[]string `json:"additionalAllowedPrincipals,omitempty"` } // AssumeRole stores information for the IAM role that needs to be assumed diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/aws/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/aws/zz_generated.deepcopy.go index bccf75c9..7d5f07fe 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/aws/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/aws/zz_generated.deepcopy.go @@ -21,6 +21,22 @@ func (in *AssumeRole) DeepCopy() *AssumeRole { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EC2Metadata) DeepCopyInto(out *EC2Metadata) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EC2Metadata. +func (in *EC2Metadata) DeepCopy() *EC2Metadata { + if in == nil { + return nil + } + out := new(EC2Metadata) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EC2RootVolume) DeepCopyInto(out *EC2RootVolume) { *out = *in @@ -56,6 +72,16 @@ func (in *MachinePoolPlatform) DeepCopyInto(out *MachinePoolPlatform) { *out = new(SpotMarketOptions) (*in).DeepCopyInto(*out) } + if in.EC2Metadata != nil { + in, out := &in.EC2Metadata, &out.EC2Metadata + *out = new(EC2Metadata) + **out = **in + } + if in.AdditionalSecurityGroupIDs != nil { + in, out := &in.AdditionalSecurityGroupIDs, &out.AdditionalSecurityGroupIDs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -69,6 +95,27 @@ func (in *MachinePoolPlatform) DeepCopy() *MachinePoolPlatform { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Metadata) DeepCopyInto(out *Metadata) { + *out = *in + if in.HostedZoneRole != nil { + in, out := &in.HostedZoneRole, &out.HostedZoneRole + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Metadata. +func (in *Metadata) DeepCopy() *Metadata { + if in == nil { + return nil + } + out := new(Metadata) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Platform) DeepCopyInto(out *Platform) { *out = *in @@ -88,7 +135,7 @@ func (in *Platform) DeepCopyInto(out *Platform) { if in.PrivateLink != nil { in, out := &in.PrivateLink, &out.PrivateLink *out = new(PrivateLinkAccess) - **out = **in + (*in).DeepCopyInto(*out) } return } @@ -109,7 +156,7 @@ func (in *PlatformStatus) DeepCopyInto(out *PlatformStatus) { if in.PrivateLink != nil { in, out := &in.PrivateLink, &out.PrivateLink *out = new(PrivateLinkAccessStatus) - **out = **in + (*in).DeepCopyInto(*out) } return } @@ -127,6 +174,15 @@ func (in *PlatformStatus) DeepCopy() *PlatformStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateLinkAccess) DeepCopyInto(out *PrivateLinkAccess) { *out = *in + if in.AdditionalAllowedPrincipals != nil { + in, out := &in.AdditionalAllowedPrincipals, &out.AdditionalAllowedPrincipals + *out = new([]string) + if **in != nil { + in, out := *in, *out + *out = make([]string, len(*in)) + copy(*out, *in) + } + } return } @@ -143,7 +199,7 @@ func (in *PrivateLinkAccess) DeepCopy() *PrivateLinkAccess { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateLinkAccessStatus) DeepCopyInto(out *PrivateLinkAccessStatus) { *out = *in - out.VPCEndpointService = in.VPCEndpointService + in.VPCEndpointService.DeepCopyInto(&out.VPCEndpointService) return } @@ -181,6 +237,20 @@ func (in *SpotMarketOptions) DeepCopy() *SpotMarketOptions { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VPCEndpointService) DeepCopyInto(out *VPCEndpointService) { *out = *in + if in.DefaultAllowedPrincipal != nil { + in, out := &in.DefaultAllowedPrincipal, &out.DefaultAllowedPrincipal + *out = new(string) + **out = **in + } + if in.AdditionalAllowedPrincipals != nil { + in, out := &in.AdditionalAllowedPrincipals, &out.AdditionalAllowedPrincipals + *out = new([]string) + if **in != nil { + in, out := *in, *out + *out = make([]string, len(*in)) + copy(*out, *in) + } + } return } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/disk.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/disk.go new file mode 100644 index 00000000..2463235e --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/disk.go @@ -0,0 +1,48 @@ +package azure + +import "fmt" + +// ToID creates an Azure resource ID for the disk encryption set. +// It is possible to return a non-valid ID when SubscriptionID is empty. This +// should never happen since if SubscriptionID is empty, it is set to the +// current subscription. Also, should it somehow be empty and this returns an +// invalid ID, the validation code will produce an error when checked against +// the validation.RxDiskEncryptionSetID regular expression. +func (d *DiskEncryptionSet) ToID() string { + return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/diskEncryptionSets/%s", + d.SubscriptionID, d.ResourceGroup, d.Name) +} + +// OSDisk defines the disk for machines on Azure. +type OSDisk struct { + // DiskSizeGB defines the size of disk in GB. + // + // +kubebuilder:validation:Minimum=0 + DiskSizeGB int32 `json:"diskSizeGB"` + // DiskType defines the type of disk. + // For control plane nodes, the valid values are Premium_LRS and StandardSSD_LRS. + // Default is Premium_LRS. + // +optional + // +kubebuilder:validation:Enum=Standard_LRS;Premium_LRS;StandardSSD_LRS + DiskType string `json:"diskType,omitempty"` + + // DiskEncryptionSet defines a disk encryption set. + // + // +optional + *DiskEncryptionSet `json:"diskEncryptionSet,omitempty"` +} + +// DiskEncryptionSet defines the configuration for a disk encryption set. +type DiskEncryptionSet struct { + // SubscriptionID defines the Azure subscription the disk encryption + // set is in. + SubscriptionID string `json:"subscriptionId,omitempty"` + // ResourceGroup defines the Azure resource group used by the disk + // encryption set. + ResourceGroup string `json:"resourceGroup"` + // Name is the name of the disk encryption set. + Name string `json:"name"` +} + +// DefaultDiskType holds the default Azure disk type used by the VMs. +const DefaultDiskType string = "Premium_LRS" diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go index 9bb9b7f9..1fb9f51c 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go @@ -13,29 +13,20 @@ type MachinePool struct { // OSDisk defines the storage for instance. OSDisk `json:"osDisk"` -} -// OSDisk defines the disk for machines on Azure. -type OSDisk struct { - // DiskSizeGB defines the size of disk in GB. - DiskSizeGB int32 `json:"diskSizeGB"` + // OSImage defines the image to use for the OS. + // +optional + OSImage *OSImage `json:"osImage,omitempty"` } -// Set sets the values from `required` to `a`. -func (a *MachinePool) Set(required *MachinePool) { - if required == nil || a == nil { - return - } - - if len(required.Zones) > 0 { - a.Zones = required.Zones - } - - if required.InstanceType != "" { - a.InstanceType = required.InstanceType - } - - if required.OSDisk.DiskSizeGB != 0 { - a.OSDisk.DiskSizeGB = required.OSDisk.DiskSizeGB - } +// OSImage is the image to use for the OS of a machine. +type OSImage struct { + // Publisher is the publisher of the image. + Publisher string `json:"publisher"` + // Offer is the offer of the image. + Offer string `json:"offer"` + // SKU is the SKU of the image. + SKU string `json:"sku"` + // Version is the version of the image. + Version string `json:"version"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go index 472c01c4..65552358 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go @@ -2,5 +2,6 @@ package azure // Metadata contains Azure metadata (e.g. for uninstalling the cluster). type Metadata struct { - Region string `json:"region"` + // ResourceGroupName is the name of the resource group in which the cluster resources were created. + ResourceGroupName *string `json:"resourceGroupName"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/platform.go index 37bb188d..d5201a93 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/platform.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/platform.go @@ -50,7 +50,7 @@ func (e CloudEnvironment) Name() string { return string(e) } -//SetBaseDomain parses the baseDomainID and sets the related fields on azure.Platform +// SetBaseDomain parses the baseDomainID and sets the related fields on azure.Platform func (p *Platform) SetBaseDomain(baseDomainID string) error { parts := strings.Split(baseDomainID, "/") p.BaseDomainResourceGroupName = parts[4] diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/zz_generated.deepcopy.go index 81cad96d..adc8cd56 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/zz_generated.deepcopy.go @@ -5,6 +5,22 @@ package azure +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskEncryptionSet) DeepCopyInto(out *DiskEncryptionSet) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskEncryptionSet. +func (in *DiskEncryptionSet) DeepCopy() *DiskEncryptionSet { + if in == nil { + return nil + } + out := new(DiskEncryptionSet) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachinePool) DeepCopyInto(out *MachinePool) { *out = *in @@ -13,7 +29,12 @@ func (in *MachinePool) DeepCopyInto(out *MachinePool) { *out = make([]string, len(*in)) copy(*out, *in) } - out.OSDisk = in.OSDisk + in.OSDisk.DeepCopyInto(&out.OSDisk) + if in.OSImage != nil { + in, out := &in.OSImage, &out.OSImage + *out = new(OSImage) + **out = **in + } return } @@ -30,6 +51,11 @@ func (in *MachinePool) DeepCopy() *MachinePool { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Metadata) DeepCopyInto(out *Metadata) { *out = *in + if in.ResourceGroupName != nil { + in, out := &in.ResourceGroupName, &out.ResourceGroupName + *out = new(string) + **out = **in + } return } @@ -46,6 +72,11 @@ func (in *Metadata) DeepCopy() *Metadata { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OSDisk) DeepCopyInto(out *OSDisk) { *out = *in + if in.DiskEncryptionSet != nil { + in, out := &in.DiskEncryptionSet, &out.DiskEncryptionSet + *out = new(DiskEncryptionSet) + **out = **in + } return } @@ -59,6 +90,22 @@ func (in *OSDisk) DeepCopy() *OSDisk { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSImage) DeepCopyInto(out *OSImage) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSImage. +func (in *OSImage) DeepCopy() *OSImage { + if in == nil { + return nil + } + out := new(OSImage) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Platform) DeepCopyInto(out *Platform) { *out = *in diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterclaim_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterclaim_types.go index 7bb772d0..30694959 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterclaim_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterclaim_types.go @@ -69,6 +69,16 @@ type ClusterClaimCondition struct { // ClusterClaimConditionType is a valid value for ClusterClaimCondition.Type. type ClusterClaimConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c ClusterClaimCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t ClusterClaimConditionType) String() string { + return string(t) +} + const ( // ClusterClaimPendingCondition is set when a cluster has not yet been assigned and made ready to the claim. ClusterClaimPendingCondition ClusterClaimConditionType = "Pending" diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go index 3fe46701..a42959ac 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go @@ -1,15 +1,18 @@ package v1 import ( + configv1 "github.com/openshift/api/config/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openshift/hive/apis/hive/v1/agent" + "github.com/openshift/hive/apis/hive/v1/alibabacloud" "github.com/openshift/hive/apis/hive/v1/aws" "github.com/openshift/hive/apis/hive/v1/azure" "github.com/openshift/hive/apis/hive/v1/baremetal" "github.com/openshift/hive/apis/hive/v1/gcp" "github.com/openshift/hive/apis/hive/v1/ibmcloud" + "github.com/openshift/hive/apis/hive/v1/none" "github.com/openshift/hive/apis/hive/v1/openstack" "github.com/openshift/hive/apis/hive/v1/ovirt" "github.com/openshift/hive/apis/hive/v1/vsphere" @@ -28,10 +31,6 @@ const ( // alert on cluster types differently. HiveClusterTypeLabel = "hive.openshift.io/cluster-type" - // DefaultClusterType will be used when the above HiveClusterTypeLabel is unset. This - // value will not be added as a label, only used for metrics vectors. - DefaultClusterType = "unspecified" - // HiveInstallLogLabel is used on ConfigMaps uploaded by the install manager which contain an install log. HiveInstallLogLabel = "hive.openshift.io/install-log" @@ -98,6 +97,9 @@ const ( // ClusterPowerStateWaitingForClusterOperators is used when waiting for ClusterOperators to // get to a good state. (Available=True, Processing=False, Degraded=False) ClusterPowerStateWaitingForClusterOperators ClusterPowerState = "WaitingForClusterOperators" + + // ClusterPowerStateUnknown indicates that we can't/won't discover the state of the cluster's cloud machines. + ClusterPowerStateUnknown = "Unknown" ) // ClusterDeploymentSpec defines the desired state of ClusterDeployment @@ -230,10 +232,16 @@ type Provisioning struct { // that will take precedence over the one from the ClusterImageSet. ImageSetRef *ClusterImageSetReference `json:"imageSetRef,omitempty"` - // ManifestsConfigMapRef is a reference to user-provided manifests to - // add to or replace manifests that are generated by the installer. + // ManifestsConfigMapRef is a reference to user-provided manifests to add to or replace manifests + // that are generated by the installer. It serves the same purpose as, and is mutually exclusive + // with, ManifestsSecretRef. ManifestsConfigMapRef *corev1.LocalObjectReference `json:"manifestsConfigMapRef,omitempty"` + // ManifestsSecretRef is a reference to user-provided manifests to add to or replace manifests + // that are generated by the installer. It serves the same purpose as, and is mutually exclusive + // with, ManifestsConfigMapRef. + ManifestsSecretRef *corev1.LocalObjectReference `json:"manifestsSecretRef,omitempty"` + // SSHPrivateKeySecretRef is the reference to the secret that contains the private SSH key to use // for access to compute instances. This private key should correspond to the public key included // in the InstallConfig. The private key is used by Hive to gather logs on the target cluster if @@ -271,6 +279,10 @@ type ClusterPoolReference struct { // ClaimedTimestamp is the time this cluster was assigned to a ClusterClaim. This is only used for // ClusterDeployments belonging to ClusterPools. ClaimedTimestamp *metav1.Time `json:"claimedTimestamp,omitempty"` + // CustomizationRef is the ClusterPool Inventory claimed customization for this ClusterDeployment. + // The Customization exists in the ClusterPool namespace. + // +optional + CustomizationRef *corev1.LocalObjectReference `json:"clusterDeploymentCustomization,omitempty"` } // ClusterMetadata contains metadata information about the installed cluster. @@ -288,6 +300,24 @@ type ClusterMetadata struct { // AdminPasswordSecretRef references the secret containing the admin username/password which can be used to login to this cluster. // +optional AdminPasswordSecretRef *corev1.LocalObjectReference `json:"adminPasswordSecretRef,omitempty"` + + // Platform holds platform-specific cluster metadata + // +optional + Platform *ClusterPlatformMetadata `json:"platform,omitempty"` +} + +type ClusterPlatformMetadata struct { + // AWS holds AWS-specific cluster metadata + // +optional + AWS *aws.Metadata `json:"aws,omitempty"` + + // Azure holds azure-specific cluster metadata + // +optional + Azure *azure.Metadata `json:"azure,omitempty"` + + // GCP holds GCP-specific cluster metadata + // +optional + GCP *gcp.Metadata `json:"gcp,omitempty"` } // ClusterDeploymentStatus defines the observed state of ClusterDeployment @@ -369,6 +399,16 @@ type ClusterDeploymentCondition struct { // ClusterDeploymentConditionType is a valid value for ClusterDeploymentCondition.Type type ClusterDeploymentConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c ClusterDeploymentCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t ClusterDeploymentConditionType) String() string { + return string(t) +} + const ( // InstallerImageResolutionFailedCondition is a condition that indicates whether the job // to determine the installer image based on a release image was successful. @@ -450,6 +490,10 @@ const ( ClusterInstallCompletedClusterDeploymentCondition ClusterDeploymentConditionType = "ClusterInstallCompleted" ClusterInstallStoppedClusterDeploymentCondition ClusterDeploymentConditionType = "ClusterInstallStopped" ClusterInstallRequirementsMetClusterDeploymentCondition ClusterDeploymentConditionType = "ClusterInstallRequirementsMet" + + // ClusterImageSetNotFoundCondition is a legacy condition type that is not intended to be used + // in production. This type is never used by hive. + ClusterImageSetNotFoundCondition ClusterDeploymentConditionType = "ClusterImageSetNotFound" ) // PositivePolarityClusterDeploymentConditions is a slice containing all condition types with positive polarity @@ -480,8 +524,7 @@ const ( // Hibernating state. HibernatingReasonHibernating = string(ClusterPowerStateHibernating) // HibernatingReasonUnsupported is used as the reason when the cluster spec - // specifies that the cluster be moved to a Hibernating state, but either the cluster - // version is not compatible with hibernation (< 4.4.8) or the cloud provider of + // specifies that the cluster be moved to a Hibernating state, but the cloud provider of // the cluster is not supported. HibernatingReasonUnsupported = "Unsupported" // HibernatingReasonFailedToStop is used when there was an error stopping machines @@ -494,6 +537,12 @@ const ( // (It does not necessarily mean they are currently copacetic -- check ClusterSync status // for that.) HibernatingReasonSyncSetsApplied = "SyncSetsApplied" + // HibernatingReasonPowerStatePaused indicates that we can't/won't discover the state of the + // cluster's cloud machines because the powerstate-paused annotation is set. + HibernatingReasonPowerStatePaused = "PowerStatePaused" + // HibernatingReasonClusterDeploymentDeleted indicates that a Cluster Deployment has been deleted + // and that the cluster is deprovisioning unless preserveOnDelete is set to true. + HibernatingReasonClusterDeploymentDeleted = "ClusterDeploymentDeleted" // ReadyReasonStoppingOrHibernating is used as the reason for the Ready condition when the cluster // is stopping or hibernating. Precise details are available in the Hibernating condition. @@ -514,6 +563,12 @@ const ( ReadyReasonWaitingForClusterOperators = string(ClusterPowerStateWaitingForClusterOperators) // ReadyReasonRunning is used on the Ready condition as the reason when the cluster is running and ready ReadyReasonRunning = string(ClusterPowerStateRunning) + // ReadyReasonPowerStatePaused indicates that we can't/won't discover the state of the + // cluster's cloud machines because the powerstate-paused annotation is set. + ReadyReasonPowerStatePaused = "PowerStatePaused" + // ReadyReasonClusterDeploymentDeleted indicates that a Cluster Deployment has been deleted + // and that the cluster is deprovisioning unless preserveOnDelete is set to true. + ReadyReasonClusterDeploymentDeleted = "ClusterDeploymentDeleted" ) // Provisioned status condition reasons @@ -545,7 +600,7 @@ const InitializedConditionReason = "Initialized" // +kubebuilder:printcolumn:name="InfraID",type="string",JSONPath=".spec.clusterMetadata.infraID" // +kubebuilder:printcolumn:name="Platform",type="string",JSONPath=".metadata.labels.hive\\.openshift\\.io/cluster-platform" // +kubebuilder:printcolumn:name="Region",type="string",JSONPath=".metadata.labels.hive\\.openshift\\.io/cluster-region" -// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".metadata.labels.hive\\.openshift\\.io/version-major-minor-patch" +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".metadata.labels.hive\\.openshift\\.io/version" // +kubebuilder:printcolumn:name="ClusterType",type="string",JSONPath=".metadata.labels.hive\\.openshift\\.io/cluster-type" // +kubebuilder:printcolumn:name="ProvisionStatus",type="string",JSONPath=".status.conditions[?(@.type=='Provisioned')].reason" // +kubebuilder:printcolumn:name="PowerState",type="string",JSONPath=".status.powerState" @@ -571,6 +626,9 @@ type ClusterDeploymentList struct { // Platform is the configuration for the specific platform upon which to perform // the installation. Only one of the platform configuration should be set. type Platform struct { + // AlibabaCloud is the configuration used when installing on Alibaba Cloud + AlibabaCloud *alibabacloud.Platform `json:"alibabacloud,omitempty"` + // AWS is the configuration used when installing on AWS. AWS *aws.Platform `json:"aws,omitempty"` @@ -600,6 +658,10 @@ type Platform struct { // IBMCloud is the configuration used when installing on IBM Cloud IBMCloud *ibmcloud.Platform `json:"ibmcloud,omitempty"` + + // None indicates platform-agnostic install. + // https://docs.openshift.com/container-platform/4.7/installing/installing_platform_agnostic/installing-platform-agnostic.html + None *none.Platform `json:"none,omitempty"` } // PlatformStatus contains the observed state for the specific platform upon which to @@ -634,6 +696,10 @@ type ClusterIngress struct { // should be used for this Ingress // +optional ServingCertificate string `json:"servingCertificate,omitempty"` + + // HttpErrorCodePages allows configuring custom HTTP error pages using the IngressController object + // +optional + HttpErrorCodePages *configv1.ConfigMapNameReference `json:"httpErrorCodePages,omitempty"` } // ControlPlaneConfigSpec contains additional configuration settings for a target @@ -650,6 +716,13 @@ type ControlPlaneConfigSpec struct { // active, Hive will use the override URL for further communications with the API server of the remote cluster. // +optional APIURLOverride string `json:"apiURLOverride,omitempty"` + + // APIServerIPOverride is the optional override of the API server IP address. + // Hive will use this IP address for creating TCP connections. + // Port from the original API server URL will be used. + // This field can be used when repointing the APIServer's DNS is not viable option. + // +optional + APIServerIPOverride string `json:"apiServerIPOverride,omitempty"` } // ControlPlaneServingCertificateSpec specifies serving certificate settings for diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go new file mode 100644 index 00000000..8917e756 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go @@ -0,0 +1,99 @@ +package v1 + +import ( + conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // CustomizationApplyReasonSucceeded indicates that the customization + // worked properly on the last applied cluster deployment. + CustomizationApplyReasonSucceeded = "Succeeded" + // CustomizationApplyReasonBrokenSyntax indicates that Hive failed to apply + // customization patches on install-config. More details would be found in + // ApplySucceded condition message. + CustomizationApplyReasonBrokenSyntax = "BrokenBySyntax" + // CustomizationApplyReasonBrokenCloud indicates that cluster deployment provision has failed + // when using this customization. More details would be found in the ApplySucceeded condition message. + CustomizationApplyReasonBrokenCloud = "BrokenByCloud" + // CustomizationApplyReasonInstallationPending indicates that the customization patches have + // been successfully applied but provisioning is not completed yet. + CustomizationApplyReasonInstallationPending = "InstallationPending" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterDeploymentCustomization is the Schema for clusterdeploymentcustomizations API. +// +kubebuilder:subresource:status +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Namespaced +type ClusterDeploymentCustomization struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ClusterDeploymentCustomizationSpec `json:"spec"` + Status ClusterDeploymentCustomizationStatus `json:"status,omitempty"` +} + +// ClusterDeploymentCustomizationSpec defines the desired state of ClusterDeploymentCustomization. +type ClusterDeploymentCustomizationSpec struct { + // InstallConfigPatches is a list of patches to be applied to the install-config. + InstallConfigPatches []PatchEntity `json:"installConfigPatches,omitempty"` +} + +// PatchEntity represent a json patch (RFC 6902) to be applied to the install-config +type PatchEntity struct { + // Op is the operation to perform: add, remove, replace, move, copy, test + // +required + Op string `json:"op"` + // Path is the json path to the value to be modified + // +required + Path string `json:"path"` + // From is the json path to copy or move the value from + // +optional + From string `json:"from,omitempty"` + // Value is the value to be used in the operation + // +required + Value string `json:"value"` +} + +// ClusterDeploymentCustomizationStatus defines the observed state of ClusterDeploymentCustomization. +type ClusterDeploymentCustomizationStatus struct { + // ClusterDeploymentRef is a reference to the cluster deployment that this customization is applied on. + // +optional + ClusterDeploymentRef *corev1.LocalObjectReference `json:"clusterDeploymentRef,omitempty"` + + // ClusterPoolRef is the name of the current cluster pool the CDC used at. + // +optional + ClusterPoolRef *corev1.LocalObjectReference `json:"clusterPoolRef,omitempty"` + + // LastAppliedConfiguration contains the last applied patches to the install-config. + // The information will retain for reference in case the customization is updated. + // +optional + LastAppliedConfiguration string `json:"lastAppliedConfiguration,omitempty"` + + // Conditions describes the state of the operator's reconciliation functionality. + // +patchMergeKey=type + // +patchStrategy=merge + // +optional + Conditions []conditionsv1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +const ( + ApplySucceededCondition conditionsv1.ConditionType = "ApplySucceeded" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterDeploymentCustomizationList contains a list of ClusterDeploymentCustomizations. +type ClusterDeploymentCustomizationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterDeploymentCustomization `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ClusterDeploymentCustomization{}, &ClusterDeploymentCustomizationList{}) +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go index 28342137..2b713675 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go @@ -15,6 +15,14 @@ type ClusterDeprovisionSpec struct { // ClusterID is a globally unique identifier for the cluster to deprovision. It will be used if specified. ClusterID string `json:"clusterID,omitempty"` + // ClusterName is the friendly name of the cluster. It is used for subdomains, + // some resource tagging, and other instances where a friendly name for the + // cluster is useful. + ClusterName string `json:"clusterName,omitempty"` + + // BaseDomain is the DNS base domain. + BaseDomain string `json:"baseDomain,omitempty"` + // Platform contains platform-specific configuration for a ClusterDeprovision Platform ClusterDeprovisionPlatform `json:"platform,omitempty"` } @@ -32,6 +40,8 @@ type ClusterDeprovisionStatus struct { // ClusterDeprovisionPlatform contains platform-specific configuration for the // deprovision type ClusterDeprovisionPlatform struct { + // AlibabaCloud contains Alibaba Cloud specific deprovision settings + AlibabaCloud *AlibabaCloudClusterDeprovision `json:"alibabacloud,omitempty"` // AWS contains AWS-specific deprovision settings AWS *AWSClusterDeprovision `json:"aws,omitempty"` // Azure contains Azure-specific deprovision settings @@ -48,6 +58,17 @@ type ClusterDeprovisionPlatform struct { IBMCloud *IBMClusterDeprovision `json:"ibmcloud,omitempty"` } +// AlibabaCloudClusterDeprovision contains AlibabaCloud-specific configuration for a ClusterDeprovision +type AlibabaCloudClusterDeprovision struct { + // Region is the Alibaba region for this deprovision + Region string `json:"region"` + // BaseDomain is the DNS base domain. + // TODO: Use the non-platform-specific BaseDomain field. + BaseDomain string `json:"baseDomain"` + // CredentialsSecretRef is the Alibaba account credentials to use for deprovisioning the cluster + CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` +} + // AWSClusterDeprovision contains AWS-specific configuration for a ClusterDeprovision type AWSClusterDeprovision struct { // Region is the AWS region for this deprovisioning @@ -61,6 +82,11 @@ type AWSClusterDeprovision struct { // AWS account access for deprovisioning the cluster. // +optional CredentialsAssumeRole *aws.AssumeRole `json:"credentialsAssumeRole,omitempty"` + + // HostedZoneRole is the role to assume when performing operations + // on a hosted zone owned by another account. + // +optional + HostedZoneRole *string `json:"hostedZoneRole,omitempty"` } // AzureClusterDeprovision contains Azure-specific configuration for a ClusterDeprovision @@ -72,6 +98,10 @@ type AzureClusterDeprovision struct { // If empty, the value is equal to "AzurePublicCloud". // +optional CloudName *azure.CloudEnvironment `json:"cloudName,omitempty"` + // ResourceGroupName is the name of the resource group where the cluster was installed. + // Required for new deprovisions (schema notwithstanding). + // +optional + ResourceGroupName *string `json:"resourceGroupName,omitempty"` } // GCPClusterDeprovision contains GCP-specific configuration for a ClusterDeprovision @@ -80,6 +110,10 @@ type GCPClusterDeprovision struct { Region string `json:"region"` // CredentialsSecretRef is the GCP account credentials to use for deprovisioning the cluster CredentialsSecretRef *corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"` + + // NetworkProjectID is used for shared VPC setups + // +optional + NetworkProjectID *string `json:"networkProjectID,omitempty"` } // OpenStackClusterDeprovision contains OpenStack-specific configuration for a ClusterDeprovision @@ -122,13 +156,10 @@ type OvirtClusterDeprovision struct { type IBMClusterDeprovision struct { // CredentialsSecretRef is the IBM Cloud credentials to use for deprovisioning the cluster CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` - // AccountID is the IBM Cloud Account ID - AccountID string `json:"accountID"` - // CISInstanceCRN is the IBM Cloud Internet Services Instance CRN - CISInstanceCRN string `json:"cisInstanceCRN"` // Region specifies the IBM Cloud region Region string `json:"region"` - // BaseDomain is the DNS base domain + // BaseDomain is the DNS base domain. + // TODO: Use the non-platform-specific BaseDomain field. BaseDomain string `json:"baseDomain"` } @@ -174,6 +205,16 @@ type ClusterDeprovisionCondition struct { // ClusterDeprovisionConditionType is a valid value for ClusterDeprovisionCondition.Type type ClusterDeprovisionConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c ClusterDeprovisionCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t ClusterDeprovisionConditionType) String() string { + return string(t) +} + const ( // AuthenticationFailureClusterDeprovisionCondition is true when credentials cannot be used because of authentication failure AuthenticationFailureClusterDeprovisionCondition ClusterDeprovisionConditionType = "AuthenticationFailure" diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterinstall_conditions.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterinstall_conditions.go index 8ec30212..088d586d 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterinstall_conditions.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterinstall_conditions.go @@ -10,7 +10,7 @@ import ( // ClusterInstallCondition contains details for the current condition of a cluster install. type ClusterInstallCondition struct { // Type is the type of the condition. - Type string `json:"type"` + Type ClusterInstallConditionType `json:"type"` // Status is the status of the condition. Status corev1.ConditionStatus `json:"status"` // LastProbeTime is the last time we probed the condition. @@ -27,20 +27,32 @@ type ClusterInstallCondition struct { Message string `json:"message,omitempty"` } +type ClusterInstallConditionType string + +// ConditionType satisfies the conditions.Condition interface +func (c ClusterInstallCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t ClusterInstallConditionType) String() string { + return string(t) +} + const ( // ClusterInstallRequirementsMet is True when all pre-install requirements have been met. - ClusterInstallRequirementsMet = "RequirementsMet" + ClusterInstallRequirementsMet ClusterInstallConditionType = "RequirementsMet" // ClusterInstallCompleted is True when the requested install has been completed successfully. - ClusterInstallCompleted = "Completed" + ClusterInstallCompleted ClusterInstallConditionType = "Completed" // ClusterInstallFailed is True when an attempt to install the cluster has failed. // The ClusterInstall controllers may still be retrying if supported, and this condition will // go back to False if a later attempt succeeds. - ClusterInstallFailed = "Failed" + ClusterInstallFailed ClusterInstallConditionType = "Failed" // ClusterInstallStopped is True the controllers are no longer working on this // ClusterInstall. Combine with Completed or Failed to know if the overall request was // successful or not. - ClusterInstallStopped = "Stopped" + ClusterInstallStopped ClusterInstallConditionType = "Stopped" ) diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go index 06bde7e1..577a0086 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go @@ -92,6 +92,11 @@ type ClusterPoolSpec struct { // HibernationConfig configures the hibernation/resume behavior of ClusterDeployments owned by the ClusterPool. // +optional HibernationConfig *HibernationConfig `json:"hibernationConfig"` + + // Inventory maintains a list of entries consumed by the ClusterPool + // to customize the default ClusterDeployment. + // +optional + Inventory []InventoryEntry `json:"inventory,omitempty"` } type HibernationConfig struct { @@ -110,6 +115,22 @@ type HibernationConfig struct { ResumeTimeout metav1.Duration `json:"resumeTimeout"` } +// InventoryEntryKind is the Kind of the inventory entry. +// +kubebuilder:validation:Enum="";ClusterDeploymentCustomization +type InventoryEntryKind string + +const ClusterDeploymentCustomizationInventoryEntry InventoryEntryKind = "ClusterDeploymentCustomization" + +// InventoryEntry maintains a reference to a custom resource consumed by a clusterpool to customize the cluster deployment. +type InventoryEntry struct { + // Kind denotes the kind of the referenced resource. The default is ClusterDeploymentCustomization, which is also currently the only supported value. + // +kubebuilder:default=ClusterDeploymentCustomization + Kind InventoryEntryKind `json:"kind,omitempty"` + // Name is the name of the referenced resource. + // +required + Name string `json:"name,omitempty"` +} + // ClusterPoolClaimLifetime defines the lifetimes for claims for the cluster pool. type ClusterPoolClaimLifetime struct { // Default is the default lifetime of the claim when no lifetime is set on the claim itself. @@ -177,6 +198,16 @@ type ClusterPoolCondition struct { // ClusterPoolConditionType is a valid value for ClusterPoolCondition.Type type ClusterPoolConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c ClusterPoolCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t ClusterPoolConditionType) String() string { + return string(t) +} + const ( // ClusterPoolMissingDependenciesCondition is set when a cluster pool is missing dependencies required to create a // cluster. Dependencies include resources such as the ClusterImageSet and the credentials Secret. @@ -187,6 +218,20 @@ const ( // ClusterPoolAllClustersCurrentCondition indicates whether all unassigned (installing or ready) // ClusterDeployments in the pool match the current configuration of the ClusterPool. ClusterPoolAllClustersCurrentCondition ClusterPoolConditionType = "AllClustersCurrent" + // ClusterPoolInventoryValidCondition is set to provide information on whether the cluster pool inventory is valid. + ClusterPoolInventoryValidCondition ClusterPoolConditionType = "InventoryValid" + // ClusterPoolDeletionPossibleCondition gives information about a deleted ClusterPool which is pending cleanup. + // Note that it is normal for this condition to remain Initialized/Unknown until the ClusterPool is deleted. + ClusterPoolDeletionPossibleCondition ClusterPoolConditionType = "DeletionPossible" +) + +const ( + // InventoryReasonValid is used when all ClusterDeploymentCustomization are + // available and when used the ClusterDeployments are successfully installed. + InventoryReasonValid = "Valid" + // InventoryReasonInvalid is used when there is something wrong with ClusterDeploymentCustomization, for example + // patching issue, provisioning failure, missing, etc. + InventoryReasonInvalid = "Invalid" ) // +genclient diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterprovision_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterprovision_types.go index b6274443..2382c833 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterprovision_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterprovision_types.go @@ -31,8 +31,16 @@ type ClusterProvisionSpec struct { InstallLog *string `json:"installLog,omitempty"` // Metadata is the metadata.json generated by the installer, providing metadata information about the cluster created. + // NOTE: This is not used because it didn't work (it was always empty). We think because the thing it's storing + // (ClusterMetadata from installer) is not a runtime.Object, so can't be put in a RawExtension. Metadata *runtime.RawExtension `json:"metadata,omitempty"` + // MetadataJSON is a JSON representation of the ClusterMetadata produced by the installer. We don't use a + // runtime.RawExtension because ClusterMetadata isn't a runtime.Object. We don't use ClusterMetadata itself + // because we don't want our API consumers to need to pull in the installer code and its dependencies. + // +optional + MetadataJSON []byte `json:"metadataJSON,omitempty"` + // AdminKubeconfigSecretRef references the secret containing the admin kubeconfig for this cluster. AdminKubeconfigSecretRef *corev1.LocalObjectReference `json:"adminKubeconfigSecretRef,omitempty"` @@ -96,6 +104,16 @@ type ClusterProvisionCondition struct { // ClusterProvisionConditionType is a valid value for ClusterProvisionCondition.Type type ClusterProvisionConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c ClusterProvisionCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t ClusterProvisionConditionType) String() string { + return string(t) +} + const ( // ClusterProvisionInitializedCondition is set when a cluster provision has finished initialization. ClusterProvisionInitializedCondition ClusterProvisionConditionType = "ClusterProvisionInitialized" diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/conditions.go b/vendor/github.com/openshift/hive/apis/hive/v1/conditions.go new file mode 100644 index 00000000..0a8bc956 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/conditions.go @@ -0,0 +1,11 @@ +package v1 + +import "fmt" + +type Condition interface { + ConditionType() ConditionType +} + +type ConditionType interface { + fmt.Stringer +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/dnszone_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/dnszone_types.go index a2315138..9ebd599b 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/dnszone_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/dnszone_types.go @@ -179,6 +179,16 @@ type DNSZoneCondition struct { // DNSZoneConditionType is a valid value for DNSZoneCondition.Type type DNSZoneConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c DNSZoneCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t DNSZoneConditionType) String() string { + return string(t) +} + const ( // ZoneAvailableDNSZoneCondition is true if the DNSZone is responding to DNS queries ZoneAvailableDNSZoneCondition DNSZoneConditionType = "ZoneAvailable" diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go index 283099f2..c8a595b2 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go @@ -13,6 +13,18 @@ type MachinePool struct { // // +optional OSDisk OSDisk `json:"osDisk"` + + // NetworkProjectID specifies which project the network and subnets exist in when + // they are not in the main ProjectID. + // +optional + NetworkProjectID string `json:"networkProjectID,omitempty"` + + // SecureBoot Defines whether the instance should have secure boot enabled. + // Verifies the digital signature of all boot components, and halts the boot process if signature verification fails. + // If omitted, the platform chooses a default, which is subject to change over time. Currently that default is "Disabled". + // +kubebuilder:validation:Enum=Enabled;Disabled + // +optional + SecureBoot string `json:"secureBoot,omitempty"` } // OSDisk defines the disk for machines on GCP. diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go index fcdc59e6..55678313 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go @@ -2,6 +2,7 @@ package gcp // Metadata contains GCP metadata (e.g. for uninstalling the cluster). type Metadata struct { - Region string `json:"region"` - ProjectID string `json:"projectID"` + // NetworkProjectID is used for shared VPC setups + // +optional + NetworkProjectID *string `json:"networkProjectID,omitempty"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go index ae6087f2..30b4a9df 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go @@ -67,6 +67,11 @@ func (in *MachinePool) DeepCopy() *MachinePool { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Metadata) DeepCopyInto(out *Metadata) { *out = *in + if in.NetworkProjectID != nil { + in, out := &in.NetworkProjectID, &out.NetworkProjectID + *out = new(string) + **out = **in + } return } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go index a0dbb70e..034d267d 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go @@ -5,6 +5,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openshift/hive/apis/hive/v1/azure" + "github.com/openshift/hive/apis/hive/v1/metricsconfig" ) // HiveConfigSpec defines the desired state of Hive @@ -89,6 +90,10 @@ type HiveConfigSpec struct { // +optional ControllersConfig *ControllersConfig `json:"controllersConfig,omitempty"` + // DeploymentConfig is used to configure (pods/containers of) the Deployments generated by hive-operator. + // +optional + DeploymentConfig *[]DeploymentConfig `json:"deploymentConfig,omitempty"` + // AWSPrivateLink defines the configuration for the aws-private-link controller. // It provides 3 major pieces of information required by the controller, // 1. The Credentials that should be used to create AWS PrivateLink resources other than @@ -138,12 +143,19 @@ type HiveConfigSpec struct { FeatureGates *FeatureGateSelection `json:"featureGates,omitempty"` - // ExportMetrics specifies whether the operator should enable metrics for hive controllers - // to be extracted for prometheus. - // When set to true, the operator deploys ServiceMonitors so that the prometheus instances that - // extract metrics. The operator also sets up RBAC in the TargetNamespace so that openshift - // prometheus in the cluster can list/access objects required to pull metrics. + // ExportMetrics has been disabled and has no effect. If upgrading from a version where it was + // active, please be aware of the following in your HiveConfig.Spec.TargetNamespace (default + // `hive` if unset): + // 1) ServiceMonitors named hive-controllers and hive-clustersync; + // 2) Role and RoleBinding named prometheus-k8s; + // 3) The `openshift.io/cluster-monitoring` metadata.label on the Namespace itself. + // You may wish to delete these resources. Or you may wish to continue using them to enable + // monitoring in your environment; but be aware that hive will no longer reconcile them. ExportMetrics bool `json:"exportMetrics,omitempty"` + + // MetricsConfig encapsulates metrics specific configurations, like opting in for certain metrics. + // +optional + MetricsConfig *metricsconfig.MetricsConfig `json:"metricsConfig,omitempty"` } // ReleaseImageVerificationConfigMapReference is a reference to the ConfigMap that @@ -594,6 +606,27 @@ type ControllersConfig struct { Controllers []SpecificControllerConfig `json:"controllers,omitempty"` } +type DeploymentName string + +const ( + DeploymentNameControllers DeploymentName = "hive-controllers" + DeploymentNameClustersync DeploymentName = "hive-clustersync" + DeploymentNameAdmission DeploymentName = "hiveadmission" +) + +type DeploymentConfig struct { + // DeploymentName is the name of one of the Deployments/StatefulSets managed by hive-operator. + // NOTE: At this time each deployment has only one container. In the future, we may provide a + // way to specify which container this DeploymentConfig will be applied to. + // +kubebuilder:validation:Enum=hive-controllers;hive-clustersync;hiveadmission + DeploymentName DeploymentName `json:"deploymentName"` + + // Resources allows customization of the resource (memory, CPU, etc.) limits and requests used + // by containers in the Deployment/StatefulSet named by DeploymentName. + // +optional + Resources *corev1.ResourceRequirements `json:"resources"` +} + // +genclient:nonNamespaced // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/platform.go index 1a564570..1de24acb 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/platform.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/platform.go @@ -9,13 +9,16 @@ type Platform struct { // CredentialsSecretRef refers to a secret that contains IBM Cloud account access // credentials. CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` - - // AccountID is the IBM Cloud Account ID - AccountID string `json:"accountID"` - + // AccountID is the IBM Cloud Account ID. + // AccountID is DEPRECATED and is gathered via the IBM Cloud API for the provided + // credentials. This field will be ignored. + // +optional + AccountID string `json:"accountID,omitempty"` // CISInstanceCRN is the IBM Cloud Internet Services Instance CRN - CISInstanceCRN string `json:"cisInstanceCRN"` - + // CISInstanceCRN is DEPRECATED and gathered via the IBM Cloud API for the provided + // credentials and cluster deployment base domain. This field will be ignored. + // +optional + CISInstanceCRN string `json:"cisInstanceCRN,omitempty"` // Region specifies the IBM Cloud region where the cluster will be // created. Region string `json:"region"` diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go index 3dc0b061..7210abfa 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go @@ -1,6 +1,7 @@ package v1 import ( + "github.com/openshift/hive/apis/hive/v1/alibabacloud" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -15,7 +16,7 @@ import ( const ( // MachinePoolImageIDOverrideAnnotation can be applied to MachinePools to control the precise image ID to be used - // for the MachineSets we reconcile for this pool. This feature is presently only implemented for AWS, and + // for the MachineSets we reconcile for this pool. This feature is presently only implemented for AWS and GCP, and // is intended for very limited use cases we do not recommend pursuing regularly. As such it is not currently // part of our official API. MachinePoolImageIDOverrideAnnotation = "hive.openshift.io/image-id-override" @@ -53,6 +54,9 @@ type MachinePoolSpec struct { // List of taints that will be applied to the created MachineSet's MachineSpec. // This list will overwrite any modifications made to Node taints on an ongoing basis. + // In case of duplicate entries, first encountered taint Value will be preserved, + // and the rest collapsed on the corresponding MachineSets. + // Note that taints are uniquely identified based on key+effect, not just key. // +optional Taints []corev1.Taint `json:"taints,omitempty"` } @@ -69,6 +73,8 @@ type MachinePoolAutoscaling struct { // MachinePoolPlatform is the platform-specific configuration for a machine // pool. Only one of the platforms should be set. type MachinePoolPlatform struct { + // AlibabaCloud is the configuration used when installing on Alibaba Cloud. + AlibabaCloud *alibabacloud.MachinePool `json:"alibabacloud,omitempty"` // AWS is the configuration used when installing on AWS. AWS *aws.MachinePoolPlatform `json:"aws,omitempty"` // Azure is the configuration used when installing on Azure. @@ -97,6 +103,26 @@ type MachinePoolStatus struct { // Conditions includes more detailed status for the cluster deployment // +optional Conditions []MachinePoolCondition `json:"conditions,omitempty"` + + // OwnedLabels lists the keys of labels this MachinePool created on the remote MachineSet. + // Used to identify labels to remove from the remote MachineSet when they are absent from + // the MachinePool's spec.labels. + // +optional + OwnedLabels []string `json:"ownedLabels,omitempty"` + // OwnedTaints lists identifiers of taints this MachinePool created on the remote MachineSet. + // Used to identify taints to remove from the remote MachineSet when they are absent from + // the MachinePool's spec.taints. + // +optional + OwnedTaints []TaintIdentifier `json:"ownedTaints,omitempty"` +} + +// TaintIdentifier uniquely identifies a Taint. (It turns out taints are mutually exclusive by +// key+effect, not simply by key.) +type TaintIdentifier struct { + // Key matches corev1.Taint.Key. + Key string `json:"key,omitempty"` + // Effect matches corev1.Taint.Effect. + Effect corev1.TaintEffect `json:"effect,omitempty"` } // MachineSetStatus is the status of a machineset in the remote cluster. @@ -153,6 +179,16 @@ type MachinePoolCondition struct { // MachinePoolConditionType is a valid value for MachinePoolCondition.Type type MachinePoolConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c MachinePoolCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t MachinePoolConditionType) String() string { + return string(t) +} + const ( // NotEnoughReplicasMachinePoolCondition is true when the minReplicas field // is set too low for the number of machinesets for the machine pool. diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go new file mode 100644 index 00000000..422f98a2 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go @@ -0,0 +1,4 @@ +// Package metricsconfig contains API Schema definitions for configurations specific to metrics controller. +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +package metricsconfig diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/duration_metrics.go b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/duration_metrics.go new file mode 100644 index 00000000..e81f3f94 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/duration_metrics.go @@ -0,0 +1,41 @@ +package metricsconfig + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// MetricsWithDuration represents metrics that report time as values,like transition seconds. +// The purpose of these metrics should be to track outliers - ensure their duration is not set too low. +type MetricsWithDuration struct { + // Name of the metric. It will correspond to an optional relevant metric in hive + // +kubebuilder:validation:Enum=currentStopping;currentResuming;currentWaitingForCO;currentClusterSyncFailing;cumulativeHibernated;cumulativeResumed + Name DurationMetricType `json:"name"` + // Duration is the minimum time taken - the relevant metric will be logged only if the value reported by that metric + // is more than the time mentioned here. For example, if a user opts-in for current clusters stopping and mentions + // 1 hour here, only the clusters stopping for more than an hour will be reported. + // This is a Duration value; see https://pkg.go.dev/time#ParseDuration for accepted formats. + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + Duration *metav1.Duration `json:"duration"` +} + +// DurationMetricType is a valid value for MetricsWithDuration.Name +type DurationMetricType string + +const ( + // Metrics logged per cluster + + // CurrentStopping corresponds to hive_cluster_deployments_stopping_seconds + CurrentStopping DurationMetricType = "currentStopping" + // CurrentResuming corresponds to hive_cluster_deployments_resuming_seconds + CurrentResuming DurationMetricType = "currentResuming" + // CurrentWaitingForCO corresponds to hive_cluster_deployments_waiting_for_cluster_operators_seconds + CurrentWaitingForCO DurationMetricType = "currentWaitingForCO" + // CurrentClusterSyncFailing corresponds to hive_clustersync_failing_seconds + CurrentClusterSyncFailing DurationMetricType = "currentClusterSyncFailing" + + // These metrics will not be cleared and can potentially blow up the cardinality + + // CumulativeHibernated corresponds to hive_cluster_deployment_hibernation_transition_seconds + CumulativeHibernated DurationMetricType = "cumulativeHibernated" + // CumulativeResumed corresponds to hive_cluster_deployment_running_transition_seconds + CumulativeResumed DurationMetricType = "cumulativeResumed" +) diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/metrics_config.go b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/metrics_config.go new file mode 100644 index 00000000..7a85e3e0 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/metrics_config.go @@ -0,0 +1,20 @@ +package metricsconfig + +type MetricsConfig struct { + // Optional metrics and their configurations + // +optional + MetricsWithDuration []MetricsWithDuration `json:"metricsWithDuration,omitempty"` + // AdditionalClusterDeploymentLabels allows configuration of additional labels to be applied to certain metrics. + // The keys can be any string value suitable for a metric label (see https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels). + // The values can be any ClusterDeployment label key (from metadata.labels). When observing an affected metric, + // hive will label it with the specified metric key, and copy the value from the specified ClusterDeployment label. + // For example, including {"ocp_major_version": "hive.openshift.io/version-major"} will cause affected metrics to + // include a label key ocp_major_version with the value from the hive.openshift.io/version-major ClusterDeployment + // label -- e.g. "4". + // NOTE: Avoid ClusterDeployment labels whose values are unbounded, such as those representing cluster names or IDs, + // as these will cause your prometheus database to grow indefinitely. + // Affected metrics are those whose type implements the metricsWithDynamicLabels interface found in + // pkg/controller/metrics/metrics_with_dynamic_labels.go + // +optional + AdditionalClusterDeploymentLabels *map[string]string `json:"additionalClusterDeploymentLabels,omitempty"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/zz_generated.deepcopy.go new file mode 100644 index 00000000..2f657023 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/zz_generated.deepcopy.go @@ -0,0 +1,65 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package metricsconfig + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetricsConfig) DeepCopyInto(out *MetricsConfig) { + *out = *in + if in.MetricsWithDuration != nil { + in, out := &in.MetricsWithDuration, &out.MetricsWithDuration + *out = make([]MetricsWithDuration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AdditionalClusterDeploymentLabels != nil { + in, out := &in.AdditionalClusterDeploymentLabels, &out.AdditionalClusterDeploymentLabels + *out = new(map[string]string) + if **in != nil { + in, out := *in, *out + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsConfig. +func (in *MetricsConfig) DeepCopy() *MetricsConfig { + if in == nil { + return nil + } + out := new(MetricsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetricsWithDuration) DeepCopyInto(out *MetricsWithDuration) { + *out = *in + if in.Duration != nil { + in, out := &in.Duration, &out.Duration + *out = new(v1.Duration) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsWithDuration. +func (in *MetricsWithDuration) DeepCopy() *MetricsWithDuration { + if in == nil { + return nil + } + out := new(MetricsWithDuration) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go new file mode 100644 index 00000000..f2bb8992 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go @@ -0,0 +1,4 @@ +// Package none contains API Schema definitions for platform-agnostic installations. +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +package none diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/none/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/none/platform.go new file mode 100644 index 00000000..e80ef0f0 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/none/platform.go @@ -0,0 +1,6 @@ +package none + +// Platform defines agent based install configuration for platform-agnostic clusters. +// Can only be used with spec.installStrategy.agent. +type Platform struct { +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/none/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/none/zz_generated.deepcopy.go new file mode 100644 index 00000000..e474004e --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/none/zz_generated.deepcopy.go @@ -0,0 +1,22 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package none + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Platform) DeepCopyInto(out *Platform) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Platform. +func (in *Platform) DeepCopy() *Platform { + if in == nil { + return nil + } + out := new(Platform) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go index cabc7fbb..fafdc9d9 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go @@ -106,6 +106,16 @@ type SecretMapping struct { // SyncConditionType is a valid value for SyncCondition.Type type SyncConditionType string +// ConditionType satisfies the conditions.Condition interface +func (c SyncCondition) ConditionType() ConditionType { + return c.Type +} + +// String satisfies the conditions.ConditionType interface +func (t SyncConditionType) String() string { + return string(t) +} + const ( // ApplySuccessSyncCondition indicates whether the resource or patch has been applied. ApplySuccessSyncCondition SyncConditionType = "ApplySuccess" diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go index 95ca854e..71e67294 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go @@ -3,6 +3,11 @@ package vsphere // MachinePool stores the configuration for a machine pool installed // on vSphere. type MachinePool struct { + // ResourcePool is the name of the resource pool that will be used for virtual machines. + // If it is not present, a default value will be used. + // +optional + ResourcePool string `json:"resourcePool,omitempty"` + // NumCPUs is the total number of virtual processor cores to assign a vm. NumCPUs int32 `json:"cpus"` diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go index dfdd9fbe..4e455420 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go @@ -7,12 +7,16 @@ package v1 import ( configv1 "github.com/openshift/api/config/v1" + conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" agent "github.com/openshift/hive/apis/hive/v1/agent" + alibabacloud "github.com/openshift/hive/apis/hive/v1/alibabacloud" aws "github.com/openshift/hive/apis/hive/v1/aws" azure "github.com/openshift/hive/apis/hive/v1/azure" baremetal "github.com/openshift/hive/apis/hive/v1/baremetal" gcp "github.com/openshift/hive/apis/hive/v1/gcp" ibmcloud "github.com/openshift/hive/apis/hive/v1/ibmcloud" + metricsconfig "github.com/openshift/hive/apis/hive/v1/metricsconfig" + none "github.com/openshift/hive/apis/hive/v1/none" openstack "github.com/openshift/hive/apis/hive/v1/openstack" ovirt "github.com/openshift/hive/apis/hive/v1/ovirt" vsphere "github.com/openshift/hive/apis/hive/v1/vsphere" @@ -57,6 +61,11 @@ func (in *AWSClusterDeprovision) DeepCopyInto(out *AWSClusterDeprovision) { *out = new(aws.AssumeRole) **out = **in } + if in.HostedZoneRole != nil { + in, out := &in.HostedZoneRole, &out.HostedZoneRole + *out = new(string) + **out = **in + } return } @@ -236,6 +245,23 @@ func (in *AWSServiceProviderCredentials) DeepCopy() *AWSServiceProviderCredentia return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AlibabaCloudClusterDeprovision) DeepCopyInto(out *AlibabaCloudClusterDeprovision) { + *out = *in + out.CredentialsSecretRef = in.CredentialsSecretRef + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaCloudClusterDeprovision. +func (in *AlibabaCloudClusterDeprovision) DeepCopy() *AlibabaCloudClusterDeprovision { + if in == nil { + return nil + } + out := new(AlibabaCloudClusterDeprovision) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ArgoCDConfig) DeepCopyInto(out *ArgoCDConfig) { *out = *in @@ -265,6 +291,11 @@ func (in *AzureClusterDeprovision) DeepCopyInto(out *AzureClusterDeprovision) { *out = new(azure.CloudEnvironment) **out = **in } + if in.ResourceGroupName != nil { + in, out := &in.ResourceGroupName, &out.ResourceGroupName + *out = new(string) + **out = **in + } return } @@ -656,6 +687,121 @@ func (in *ClusterDeploymentCondition) DeepCopy() *ClusterDeploymentCondition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterDeploymentCustomization) DeepCopyInto(out *ClusterDeploymentCustomization) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDeploymentCustomization. +func (in *ClusterDeploymentCustomization) DeepCopy() *ClusterDeploymentCustomization { + if in == nil { + return nil + } + out := new(ClusterDeploymentCustomization) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterDeploymentCustomization) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterDeploymentCustomizationList) DeepCopyInto(out *ClusterDeploymentCustomizationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterDeploymentCustomization, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDeploymentCustomizationList. +func (in *ClusterDeploymentCustomizationList) DeepCopy() *ClusterDeploymentCustomizationList { + if in == nil { + return nil + } + out := new(ClusterDeploymentCustomizationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterDeploymentCustomizationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterDeploymentCustomizationSpec) DeepCopyInto(out *ClusterDeploymentCustomizationSpec) { + *out = *in + if in.InstallConfigPatches != nil { + in, out := &in.InstallConfigPatches, &out.InstallConfigPatches + *out = make([]PatchEntity, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDeploymentCustomizationSpec. +func (in *ClusterDeploymentCustomizationSpec) DeepCopy() *ClusterDeploymentCustomizationSpec { + if in == nil { + return nil + } + out := new(ClusterDeploymentCustomizationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterDeploymentCustomizationStatus) DeepCopyInto(out *ClusterDeploymentCustomizationStatus) { + *out = *in + if in.ClusterDeploymentRef != nil { + in, out := &in.ClusterDeploymentRef, &out.ClusterDeploymentRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.ClusterPoolRef != nil { + in, out := &in.ClusterPoolRef, &out.ClusterPoolRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]conditionsv1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDeploymentCustomizationStatus. +func (in *ClusterDeploymentCustomizationStatus) DeepCopy() *ClusterDeploymentCustomizationStatus { + if in == nil { + return nil + } + out := new(ClusterDeploymentCustomizationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterDeploymentList) DeepCopyInto(out *ClusterDeploymentList) { *out = *in @@ -902,6 +1048,11 @@ func (in *ClusterDeprovisionList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterDeprovisionPlatform) DeepCopyInto(out *ClusterDeprovisionPlatform) { *out = *in + if in.AlibabaCloud != nil { + in, out := &in.AlibabaCloud, &out.AlibabaCloud + *out = new(AlibabaCloudClusterDeprovision) + **out = **in + } if in.AWS != nil { in, out := &in.AWS, &out.AWS *out = new(AWSClusterDeprovision) @@ -1112,6 +1263,11 @@ func (in *ClusterIngress) DeepCopyInto(out *ClusterIngress) { *out = new(metav1.LabelSelector) (*in).DeepCopyInto(*out) } + if in.HttpErrorCodePages != nil { + in, out := &in.HttpErrorCodePages, &out.HttpErrorCodePages + *out = new(configv1.ConfigMapNameReference) + **out = **in + } return } @@ -1168,6 +1324,11 @@ func (in *ClusterMetadata) DeepCopyInto(out *ClusterMetadata) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.Platform != nil { + in, out := &in.Platform, &out.Platform + *out = new(ClusterPlatformMetadata) + (*in).DeepCopyInto(*out) + } return } @@ -1204,6 +1365,37 @@ func (in *ClusterOperatorState) DeepCopy() *ClusterOperatorState { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterPlatformMetadata) DeepCopyInto(out *ClusterPlatformMetadata) { + *out = *in + if in.AWS != nil { + in, out := &in.AWS, &out.AWS + *out = new(aws.Metadata) + (*in).DeepCopyInto(*out) + } + if in.Azure != nil { + in, out := &in.Azure, &out.Azure + *out = new(azure.Metadata) + (*in).DeepCopyInto(*out) + } + if in.GCP != nil { + in, out := &in.GCP, &out.GCP + *out = new(gcp.Metadata) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPlatformMetadata. +func (in *ClusterPlatformMetadata) DeepCopy() *ClusterPlatformMetadata { + if in == nil { + return nil + } + out := new(ClusterPlatformMetadata) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterPool) DeepCopyInto(out *ClusterPool) { *out = *in @@ -1316,6 +1508,11 @@ func (in *ClusterPoolReference) DeepCopyInto(out *ClusterPoolReference) { in, out := &in.ClaimedTimestamp, &out.ClaimedTimestamp *out = (*in).DeepCopy() } + if in.CustomizationRef != nil { + in, out := &in.CustomizationRef, &out.CustomizationRef + *out = new(corev1.LocalObjectReference) + **out = **in + } return } @@ -1388,6 +1585,11 @@ func (in *ClusterPoolSpec) DeepCopyInto(out *ClusterPoolSpec) { *out = new(HibernationConfig) **out = **in } + if in.Inventory != nil { + in, out := &in.Inventory, &out.Inventory + *out = make([]InventoryEntry, len(*in)) + copy(*out, *in) + } return } @@ -1528,6 +1730,11 @@ func (in *ClusterProvisionSpec) DeepCopyInto(out *ClusterProvisionSpec) { *out = new(runtime.RawExtension) (*in).DeepCopyInto(*out) } + if in.MetadataJSON != nil { + in, out := &in.MetadataJSON, &out.MetadataJSON + *out = make([]byte, len(*in)) + copy(*out, *in) + } if in.AdminKubeconfigSecretRef != nil { in, out := &in.AdminKubeconfigSecretRef, &out.AdminKubeconfigSecretRef *out = new(corev1.LocalObjectReference) @@ -2098,6 +2305,27 @@ func (in *DNSZoneStatus) DeepCopy() *DNSZoneStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentConfig) DeepCopyInto(out *DeploymentConfig) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(corev1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentConfig. +func (in *DeploymentConfig) DeepCopy() *DeploymentConfig { + if in == nil { + return nil + } + out := new(DeploymentConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FailedProvisionAWSConfig) DeepCopyInto(out *FailedProvisionAWSConfig) { *out = *in @@ -2195,6 +2423,11 @@ func (in *GCPClusterDeprovision) DeepCopyInto(out *GCPClusterDeprovision) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.NetworkProjectID != nil { + in, out := &in.NetworkProjectID, &out.NetworkProjectID + *out = new(string) + **out = **in + } return } @@ -2385,6 +2618,17 @@ func (in *HiveConfigSpec) DeepCopyInto(out *HiveConfigSpec) { *out = new(ControllersConfig) (*in).DeepCopyInto(*out) } + if in.DeploymentConfig != nil { + in, out := &in.DeploymentConfig, &out.DeploymentConfig + *out = new([]DeploymentConfig) + if **in != nil { + in, out := *in, *out + *out = make([]DeploymentConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } if in.AWSPrivateLink != nil { in, out := &in.AWSPrivateLink, &out.AWSPrivateLink *out = new(AWSPrivateLinkConfig) @@ -2401,6 +2645,11 @@ func (in *HiveConfigSpec) DeepCopyInto(out *HiveConfigSpec) { *out = new(FeatureGateSelection) (*in).DeepCopyInto(*out) } + if in.MetricsConfig != nil { + in, out := &in.MetricsConfig, &out.MetricsConfig + *out = new(metricsconfig.MetricsConfig) + (*in).DeepCopyInto(*out) + } return } @@ -2470,6 +2719,22 @@ func (in *IdentityProviderStatus) DeepCopy() *IdentityProviderStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InventoryEntry) DeepCopyInto(out *InventoryEntry) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InventoryEntry. +func (in *InventoryEntry) DeepCopy() *InventoryEntry { + if in == nil { + return nil + } + out := new(InventoryEntry) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubeconfigSecretReference) DeepCopyInto(out *KubeconfigSecretReference) { *out = *in @@ -2677,6 +2942,11 @@ func (in *MachinePoolNameLeaseStatus) DeepCopy() *MachinePoolNameLeaseStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachinePoolPlatform) DeepCopyInto(out *MachinePoolPlatform) { *out = *in + if in.AlibabaCloud != nil { + in, out := &in.AlibabaCloud, &out.AlibabaCloud + *out = new(alibabacloud.MachinePool) + (*in).DeepCopyInto(*out) + } if in.AWS != nil { in, out := &in.AWS, &out.AWS *out = new(aws.MachinePoolPlatform) @@ -2784,6 +3054,16 @@ func (in *MachinePoolStatus) DeepCopyInto(out *MachinePoolStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OwnedLabels != nil { + in, out := &in.OwnedLabels, &out.OwnedLabels + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.OwnedTaints != nil { + in, out := &in.OwnedTaints, &out.OwnedTaints + *out = make([]TaintIdentifier, len(*in)) + copy(*out, *in) + } return } @@ -2954,9 +3234,30 @@ func (in *OvirtClusterDeprovision) DeepCopy() *OvirtClusterDeprovision { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PatchEntity) DeepCopyInto(out *PatchEntity) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PatchEntity. +func (in *PatchEntity) DeepCopy() *PatchEntity { + if in == nil { + return nil + } + out := new(PatchEntity) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Platform) DeepCopyInto(out *Platform) { *out = *in + if in.AlibabaCloud != nil { + in, out := &in.AlibabaCloud, &out.AlibabaCloud + *out = new(alibabacloud.Platform) + **out = **in + } if in.AWS != nil { in, out := &in.AWS, &out.AWS *out = new(aws.Platform) @@ -3002,6 +3303,11 @@ func (in *Platform) DeepCopyInto(out *Platform) { *out = new(ibmcloud.Platform) **out = **in } + if in.None != nil { + in, out := &in.None, &out.None + *out = new(none.Platform) + **out = **in + } return } @@ -3054,6 +3360,11 @@ func (in *Provisioning) DeepCopyInto(out *Provisioning) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.ManifestsSecretRef != nil { + in, out := &in.ManifestsSecretRef, &out.ManifestsSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } if in.SSHPrivateKeySecretRef != nil { in, out := &in.SSHPrivateKeySecretRef, &out.SSHPrivateKeySecretRef *out = new(corev1.LocalObjectReference) @@ -3685,6 +3996,22 @@ func (in *SyncStatus) DeepCopy() *SyncStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TaintIdentifier) DeepCopyInto(out *TaintIdentifier) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TaintIdentifier. +func (in *TaintIdentifier) DeepCopy() *TaintIdentifier { + if in == nil { + return nil + } + out := new(TaintIdentifier) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VSphereClusterDeprovision) DeepCopyInto(out *VSphereClusterDeprovision) { *out = *in diff --git a/vendor/github.com/openshift/hive/apis/scheme/scheme.go b/vendor/github.com/openshift/hive/apis/scheme/scheme.go index 0afe1edf..622ccaff 100644 --- a/vendor/github.com/openshift/hive/apis/scheme/scheme.go +++ b/vendor/github.com/openshift/hive/apis/scheme/scheme.go @@ -24,37 +24,36 @@ limitations under the License. // Each API group should define a utility function // called AddToScheme for adding its types to a Scheme: // -// // in package myapigroupv1... -// var ( -// SchemeGroupVersion = schema.GroupVersion{Group: "my.api.group", Version: "v1"} -// SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} -// AddToScheme = SchemeBuilder.AddToScheme -// ) +// // in package myapigroupv1... +// var ( +// SchemeGroupVersion = schema.GroupVersion{Group: "my.api.group", Version: "v1"} +// SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +// AddToScheme = SchemeBuilder.AddToScheme +// ) // -// func init() { -// SchemeBuilder.Register(&MyType{}, &MyTypeList) -// } -// var ( -// scheme *runtime.Scheme = runtime.NewScheme() -// ) +// func init() { +// SchemeBuilder.Register(&MyType{}, &MyTypeList) +// } +// var ( +// scheme *runtime.Scheme = runtime.NewScheme() +// ) // // This also true of the built-in Kubernetes types. Then, in the entrypoint for // your manager, assemble the scheme containing exactly the types you need, // panicing if scheme registration failed. For instance, if our controller needs // types from the core/v1 API group (e.g. Pod), plus types from my.api.group/v1: // -// func init() { -// utilruntime.Must(myapigroupv1.AddToScheme(scheme)) -// utilruntime.Must(kubernetesscheme.AddToScheme(scheme)) -// } -// -// func main() { -// mgr := controllers.NewManager(context.Background(), controllers.GetConfigOrDie(), manager.Options{ -// Scheme: scheme, -// }) -// // ... -// } +// func init() { +// utilruntime.Must(myapigroupv1.AddToScheme(scheme)) +// utilruntime.Must(kubernetesscheme.AddToScheme(scheme)) +// } // +// func main() { +// mgr := controllers.NewManager(context.Background(), controllers.GetConfigOrDie(), manager.Options{ +// Scheme: scheme, +// }) +// // ... +// } package scheme import ( diff --git a/vendor/modules.txt b/vendor/modules.txt index 99eefc36..069be949 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -129,6 +129,12 @@ github.com/google/uuid # github.com/imdario/mergo v0.3.16 ## explicit; go 1.13 github.com/imdario/mergo +# github.com/itchyny/gojq v0.12.8 +## explicit; go 1.16 +github.com/itchyny/gojq +# github.com/itchyny/timefmt-go v0.1.3 +## explicit; go 1.14 +github.com/itchyny/timefmt-go # github.com/jinzhu/inflection v1.0.0 ## explicit github.com/jinzhu/inflection @@ -216,8 +222,8 @@ github.com/openshift/api/config/v1 # github.com/openshift/assisted-service v1.0.10-0.20240506174859-4577ef6f4cf1 ## explicit; go 1.20 github.com/openshift/assisted-service/pkg/validations -# github.com/openshift/assisted-service/api v0.0.0 => github.com/openshift/assisted-service/api v0.0.0-20240506174859-4577ef6f4cf1 -## explicit; go 1.20 +# github.com/openshift/assisted-service/api v0.0.0 => github.com/openshift/assisted-service/api v0.0.0-20251008122257-ed1e53465867 +## explicit; go 1.21 github.com/openshift/assisted-service/api/common github.com/openshift/assisted-service/api/hiveextension/v1beta1 github.com/openshift/assisted-service/api/v1beta1 @@ -228,18 +234,21 @@ github.com/openshift/assisted-service/models ## explicit; go 1.21 github.com/openshift/cluster-api-provider-agent/api/v1alpha1 github.com/openshift/cluster-api-provider-agent/api/v1beta1 -# github.com/openshift/custom-resource-status v1.1.2 +# github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 ## explicit; go 1.12 github.com/openshift/custom-resource-status/conditions/v1 -# github.com/openshift/hive/apis v0.0.0-20220222213051-def9088fdb5a -## explicit; go 1.17 +# github.com/openshift/hive/apis v0.0.0-20231220215202-ad99b9e52d27 +## explicit; go 1.20 github.com/openshift/hive/apis/hive/v1 github.com/openshift/hive/apis/hive/v1/agent +github.com/openshift/hive/apis/hive/v1/alibabacloud github.com/openshift/hive/apis/hive/v1/aws github.com/openshift/hive/apis/hive/v1/azure github.com/openshift/hive/apis/hive/v1/baremetal github.com/openshift/hive/apis/hive/v1/gcp github.com/openshift/hive/apis/hive/v1/ibmcloud +github.com/openshift/hive/apis/hive/v1/metricsconfig +github.com/openshift/hive/apis/hive/v1/none github.com/openshift/hive/apis/hive/v1/openstack github.com/openshift/hive/apis/hive/v1/ovirt github.com/openshift/hive/apis/hive/v1/vsphere @@ -784,7 +793,7 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.12 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 -# github.com/openshift/assisted-service/api => github.com/openshift/assisted-service/api v0.0.0-20240506174859-4577ef6f4cf1 +# github.com/openshift/assisted-service/api => github.com/openshift/assisted-service/api v0.0.0-20251008122257-ed1e53465867 # github.com/openshift/assisted-service/models => github.com/openshift/assisted-service/models v0.0.0-20240506174859-4577ef6f4cf1 # github.com/openshift/cluster-api-provider-agent/api => ./api # golang.org/x/oauth2 => github.com/openshift/golang-oauth2 v0.26.1-0.20250310184649-06a918c6239d