Merge branch 'master' into feature/pubsub-batching
This commit is contained in:
commit
eab68d1a7e
|
@ -0,0 +1,3 @@
|
|||
# Compiled files
|
||||
components-contrib-build-tools
|
||||
components-contrib-build-tools.exe
|
|
@ -0,0 +1,18 @@
|
|||
# dapr/components-contrib build-tools CLI
|
||||
|
||||
This folder contains a CLI that implements a number of build tools used by dapr/components-contrib.
|
||||
|
||||
The CLI is written in Go and based on the [cobra](https://github.com/spf13/cobra) framework. In order to use it, Go (1.18+) must be installed on your system.
|
||||
|
||||
## Running the CLI
|
||||
|
||||
You have two ways to run the CLI:
|
||||
|
||||
1. Within the `build-tools` directly, you can run the CLI with `go run .` directly. For example `go run . help` shows the help page.
|
||||
2. You can build a pre-compiled binary by running `make compile-build-tools` in the root folder of this repository. This will build an executable called `build-tools` (or `build-tools.exe` on Windows) in the `build-tools` folder. You can then run the command directly, for example `./build-tools help`
|
||||
|
||||
## Available commands
|
||||
|
||||
The list of available commands in this CLI is dynamic and is subject to change at any time. Each command, including the "root" one (no sub-command), are self-documented in the CLI, and you can read the help page by adding `--help`.
|
||||
|
||||
For example, `./build-tools --help` shows the full list of commands the CLI offers.
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/dapr/components-contrib/build-tools/pkg/componentmetadata"
|
||||
"github.com/dapr/components-contrib/build-tools/pkg/metadataschema"
|
||||
)
|
||||
|
||||
// bundleComponentMetadataCmd represents the bundle-component-metadata command
|
||||
var bundleComponentMetadataCmd = &cobra.Command{
|
||||
Use: "bundle-component-metadata",
|
||||
Short: "Generates the component metadata bundle",
|
||||
Long: `Generates the component metadata bundle as a JSON files, and outputs it to stdout.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// Navigate to the root of the repo
|
||||
err := cwdToRepoRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create a parser that also loads the JSON schema
|
||||
parser, err := componentmetadata.NewParserWithSchemaFile("component-metadata-schema.json")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Find all components
|
||||
list, err := componentmetadata.FindComponents(ComponentFolders, ExcludeFolders)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Load the metadata for all components
|
||||
bundle := metadataschema.Bundle{
|
||||
SchemaVersion: "v1",
|
||||
Date: time.Now().Format("20060102150405"),
|
||||
Components: make([]*metadataschema.ComponentMetadata, 0, len(list)),
|
||||
}
|
||||
for _, component := range list {
|
||||
componentMetadata, err := parser.LoadForComponent(component)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Failed to load metadata for component %s: %w", component, err))
|
||||
}
|
||||
if componentMetadata == nil {
|
||||
fmt.Fprintln(os.Stderr, "Info: metadata file not found in component "+component)
|
||||
continue
|
||||
}
|
||||
bundle.Components = append(bundle.Components, componentMetadata)
|
||||
}
|
||||
|
||||
// Write to stdout
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetEscapeHTML(false)
|
||||
enc.SetIndent("", " ")
|
||||
err = enc.Encode(bundle)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Failed to encode bundle to JSON: %w", err))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(bundleComponentMetadataCmd)
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/invopop/jsonschema"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/dapr/components-contrib/build-tools/pkg/metadataschema"
|
||||
)
|
||||
|
||||
// genComponentSchemaCmd represents the genComponentSchema command
|
||||
var genComponentSchemaCmd = &cobra.Command{
|
||||
Use: "gen-component-schema",
|
||||
Short: "Generates the schema for the metadata.yaml / metadata.json files",
|
||||
Long: `Generates the schema for the metadata.yaml / metadata.json files by parsing the model in pkg/schema.
|
||||
The result is written to stdout.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// Generate the schema from the struct
|
||||
reflector := &jsonschema.Reflector{}
|
||||
reflector.ExpandedStruct = true
|
||||
err := reflector.AddGoComments("github.com/dapr/components-contrib/build-tools", "./pkg/metadataschema")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res := reflector.Reflect(&metadataschema.ComponentMetadata{})
|
||||
res.Title = "ComponentMetadata"
|
||||
// Print resut to stdout
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
_ = enc.Encode(res)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(genComponentSchemaCmd)
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "components-contrib-build-tools",
|
||||
Short: "Build tools for dapr/components-contrib",
|
||||
Long: `A collection of commands and tools used to build dapr/components-contrib`,
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Globals
|
||||
var (
|
||||
// List of folders containing components
|
||||
ComponentFolders []string
|
||||
|
||||
// Paths within ComponentFolders to ignore
|
||||
ExcludeFolders []string
|
||||
)
|
||||
|
||||
// Navigate to the root of the repo
|
||||
func cwdToRepoRoot() error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cwd, err = filepath.Abs(cwd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
stat, err := os.Stat(filepath.Join(cwd, ".git"))
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err == nil && stat != nil && stat.IsDir() {
|
||||
return os.Chdir(cwd)
|
||||
}
|
||||
|
||||
// Go one level up
|
||||
cwd = filepath.Dir(cwd)
|
||||
if cwd == "" || cwd == "." || cwd == string(filepath.Separator) {
|
||||
return errors.New("could not find the repository's root")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"componentFolders": [
|
||||
"bindings",
|
||||
"configuration",
|
||||
"lock",
|
||||
"middleware/http",
|
||||
"nameresolution",
|
||||
"pubsub",
|
||||
"secretstores",
|
||||
"state"
|
||||
],
|
||||
"excludeFolders": [
|
||||
"bindings/alicloud",
|
||||
"bindings/aws",
|
||||
"bindings/azure",
|
||||
"bindings/gcp",
|
||||
"bindings/huawei",
|
||||
"bindings/rethinkdb",
|
||||
"bindings/twilio",
|
||||
"bindings/zeebe",
|
||||
"configuration/azure",
|
||||
"configuration/redis/internal",
|
||||
"pubsub/aws",
|
||||
"pubsub/azure",
|
||||
"pubsub/gcp",
|
||||
"secretstores/alicloud",
|
||||
"secretstores/aws",
|
||||
"secretstores/azure",
|
||||
"secretstores/gcp",
|
||||
"secretstores/hashicorp",
|
||||
"secretstores/huaweicloud",
|
||||
"secretstores/local",
|
||||
"state/alicloud",
|
||||
"state/aws",
|
||||
"state/azure",
|
||||
"state/gcp",
|
||||
"state/hashicorp",
|
||||
"state/oci",
|
||||
"state/utils"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
module github.com/dapr/components-contrib/build-tools
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/invopop/jsonschema v0.6.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/xeipuuv/gojsonschema v1.2.1-0.20201027075954-b076d39a02e5
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.8.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
|
@ -0,0 +1,39 @@
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/invopop/jsonschema v0.6.0 h1:8e+xY8ZEn8gDHUYylSlLHy22P+SLeIRIHv3nM3hCbmY=
|
||||
github.com/invopop/jsonschema v0.6.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.1-0.20201027075954-b076d39a02e5 h1:ImnGIsrcG8vwbovhYvvSY8fagVV6QhCWSWXfzwGDLVs=
|
||||
github.com/xeipuuv/gojsonschema v1.2.1-0.20201027075954-b076d39a02e5/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/dapr/components-contrib/build-tools/cmd"
|
||||
)
|
||||
|
||||
//go:embed component-folders.json
|
||||
var componentFoldersJSON []byte
|
||||
|
||||
func init() {
|
||||
parsed := struct {
|
||||
ComponentFolders []string `json:"componentFolders"`
|
||||
ExcludeFolders []string `json:"excludeFolders"`
|
||||
}{}
|
||||
err := json.Unmarshal(componentFoldersJSON, &parsed)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmd.ComponentFolders = parsed.ComponentFolders
|
||||
cmd.ExcludeFolders = parsed.ExcludeFolders
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 componentmetadata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// FindComponents finds all component folders and returns their paths.
|
||||
func FindComponents(folders []string, skip []string) ([]string, error) {
|
||||
skipMap := map[string]struct{}{}
|
||||
for _, v := range skip {
|
||||
// Normalize all slashes
|
||||
v = filepath.Clean(v)
|
||||
skipMap[v] = struct{}{}
|
||||
}
|
||||
|
||||
res := []string{}
|
||||
for _, folder := range folders {
|
||||
folder = filepath.Clean(folder)
|
||||
err := findInDirectory(folder, skipMap, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func findInDirectory(dir string, skip map[string]struct{}, res *[]string) error {
|
||||
read, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, e := range read {
|
||||
// Ignore anything but directories
|
||||
if !e.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
path := filepath.Join(dir, e.Name())
|
||||
|
||||
// Add the directory if not skipped
|
||||
if _, ok := skip[path]; !ok {
|
||||
*res = append(*res, path)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "Info: skipped folder "+path)
|
||||
}
|
||||
|
||||
// Read the directory recursively
|
||||
findInDirectory(path, skip, res)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 componentmetadata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/dapr/components-contrib/build-tools/pkg/metadataschema"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
// Parser used to parse and validate component metadata YAML or JSON files.
|
||||
type Parser struct {
|
||||
validator *gojsonschema.Schema
|
||||
}
|
||||
|
||||
// NewParserWithSchema creates a new Parser object with the schema read from the file.
|
||||
func NewParserWithSchemaFile(file string) (*Parser, error) {
|
||||
read, err := os.ReadFile("component-metadata-schema.json")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read component-metadata-schema.json: %w", err)
|
||||
}
|
||||
|
||||
return NewParserWithSchema(read)
|
||||
}
|
||||
|
||||
// NewParserWithSchema creates a new Parser object with the schema passed as JSON-encoded data.
|
||||
func NewParserWithSchema(schema []byte) (*Parser, error) {
|
||||
schemaLoader := gojsonschema.NewBytesLoader(schema)
|
||||
validator, err := gojsonschema.NewSchema(schemaLoader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create schema validator: %w", err)
|
||||
}
|
||||
|
||||
return &Parser{
|
||||
validator: validator,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LoadForComponent loads the metadata.yaml / metadata.json for the component, parses it, and validates it.
|
||||
func (p *Parser) LoadForComponent(componentPath string) (*metadataschema.ComponentMetadata, error) {
|
||||
var (
|
||||
read []byte
|
||||
err error
|
||||
)
|
||||
|
||||
// Try with YAML first
|
||||
read, err = os.ReadFile(filepath.Join(componentPath, "metadata.yaml"))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// IT'S YAML NOT YML
|
||||
// (Insert GIF of "It's leviOsa, not levioSA!")
|
||||
read, err = os.ReadFile(filepath.Join(componentPath, "metadata.yml"))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// JSON anyone?
|
||||
read, err = os.ReadFile(filepath.Join(componentPath, "metadata.json"))
|
||||
}
|
||||
}
|
||||
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Parse the YAML (and also JSON)
|
||||
componentMetadata, err := p.Parse(read)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse metadata file for component %s: %w", componentPath, err)
|
||||
}
|
||||
return componentMetadata, nil
|
||||
}
|
||||
|
||||
// Parse a YAML (or JSON) file, already read, and returns the ComponentMetadata object.
|
||||
// Automatically validates the metadata against the schema
|
||||
func (p *Parser) Parse(read []byte) (*metadataschema.ComponentMetadata, error) {
|
||||
componentMetadata := &metadataschema.ComponentMetadata{}
|
||||
|
||||
// Converts to JSON if it's YAML
|
||||
// Since JSON is a subset of YAML, this accepts JSON files too
|
||||
readJSON, err := yaml.YAMLToJSONStrict(read)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse metadata file: %w", err)
|
||||
}
|
||||
err = json.Unmarshal(readJSON, componentMetadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal metadata: %w", err)
|
||||
}
|
||||
|
||||
// Validate against the schema
|
||||
res, err := p.validator.Validate(gojsonschema.NewGoLoader(componentMetadata))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("metadata failed validation: %w", err)
|
||||
}
|
||||
if !res.Valid() {
|
||||
return nil, fmt.Errorf("metadata is not valid: %v", res.Errors())
|
||||
}
|
||||
|
||||
// Perform extra validation
|
||||
err = componentMetadata.IsValid()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return componentMetadata, nil
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 metadataschema
|
||||
|
||||
// Bundle is the type for the component metadata bundle.
|
||||
type Bundle struct {
|
||||
// Version of the component bundle schema.
|
||||
SchemaVersion string `json:"schemaVersion" jsonschema:"enum=v1"`
|
||||
// Date the bundle was generated, in format `20060102150405`
|
||||
Date string `json:"date"`
|
||||
// Component list.
|
||||
Components []*ComponentMetadata `json:"components"`
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 metadataschema contains the data structures for the schema of metadata.yaml / metadata.json files.
|
||||
// Schemas are built using github.com/invopop/jsonschema .
|
||||
package metadataschema
|
||||
|
||||
// ComponentMetadata is the schema for the metadata.yaml / metadata.json files.
|
||||
type ComponentMetadata struct {
|
||||
// Version of the component metadata schema.
|
||||
SchemaVersion string `json:"schemaVersion" jsonschema:"enum=v1"`
|
||||
// Component type, of one of the allowed values.
|
||||
Type string `json:"type" jsonschema:"enum=bindings,enum=state,enum=secretstores,enum=pubsub,enum=configuration,enum=lock,enum=middleware"`
|
||||
// Name of the component (without the inital type, e.g. "http" instead of "bindings.http").
|
||||
Name string `json:"name"`
|
||||
// Version of the component, with the leading "v", e.g. "v1".
|
||||
Version string `json:"version"`
|
||||
// Component status.
|
||||
Status string `json:"status" jsonschema:"enum=stable,enum=beta,enum=alpha,enum=development-only"`
|
||||
// Title of the component, e.g. "HTTP".
|
||||
Title string `json:"title"`
|
||||
// Additional description for the component, optional.
|
||||
Description string `json:"description,omitempty"`
|
||||
// URLs with additional resources for the component, such as docs.
|
||||
URLs []URL `json:"urls"`
|
||||
// Properties for bindings only.
|
||||
// This should not present unless "type" is "bindings".
|
||||
Binding *Binding `json:"binding,omitempty"`
|
||||
// Component capabilities.
|
||||
// For state stores, the presence of "actorStateStore" implies that the metadata property "actorStateStore" can be set. In that case, do not manually specify "actorStateStore" as metadata option.
|
||||
Capabilities []string `json:"capabilities,omitempty"`
|
||||
// Authentication profiles for the component.
|
||||
AuthenticationProfiles []AuthenticationProfile `json:"authenticationProfiles,omitempty"`
|
||||
// Metadata options for the component.
|
||||
Metadata []Metadata `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// URL represents one URL with additional resources.
|
||||
type URL struct {
|
||||
// Title of the URL.
|
||||
Title string `json:"title"`
|
||||
// URL.
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Binding represents properties that are specific to bindings
|
||||
type Binding struct {
|
||||
// If "true", the binding can be used as input binding.
|
||||
Input bool `json:"input,omitempty"`
|
||||
// If "true", the binding can be used as output binding.
|
||||
Output bool `json:"output,omitempty"`
|
||||
// List of operations that the output binding support.
|
||||
// Required in output bindings, and not allowed in input-only bindings.
|
||||
Operations []BindingOperation `json:"operations"`
|
||||
}
|
||||
|
||||
// BindingOperation represents an operation offered by an output binding.
|
||||
type BindingOperation struct {
|
||||
// Name of the operation, such as "create", "post", "delete", etc.
|
||||
Name string `json:"name"`
|
||||
// Descrption of the operation.
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// Metadata property.
|
||||
type Metadata struct {
|
||||
// Name of the metadata property.
|
||||
Name string `json:"name"`
|
||||
// Description of the property.
|
||||
Description string `json:"description"`
|
||||
// If "true", the property is required
|
||||
Required bool `json:"required,omitempty"`
|
||||
// If "true", the property represents a sensitive value such as a password.
|
||||
Sensitive bool `json:"sensitive,omitempty"`
|
||||
// Type of the property.
|
||||
// If this is empty, it's interpreted as "string".
|
||||
Type string `json:"type,omitempty" jsonschema:"enum=string,enum=number,enum=bool,enum=duration"`
|
||||
// Default value for the property.
|
||||
// If it's a string, don't forget to add quotes.
|
||||
Default string `json:"default,omitempty"`
|
||||
// Example value.
|
||||
Example string `json:"example"`
|
||||
// If set, forces the value to be one of those specified in this allowlist.
|
||||
AllowedValues []string `json:"allowedValues,omitempty"`
|
||||
// If set, specifies that the property is only applicable to bindings of the type specified below.
|
||||
// At least one of "input" and "output" must be "true".
|
||||
Binding *MetadataBinding `json:"binding,omitempty"`
|
||||
}
|
||||
|
||||
// MetadataBinding is the type for the "binding" property in the "metadata" object.
|
||||
type MetadataBinding struct {
|
||||
// If "true", the property can be used with the binding as input binding only.
|
||||
Input bool `json:"input,omitempty"`
|
||||
// If "true", the property can be used with the binding as output binding only.
|
||||
Output bool `json:"output,omitempty"`
|
||||
}
|
||||
|
||||
// AuthenticationProfile is the type for an authentication profile.
|
||||
type AuthenticationProfile struct {
|
||||
// Title of the authentication profile.
|
||||
Title string `json:"title"`
|
||||
// Additional description for the authentication profile, optional.
|
||||
Description string `json:"description"`
|
||||
// Metadata options applicable when using this authentication profile.
|
||||
Metadata []Metadata `json:"metadata,omitempty"`
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2022 The Dapr Authors
|
||||
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 metadataschema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsValid performs additional validation and returns true if the object is valid.
|
||||
func (c ComponentMetadata) IsValid() error {
|
||||
// Sanity check for bindings
|
||||
if c.Type == "" {
|
||||
return errors.New("type is empty")
|
||||
}
|
||||
if c.Type == "bindings" && c.Binding == nil {
|
||||
return errors.New("property binding is required for components of type 'bindings'")
|
||||
}
|
||||
if c.Type != "bindings" && c.Binding != nil {
|
||||
return errors.New("property binding is not allowed in components that are not of type 'bindings'")
|
||||
}
|
||||
|
||||
// Ensure that there's a URL called Reference to the Dapr docs
|
||||
if len(c.URLs) < 1 {
|
||||
return errors.New("property urls must contain at least one URL to the Dapr docs with title 'Reference'")
|
||||
}
|
||||
hasReferenceUrl := false
|
||||
for _, u := range c.URLs {
|
||||
if u.Title == "Reference" && strings.HasPrefix(u.URL, "https://docs.dapr.io/reference/components-reference/") {
|
||||
hasReferenceUrl = true
|
||||
}
|
||||
}
|
||||
if !hasReferenceUrl {
|
||||
return errors.New("property urls must a link to the Dapr docs with title 'Reference' and URL starting with 'https://docs.dapr.io/reference/components-reference/'")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -91,6 +91,9 @@ jobs:
|
|||
key: ${{ matrix.target_os }}-${{ matrix.target_arch }}-go-${{ env.GOVER }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ matrix.target_os }}-${{ matrix.target_arch }}-go-${{ env.GOVER }}-
|
||||
- name: Check components-schema
|
||||
if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' && steps.skip_check.outputs.should_skip != 'true'
|
||||
run: make check-component-metadata-schema-diff
|
||||
- name: Run golangci-lint
|
||||
if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' && steps.skip_check.outputs.should_skip != 'true'
|
||||
uses: golangci/golangci-lint-action@v3.2.0
|
||||
|
@ -100,7 +103,7 @@ jobs:
|
|||
args: --timeout 15m
|
||||
- name: Run go mod tidy check diff
|
||||
if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' && steps.skip_check.outputs.should_skip != 'true'
|
||||
run: make modtidy-all check-diff
|
||||
run: make modtidy-all check-mod-diff
|
||||
# - name: Run Go Vulnerability Check
|
||||
# if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' && steps.skip_check.outputs.should_skip != 'true'
|
||||
# run: |
|
||||
|
|
|
@ -6,3 +6,4 @@ vendor
|
|||
go.work
|
||||
go.work.sum
|
||||
.DS_Store
|
||||
component-metadata-bundle.json
|
||||
|
|
50
Makefile
50
Makefile
|
@ -67,6 +67,17 @@ else
|
|||
INSTALLED_LINT_VERSION=v$(shell $(LINTER_BINARY) version | grep -Eo '([0-9]+\.)+[0-9]+' - || "")
|
||||
endif
|
||||
|
||||
# Build tools
|
||||
ifeq ($(TARGET_OS_LOCAL),windows)
|
||||
BUILD_TOOLS_BIN ?= components-contrib-build-tools.exe
|
||||
BUILD_TOOLS ?= ./.build-tools/$(BUILD_TOOLS_BIN)
|
||||
RUN_BUILD_TOOLS ?= cd .build-tools; go.exe run .
|
||||
else
|
||||
BUILD_TOOLS_BIN ?= components-contrib-build-tools
|
||||
BUILD_TOOLS ?= ./.build-tools/$(BUILD_TOOLS_BIN)
|
||||
RUN_BUILD_TOOLS ?= cd .build-tools; go run .
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Linter targets #
|
||||
################################################################################
|
||||
|
@ -139,13 +150,40 @@ modtidy:
|
|||
go mod tidy
|
||||
|
||||
################################################################################
|
||||
# Target: check-diff #
|
||||
# Target: check-mod-diff #
|
||||
################################################################################
|
||||
.PHONY: check-diff
|
||||
check-diff:
|
||||
.PHONY: check-mod-diff
|
||||
check-mod-diff:
|
||||
git diff --exit-code -- '*go.mod' # check no changes
|
||||
git diff --exit-code -- '*go.sum' # check no changes
|
||||
|
||||
################################################################################
|
||||
# Target: compile-build-tools #
|
||||
################################################################################
|
||||
.PHONY: compile-build-tools
|
||||
compile-build-tools:
|
||||
ifeq (,$(wildcard $(BUILD_TOOLS)))
|
||||
cd .build-tools; CGO_ENABLED=$(CGO) GOOS=$(TARGET_OS_LOCAL) GOARCH=$(TARGET_ARCH_LOCAL) go build -o $(BUILD_TOOLS_BIN) .
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Components schema targets #
|
||||
################################################################################
|
||||
.PHONY: component-metadata-schema
|
||||
component-metadata-schema:
|
||||
$(RUN_BUILD_TOOLS) gen-component-schema > ../component-metadata-schema.json
|
||||
|
||||
.PHONY: check-component-metadata-schema-diff
|
||||
check-component-metadata-schema-diff: component-metadata-schema
|
||||
git diff --exit-code -- component-metadata-schema.json # check no changes
|
||||
|
||||
################################################################################
|
||||
# Component metadata bundle targets #
|
||||
################################################################################
|
||||
.PHONY: bundle-component-metadata
|
||||
bundle-component-metadata:
|
||||
$(RUN_BUILD_TOOLS) bundle-component-metadata > ../component-metadata-bundle.json
|
||||
|
||||
################################################################################
|
||||
# Target: conf-tests #
|
||||
################################################################################
|
||||
|
@ -154,8 +192,6 @@ conf-tests:
|
|||
CGO_ENABLED=$(CGO) go test -v -tags=conftests -count=1 ./tests/conformance
|
||||
|
||||
################################################################################
|
||||
# Target: e2e-tests-zeebe #
|
||||
# Target: e2e #
|
||||
################################################################################
|
||||
.PHONY: e2e-tests-zeebe
|
||||
e2e-tests-zeebe:
|
||||
CGO_ENABLED=$(CGO) go test -v -tags=e2etests -count=1 ./tests/e2e/bindings/zeebe/...
|
||||
include tests/e2e/e2e_tests.mk
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
# yaml-language-server: $schema=../../../component-metadata-schema.json
|
||||
schemaVersion: v1
|
||||
type: bindings
|
||||
name: azure.servicebusqueues
|
||||
version: v1
|
||||
status: stable
|
||||
title: "Azure Service Bus Queues"
|
||||
urls:
|
||||
- title: Reference
|
||||
url: https://docs.dapr.io/reference/components-reference/supported-bindings/servicebusqueues/
|
||||
binding:
|
||||
output: true
|
||||
input: true
|
||||
operations:
|
||||
- name: create
|
||||
description: "Publish a new message in the queue."
|
||||
capabilities: []
|
||||
authenticationProfiles:
|
||||
- title: "Connection string"
|
||||
description: "Authenticate using a connection string."
|
||||
metadata:
|
||||
- name: connectionString
|
||||
required: true
|
||||
sensitive: true
|
||||
description: "The Service Bus connection string."
|
||||
example: '"Endpoint=sb://************"'
|
||||
# If omitted, uses the same values as "<root>.binding"
|
||||
binding:
|
||||
output: true
|
||||
input: true
|
||||
- title: "Azure AD: Managed identity"
|
||||
description: "Authenticate using Azure AD and a managed identity."
|
||||
metadata:
|
||||
- name: namespaceName
|
||||
description: "Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name."
|
||||
example: '"namespace.servicebus.windows.net"'
|
||||
required: true
|
||||
binding:
|
||||
output: true
|
||||
input: true
|
||||
- name: azureClientId
|
||||
required: false
|
||||
description: "Client ID (application ID). Required if the service has multiple identities assigned."
|
||||
example: '"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"'
|
||||
- title: "Azure AD: Client credentials"
|
||||
description: "Authenticate using Azure AD with client credentials, also known as \"service principals\"."
|
||||
metadata:
|
||||
- name: namespaceName
|
||||
description: "Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name."
|
||||
example: '"namespace.servicebus.windows.net"'
|
||||
required: true
|
||||
binding:
|
||||
output: true
|
||||
input: true
|
||||
- name: azureTenantId
|
||||
required: true
|
||||
description: "ID of the Azure AD tenant"
|
||||
example: '"cd4b2887-304c-47e1-b4d5-65447fdd542b"'
|
||||
- name: azureClientId
|
||||
required: true
|
||||
description: "Client ID (application ID)"
|
||||
example: '"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"'
|
||||
- name: azureClientSecret
|
||||
sensitive: true
|
||||
required: true
|
||||
description: "Client secret (application password)"
|
||||
example: '"Ecy3XG7zVZK3/vl/a2NSB+a1zXLa8RnMum/IgD0E"'
|
||||
- title: "Azure AD: Client certificate"
|
||||
description: "Authenticate using Azure AD with a client certificate (in PFX/PKCS#12 format). One of azureCertificate and azureCertificateFile is required."
|
||||
metadata:
|
||||
- name: namespaceName
|
||||
description: "Parameter to set the address of the Service Bus namespace, as a fully-qualified domain name."
|
||||
example: '"namespace.servicebus.windows.net"'
|
||||
required: true
|
||||
binding:
|
||||
output: true
|
||||
input: true
|
||||
- name: azureTenantId
|
||||
required: true
|
||||
description: "ID of the Azure AD tenant."
|
||||
example: '"cd4b2887-304c-47e1-b4d5-65447fdd542b"'
|
||||
- name: azureClientId
|
||||
required: true
|
||||
description: "Client ID (application ID)."
|
||||
example: '"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"'
|
||||
- name: azureCertificate
|
||||
sensitive: true
|
||||
required: false
|
||||
description: "Certificate and private key (in PFX/PKCS#12 format)."
|
||||
example: |
|
||||
"-----BEGIN PRIVATE KEY-----\n MIIEvgI... \n -----END PRIVATE KEY----- \n -----BEGIN CERTIFICATE----- \n MIICoTC... \n -----END CERTIFICATE-----"
|
||||
- name: azureCertificateFile
|
||||
sensitive: true
|
||||
required: false
|
||||
description: "Path to PFX/PKCS#12 file on disk, containing the certificate and private key."
|
||||
example: "/path/to/file.pem"
|
||||
- name: azureCertificatePassword
|
||||
sensitive: true
|
||||
required: false
|
||||
description: "Password for the certificate if encrypted."
|
||||
example: "password"
|
||||
metadata:
|
||||
- name: queueName
|
||||
required: true
|
||||
description: "The Service Bus queue name. Queue names are case-insensitive and will always be forced to lowercase."
|
||||
# string is the default type if omitted
|
||||
type: string
|
||||
example: '"queuename"'
|
||||
binding:
|
||||
output: true
|
||||
input: true
|
||||
- name: ttlInSeconds
|
||||
description: "Parameter to set the default message time to live. If this parameter is omitted, messages will expire after 14 days (the built-in default value in Azure Sevice Bus)."
|
||||
type: number
|
||||
example: '86400'
|
||||
binding:
|
||||
# input is omitted so it's assumed as false
|
||||
output: true
|
||||
- name: maxRetriableErrorsPerSec
|
||||
description: "Maximum number of retriable errors that are processed per second. If a message fails to be processed with a retriable error, the component adds a delay before it starts processing another message, to avoid immediately re-processing messages that have failed"
|
||||
type: number
|
||||
default: '10'
|
||||
example: '2'
|
||||
binding:
|
||||
# output is omitted so it's assumed as false
|
||||
input: true
|
||||
- name: minConnectionRecoveryInSec
|
||||
description: "Minimum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure."
|
||||
type: number
|
||||
default: '2'
|
||||
example: '5'
|
||||
binding:
|
||||
# output is omitted so it's assumed as false
|
||||
input: true
|
||||
- name: maxConnectionRecoveryInSec
|
||||
description: "Maximum interval (in seconds) to wait before attempting to reconnect to Azure Service Bus in case of a connection failure. After each attempt, the binding waits a random number of seconds, increasing every time, between the minimum and the maximum. Default is 300 seconds (5 minutes)."
|
||||
type: number
|
||||
default: '300'
|
||||
example: '600'
|
||||
binding:
|
||||
# output is omitted so it's assumed as false
|
||||
input: true
|
||||
- name: maxActiveMessages
|
||||
description: "Defines the maximum number of messages to be processing or in the buffer at once. This should be at least as big as the \"maxConcurrentHandlers\"."
|
||||
type: number
|
||||
default: '1'
|
||||
example: '8'
|
||||
binding:
|
||||
input: true
|
||||
- name: maxConcurrentHandlers
|
||||
description: "Defines the maximum number of concurrent message handlers."
|
||||
type: number
|
||||
default: '1'
|
||||
example: '5'
|
||||
binding:
|
||||
input: true
|
||||
- name: lockRenewalInSec
|
||||
description: "Defines the frequency at which buffered message locks will be renewed."
|
||||
type: number
|
||||
default: '20'
|
||||
example: '10'
|
||||
binding:
|
||||
input: true
|
||||
- name: timeoutInSec
|
||||
description: "Timeout for all invocations to the Azure Service Bus endpoint, in seconds. Note that this option impacts network calls and it's unrelated to the TTL applies to messages."
|
||||
type: number
|
||||
default: '60'
|
||||
example: '30'
|
||||
# binding is not specified so it's the same as <root>.binding
|
|
@ -0,0 +1,41 @@
|
|||
# yaml-language-server: $schema=../../component-metadata-schema.json
|
||||
schemaVersion: v1
|
||||
type: bindings
|
||||
name: http
|
||||
version: v1
|
||||
status: stable
|
||||
title: "HTTP"
|
||||
urls:
|
||||
- title: Reference
|
||||
url: https://docs.dapr.io/reference/components-reference/supported-bindings/http/
|
||||
binding:
|
||||
output: true
|
||||
input: false
|
||||
operations:
|
||||
- name: create
|
||||
description: "Alias for \"post\", for backwards-compatibility."
|
||||
- name: get
|
||||
description: "Read data/records."
|
||||
- name: head
|
||||
description: "Identical to get except that the server does not return a response body."
|
||||
- name: post
|
||||
description: "Typically used to create records or send commands."
|
||||
- name: put
|
||||
description: "Update data/records."
|
||||
- name: patch
|
||||
description: "Sometimes used to update a subset of fields of a record."
|
||||
- name: delete
|
||||
description: "Delete a data/record."
|
||||
- name: options
|
||||
description: "Requests for information about the communication options available (not commonly used)."
|
||||
- name: trace
|
||||
description: "Used to invoke a remote, application-layer loop-back of the request message (not commonly used)."
|
||||
capabilities: []
|
||||
metadata:
|
||||
- name: url
|
||||
required: true
|
||||
description: "The base URL of the HTTP endpoint to invoke"
|
||||
example: '"http://host:port/path", "http://myservice:8000/customer"'
|
||||
# If omitted, uses the same values as "<root>.binding"
|
||||
binding:
|
||||
output: true
|
|
@ -0,0 +1,260 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://github.com/dapr/components-contrib/build-tools/pkg/metadataschema/component-metadata",
|
||||
"$defs": {
|
||||
"AuthenticationProfile": {
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Title of the authentication profile."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Additional description for the authentication profile, optional."
|
||||
},
|
||||
"metadata": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/Metadata"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Metadata options applicable when using this authentication profile."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"title",
|
||||
"description"
|
||||
],
|
||||
"description": "AuthenticationProfile is the type for an authentication profile."
|
||||
},
|
||||
"Binding": {
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "boolean",
|
||||
"description": "If \"true\", the binding can be used as input binding."
|
||||
},
|
||||
"output": {
|
||||
"type": "boolean",
|
||||
"description": "If \"true\", the binding can be used as output binding."
|
||||
},
|
||||
"operations": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/BindingOperation"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "List of operations that the output binding support.\nRequired in output bindings, and not allowed in input-only bindings."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"operations"
|
||||
],
|
||||
"description": "Binding represents properties that are specific to bindings"
|
||||
},
|
||||
"BindingOperation": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the operation, such as \"create\", \"post\", \"delete\", etc."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Descrption of the operation."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"description"
|
||||
],
|
||||
"description": "BindingOperation represents an operation offered by an output binding."
|
||||
},
|
||||
"Metadata": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the metadata property."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Description of the property."
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "If \"true\", the property is required"
|
||||
},
|
||||
"sensitive": {
|
||||
"type": "boolean",
|
||||
"description": "If \"true\", the property represents a sensitive value such as a password."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"bool",
|
||||
"duration"
|
||||
],
|
||||
"description": "Type of the property.\nIf this is empty, it's interpreted as \"string\"."
|
||||
},
|
||||
"default": {
|
||||
"type": "string",
|
||||
"description": "Default value for the property.\nIf it's a string, don't forget to add quotes."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"description": "Example value."
|
||||
},
|
||||
"allowedValues": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "If set, forces the value to be one of those specified in this allowlist."
|
||||
},
|
||||
"binding": {
|
||||
"$ref": "#/$defs/MetadataBinding",
|
||||
"description": "If set, specifies that the property is only applicable to bindings of the type specified below.\nAt least one of \"input\" and \"output\" must be \"true\"."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"description",
|
||||
"example"
|
||||
],
|
||||
"description": "Metadata property."
|
||||
},
|
||||
"MetadataBinding": {
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "boolean",
|
||||
"description": "If \"true\", the property can be used with the binding as input binding only."
|
||||
},
|
||||
"output": {
|
||||
"type": "boolean",
|
||||
"description": "If \"true\", the property can be used with the binding as output binding only."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "MetadataBinding is the type for the \"binding\" property in the \"metadata\" object."
|
||||
},
|
||||
"URL": {
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Title of the URL."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "URL."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"title",
|
||||
"url"
|
||||
],
|
||||
"description": "URL represents one URL with additional resources."
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"schemaVersion": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"v1"
|
||||
],
|
||||
"description": "Version of the component metadata schema."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"bindings",
|
||||
"state",
|
||||
"secretstores",
|
||||
"pubsub",
|
||||
"configuration",
|
||||
"lock",
|
||||
"middleware"
|
||||
],
|
||||
"description": "Component type, of one of the allowed values."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the component (without the inital type, e.g. \"http\" instead of \"bindings.http\")."
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Version of the component, with the leading \"v\", e.g. \"v1\"."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"stable",
|
||||
"beta",
|
||||
"alpha",
|
||||
"development-only"
|
||||
],
|
||||
"description": "Component status."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Title of the component, e.g. \"HTTP\"."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Additional description for the component, optional."
|
||||
},
|
||||
"urls": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/URL"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "URLs with additional resources for the component, such as docs."
|
||||
},
|
||||
"binding": {
|
||||
"$ref": "#/$defs/Binding",
|
||||
"description": "Properties for bindings only.\nThis should not present unless \"type\" is \"bindings\"."
|
||||
},
|
||||
"capabilities": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Component capabilities.\nFor state stores, the presence of \"actorStateStore\" implies that the metadata property \"actorStateStore\" can be set. In that case, do not manually specify \"actorStateStore\" as metadata option."
|
||||
},
|
||||
"authenticationProfiles": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/AuthenticationProfile"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Authentication profiles for the component."
|
||||
},
|
||||
"metadata": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/Metadata"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Metadata options for the component."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"schemaVersion",
|
||||
"type",
|
||||
"name",
|
||||
"version",
|
||||
"status",
|
||||
"title",
|
||||
"urls"
|
||||
],
|
||||
"title": "ComponentMetadata",
|
||||
"description": "ComponentMetadata is the schema for the metadata.yaml / metadata.json files."
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
# yaml-language-server: $schema=../../../component-metadata-schema.json
|
||||
schemaVersion: v1
|
||||
type: state
|
||||
name: azure.cosmosdb
|
||||
version: v1
|
||||
status: stable
|
||||
title: "Azure Cosmos DB (SQL API)"
|
||||
urls:
|
||||
- title: Reference
|
||||
url: https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-azure-cosmosdb/
|
||||
capabilities:
|
||||
# If actorStateStore is present, the metadata key actorStateStore can be used
|
||||
- actorStateStore
|
||||
- crud
|
||||
- transactional
|
||||
- etag
|
||||
- ttl
|
||||
- query
|
||||
authenticationProfiles:
|
||||
- title: "Master key"
|
||||
description: "Authenticate using a pre-shared \"master key\"."
|
||||
metadata:
|
||||
- name: masterKey
|
||||
required: true
|
||||
sensitive: true
|
||||
description: "The key to authenticate to the Cosmos DB account."
|
||||
example: '"my-secret-key"'
|
||||
- title: "Azure AD: Managed identity"
|
||||
description: "Authenticate using Azure AD and a managed identity."
|
||||
metadata:
|
||||
- name: azureClientId
|
||||
required: false
|
||||
description: "Client ID (application ID). Required if the service has multiple identities assigned."
|
||||
example: '"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"'
|
||||
- title: "Azure AD: Client credentials"
|
||||
description: "Authenticate using Azure AD with client credentials, also known as \"service principals\"."
|
||||
metadata:
|
||||
- name: azureTenantId
|
||||
required: true
|
||||
description: "ID of the Azure AD tenant"
|
||||
example: '"cd4b2887-304c-47e1-b4d5-65447fdd542b"'
|
||||
- name: azureClientId
|
||||
required: true
|
||||
description: "Client ID (application ID)"
|
||||
example: '"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"'
|
||||
- name: azureClientSecret
|
||||
required: true
|
||||
sensitive: true
|
||||
description: "Client secret (application password)"
|
||||
example: '"Ecy3XG7zVZK3/vl/a2NSB+a1zXLa8RnMum/IgD0E"'
|
||||
- title: "Azure AD: Client certificate"
|
||||
description: "Authenticate using Azure AD with a client certificate (in PFX/PKCS#12 format). One of azureCertificate and azureCertificateFile is required."
|
||||
metadata:
|
||||
- name: azureTenantId
|
||||
required: true
|
||||
description: "ID of the Azure AD tenant."
|
||||
example: '"cd4b2887-304c-47e1-b4d5-65447fdd542b"'
|
||||
- name: azureClientId
|
||||
required: true
|
||||
description: "Client ID (application ID)."
|
||||
example: '"c7dd251f-811f-4ba2-a905-acd4d3f8f08b"'
|
||||
- name: azureCertificate
|
||||
required: false
|
||||
sensitive: true
|
||||
description: "Certificate and private key (in PFX/PKCS#12 format)."
|
||||
example: |
|
||||
"-----BEGIN PRIVATE KEY-----\n MIIEvgI... \n -----END PRIVATE KEY----- \n -----BEGIN CERTIFICATE----- \n MIICoTC... \n -----END CERTIFICATE-----"
|
||||
- name: azureCertificateFile
|
||||
required: false
|
||||
sensitive: true
|
||||
description: "Path to PFX/PKCS#12 file on disk, containing the certificate and private key."
|
||||
example: "/path/to/file.pem"
|
||||
- name: azureCertificatePassword
|
||||
required: false
|
||||
sensitive: true
|
||||
description: "Password for the certificate if encrypted."
|
||||
example: "password"
|
||||
metadata:
|
||||
- name: url
|
||||
required: true
|
||||
description: "The Cosmos DB url."
|
||||
example: '"https://******.documents.azure.com:443/"'
|
||||
- name: database
|
||||
required: true
|
||||
description: "The name of the database."
|
||||
example: '"db"'
|
||||
- name: collection
|
||||
required: true
|
||||
description: "The name of the collection (container)."
|
||||
example: '"collection"'
|
|
@ -0,0 +1,66 @@
|
|||
# yaml-language-server: $schema=../../component-metadata-schema.json
|
||||
schemaVersion: v1
|
||||
type: state
|
||||
name: mongodb
|
||||
version: v1
|
||||
status: stable
|
||||
title: "MongoDB"
|
||||
urls:
|
||||
- title: Reference
|
||||
url: https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-mongodb/
|
||||
- title: Connection options
|
||||
url: https://www.mongodb.com/docs/manual/reference/connection-string/#std-label-connections-connection-options
|
||||
capabilities:
|
||||
# If actorStateStore is present, the metadata key actorStateStore can be used
|
||||
- actorStateStore
|
||||
- crud
|
||||
- transactional
|
||||
- etag
|
||||
- query
|
||||
metadata:
|
||||
- name: server
|
||||
# Required if host is not set
|
||||
required: false
|
||||
description: "The server to connect to, when using DNS SRV record. One of \"server\" and \"host\" is required."
|
||||
example: '"server.example.com"'
|
||||
- name: host
|
||||
# Required if server is not set
|
||||
required: false
|
||||
description: "The host to connect to. One of \"server\" and \"host\" is required."
|
||||
example: '"mongo-mongodb.default.svc.cluster.local:27017"'
|
||||
- name: username
|
||||
description: "The username of the user to connect with (applicable in conjunction with \"host\")"
|
||||
example: '"admin"'
|
||||
- name: password
|
||||
sensitive: true
|
||||
description: "The password of the user (applicable in conjunction with \"host\")"
|
||||
example: '"password"'
|
||||
- name: databaseName
|
||||
description: "The name of the database to use."
|
||||
default: '"daprStore"'
|
||||
example: '"daprStore"'
|
||||
- name: collectionName
|
||||
description: "The name of the collection to use."
|
||||
default: '"daprCollection"'
|
||||
example: '"daprCollection"'
|
||||
- name: writeconcern
|
||||
description: "The write concern to use"
|
||||
example: '"majority", "2"'
|
||||
- name: readconcern
|
||||
description: "The read concern to use"
|
||||
type: string
|
||||
allowedValues:
|
||||
- "available"
|
||||
- "local"
|
||||
- "linearizable"
|
||||
- "majority"
|
||||
- "snapshot"
|
||||
example: '"local"'
|
||||
- name: operationTimeout
|
||||
description: "The timeout for the operation."
|
||||
type: duration
|
||||
default: '"5s"'
|
||||
example: '"10s"'
|
||||
- name: params
|
||||
description: "Additional parameters to use when connecting. The params field accepts a query string that specifies connection specific options as \"<name>=<value>\" pairs, separated by \"&\" and prefixed with \"?\". See the MongoDB manual for the list of available options and their use cases."
|
||||
example: '"?authSource=daprStore&ssl=true"'
|
|
@ -0,0 +1,6 @@
|
|||
################################################################################
|
||||
# Target: e2e-tests-zeebe #
|
||||
################################################################################
|
||||
.PHONY: e2e-tests-zeebe
|
||||
e2e-tests-zeebe:
|
||||
CGO_ENABLED=$(CGO) go test -v -tags=e2etests -count=1 ./tests/e2e/bindings/zeebe/...
|
Loading…
Reference in New Issue