mirror of https://github.com/dapr/cli.git
Add dapr annotate command (#873)
* Add dapr inject command Signed-off-by: Joni Collinge <jonathancollinge@live.com> * Add additional opts Signed-off-by: Joni Collinge <jonathancollinge@live.com> * Update comment regarding injection Signed-off-by: Joni Collinge <jonathancollinge@live.com> * fix some linting issues (more to go) Signed-off-by: Joni Collinge <jonathancollinge@live.com> * use existing const in tests Signed-off-by: Joni Collinge <jonathancollinge@live.com> * fix some more linting Signed-off-by: Joni Collinge <jonathancollinge@live.com> * fix some more linting Signed-off-by: Joni Collinge <jonathancollinge@live.com> * udpate tests Signed-off-by: Joni Collinge <jonathancollinge@live.com> * udpate tests Signed-off-by: Joni Collinge <jonathancollinge@live.com> * add option to run against a URL Signed-off-by: Joni Collinge <jonathancollinge@live.com> * refactor cmd/inject.go slightly Signed-off-by: Joni Collinge <jonathancollinge@live.com> * update example text Signed-off-by: Joni Collinge <jonathancollinge@live.com> * autogenerate appid if not present Signed-off-by: Joni Collinge <jonathancollinge@live.com> * Update comment Signed-off-by: Joni Collinge <jonathancollinge@live.com> * Add support for target namespace Signed-off-by: Joni Collinge <jonathancollinge@live.com> * Update comment Signed-off-by: Joni Collinge <jonathancollinge@live.com> * Add warning about app id generation to usage Signed-off-by: Joni Collinge <jonathancollinge@live.com> * fix linting issues Signed-off-by: Joni Collinge <jonathancollinge@live.com> * rename inject to annotate Signed-off-by: Joni Collinge <jonathancollinge@live.com> * go mod tidy Signed-off-by: Joni Collinge <jonathancollinge@live.com> * fix lint Signed-off-by: Joni Collinge <jonathancollinge@live.com> * update --help URL Signed-off-by: Joni Collinge <jonathancollinge@live.com> * add README.md seciton Signed-off-by: Joni Collinge <jonathancollinge@live.com> Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
This commit is contained in:
parent
8e9c675bf6
commit
0630996fb4
34
README.md
34
README.md
|
@ -630,6 +630,40 @@ The default is `false`.
|
|||
|
||||
For more details, please run the command and check the examples to apply to your shell.
|
||||
|
||||
### Annotate a Kubernetes manifest
|
||||
|
||||
To add or modify dapr annotations on an existing Kubernetes manifest, use the `dapr annotate` command:
|
||||
|
||||
```bash
|
||||
dapr annotate [flags] mydeployment.yaml
|
||||
```
|
||||
|
||||
This will add the `dapr.io/enabled` and the `dapr.io/app-id` annotations. The dapr app id will be genereated using the format `<namespace>-<kind>-<name>` where the values are taken from the existing Kubernetes object metadata.
|
||||
|
||||
To provide your own dapr app id, provide the flag `--app-id`.
|
||||
|
||||
All dapr annotations are available to set if a value is provided for the appropriate flag on the `dapr annotate` command.
|
||||
|
||||
You can also provide the Kubernetes manifest via stdin:
|
||||
|
||||
```bash
|
||||
kubectl get deploy mydeploy -o yaml | dapr annotate - | kubectl apply -f -
|
||||
```
|
||||
|
||||
Or you can provide the Kubernetes manifest via a URL:
|
||||
|
||||
```bash
|
||||
dapr annotate --log-level debug https://raw.githubusercontent.com/dapr/quickstarts/master/tutorials/hello-kubernetes/deploy/node.yaml | kubectl apply -f -
|
||||
```
|
||||
|
||||
If the input contains multiple manifests then the command will search for the first appropriate one to apply the annotations. If you'd rather it applied to a specific manifest then you can provide the `--resource` flag with the value set to the name of the object you'd like to apply the annotations to. If you have a conflict between namespaces you can also provide the namespace via the `--namespace` flag to isolate the manifest you wish to target.
|
||||
|
||||
If you want to annotate multiple manifests, you can chain together the `dapr annotate` commands with each applying the annotation to a specific manifest.
|
||||
|
||||
```bash
|
||||
kubectl get deploy -o yaml | dapr annotate -r nodeapp --log-level debug - | dapr annotate --log-level debug -r pythonapp - | kubectl apply -f -
|
||||
```
|
||||
|
||||
## Reference for the Dapr CLI
|
||||
|
||||
See the [Reference Guide](https://docs.dapr.io/reference/cli/) for more information about individual Dapr commands.
|
||||
|
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
Copyright 2021 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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/dapr/cli/pkg/kubernetes"
|
||||
"github.com/dapr/cli/pkg/print"
|
||||
)
|
||||
|
||||
var (
|
||||
annotateTargetResource string
|
||||
annotateTargetNamespace string
|
||||
annotateAppID string
|
||||
annotateAppPort int
|
||||
annotateConfig string
|
||||
annotateAppProtocol string
|
||||
annotateEnableProfile bool
|
||||
annotateLogLevel string
|
||||
annotateAPITokenSecret string
|
||||
annotateAppTokenSecret string
|
||||
annotateLogAsJSON bool
|
||||
annotateAppMaxConcurrency int
|
||||
annotateEnableMetrics bool
|
||||
annotateMetricsPort int
|
||||
annotateEnableDebug bool
|
||||
annotateEnv string
|
||||
annotateCPULimit string
|
||||
annotateMemoryLimit string
|
||||
annotateCPURequest string
|
||||
annotateMemoryRequest string
|
||||
annotateListenAddresses string
|
||||
annotateLivenessProbeDelay int
|
||||
annotateLivenessProbeTimeout int
|
||||
annotateLivenessProbePeriod int
|
||||
annotateLivenessProbeThreshold int
|
||||
annotateReadinessProbeDelay int
|
||||
annotateReadinessProbeTimeout int
|
||||
annotateReadinessProbePeriod int
|
||||
annotateReadinessProbeThreshold int
|
||||
annotateDaprImage string
|
||||
annotateAppSSL bool
|
||||
annotateMaxRequestBodySize int
|
||||
annotateHTTPStreamRequestBody bool
|
||||
annotateGracefulShutdownSeconds int
|
||||
)
|
||||
|
||||
var AnnotateCmd = &cobra.Command{
|
||||
Use: "annotate [flags] CONFIG-FILE",
|
||||
Short: "Add dapr annotations to a Kubernetes configuration. Supported platforms: Kubernetes",
|
||||
Example: `
|
||||
# Annotate the first deployment found in the input
|
||||
kubectl get deploy -l app=node -o yaml | dapr annotate - | kubectl apply -f -
|
||||
|
||||
# Annotate multiple deployments by name in a chain
|
||||
kubectl get deploy -o yaml | dapr annotate -r nodeapp - | dapr annotate -r pythonapp - | kubectl apply -f -
|
||||
|
||||
# Annotate deployment in a specific namespace from file or directory by name
|
||||
dapr annotate -r nodeapp -n namespace mydeploy.yaml | kubectl apply -f -
|
||||
|
||||
# Annotate deployment from url by name
|
||||
dapr annotate -r nodeapp --log-level debug https://raw.githubusercontent.com/dapr/quickstarts/master/tutorials/hello-kubernetes/deploy/node.yaml | kubectl apply -f -
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
WARNING: If an app id is not provided, we will generate one using the format '<namespace>-<kind>-<name>'.
|
||||
--------------------------------------------------------------------------------
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) < 1 {
|
||||
print.FailureStatusEvent(os.Stderr, "please specify a kubernetes resource file")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
input, err := readInput(args[0])
|
||||
if err != nil {
|
||||
print.FailureStatusEvent(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var config kubernetes.K8sAnnotatorConfig
|
||||
if annotateTargetResource != "" {
|
||||
config = kubernetes.K8sAnnotatorConfig{
|
||||
TargetResource: &annotateTargetResource,
|
||||
} // nolint:exhaustivestruct
|
||||
if annotateTargetNamespace != "" {
|
||||
config.TargetNamespace = &annotateTargetNamespace
|
||||
}
|
||||
} else {
|
||||
if annotateTargetNamespace != "" {
|
||||
// The resource is empty but namespace is set, this
|
||||
// is invalid as we cannot search for a resource
|
||||
// if the identifier isn't provided.
|
||||
print.FailureStatusEvent(os.Stderr, "--resource is required when --namespace is provided.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
annotator := kubernetes.NewK8sAnnotator(config)
|
||||
opts := getOptionsFromFlags()
|
||||
if err := annotator.Annotate(input, os.Stdout, opts); err != nil {
|
||||
print.FailureStatusEvent(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func readInput(arg string) ([]io.Reader, error) {
|
||||
var inputs []io.Reader
|
||||
var err error
|
||||
if arg == "-" {
|
||||
// input is from stdin.
|
||||
inputs = append(inputs, os.Stdin)
|
||||
} else if isURL(arg) {
|
||||
inputs, err = readInputsFromURL(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// input is from file or dir.
|
||||
inputs, err = readInputsFromFS(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return inputs, nil
|
||||
}
|
||||
|
||||
func readInputsFromURL(url string) ([]io.Reader, error) {
|
||||
resp, err := http.Get(url) // #nosec
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unable to read from %s: %d - %s", url, resp.StatusCode, resp.Status)
|
||||
}
|
||||
|
||||
var b []byte
|
||||
b, err = ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reader := bytes.NewReader(b)
|
||||
return []io.Reader{reader}, nil
|
||||
}
|
||||
|
||||
func isURL(maybeURL string) bool {
|
||||
url, err := url.ParseRequestURI(maybeURL)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return url.Host != "" && url.Scheme != ""
|
||||
}
|
||||
|
||||
func readInputsFromFS(path string) ([]io.Reader, error) {
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !stat.IsDir() {
|
||||
// input is a file.
|
||||
var file *os.File
|
||||
file, err = os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []io.Reader{file}, nil
|
||||
}
|
||||
|
||||
// input is a directory.
|
||||
var inputs []io.Reader
|
||||
err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inputs = append(inputs, file)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return inputs, nil
|
||||
}
|
||||
|
||||
func getOptionsFromFlags() kubernetes.AnnotateOptions {
|
||||
// TODO: Use a pointer for int flag where zero is nil not -1.
|
||||
o := []kubernetes.AnnoteOption{}
|
||||
if annotateAppID != "" {
|
||||
o = append(o, kubernetes.WithAppID(annotateAppID))
|
||||
}
|
||||
if annotateConfig != "" {
|
||||
o = append(o, kubernetes.WithConfig(annotateConfig))
|
||||
}
|
||||
if annotateAppPort != -1 {
|
||||
o = append(o, kubernetes.WithAppPort(annotateAppPort))
|
||||
}
|
||||
if annotateAppProtocol != "" {
|
||||
o = append(o, kubernetes.WithAppProtocol(annotateAppProtocol))
|
||||
}
|
||||
if annotateEnableProfile {
|
||||
o = append(o, kubernetes.WithProfileEnabled())
|
||||
}
|
||||
if annotateLogLevel != "" {
|
||||
o = append(o, kubernetes.WithLogLevel(annotateLogLevel))
|
||||
}
|
||||
if annotateAPITokenSecret != "" {
|
||||
o = append(o, kubernetes.WithAPITokenSecret(annotateAPITokenSecret))
|
||||
}
|
||||
if annotateAppTokenSecret != "" {
|
||||
o = append(o, kubernetes.WithAppTokenSecret(annotateAppTokenSecret))
|
||||
}
|
||||
if annotateLogAsJSON {
|
||||
o = append(o, kubernetes.WithLogAsJSON())
|
||||
}
|
||||
if annotateAppMaxConcurrency != -1 {
|
||||
o = append(o, kubernetes.WithAppMaxConcurrency(annotateAppMaxConcurrency))
|
||||
}
|
||||
if annotateEnableMetrics {
|
||||
o = append(o, kubernetes.WithMetricsEnabled())
|
||||
}
|
||||
if annotateMetricsPort != -1 {
|
||||
o = append(o, kubernetes.WithMetricsPort(annotateMetricsPort))
|
||||
}
|
||||
if annotateEnableDebug {
|
||||
o = append(o, kubernetes.WithDebugEnabled())
|
||||
}
|
||||
if annotateEnv != "" {
|
||||
o = append(o, kubernetes.WithEnv(annotateEnv))
|
||||
}
|
||||
if annotateCPULimit != "" {
|
||||
o = append(o, kubernetes.WithCPULimit(annotateCPULimit))
|
||||
}
|
||||
if annotateMemoryLimit != "" {
|
||||
o = append(o, kubernetes.WithMemoryLimit(annotateMemoryLimit))
|
||||
}
|
||||
if annotateCPURequest != "" {
|
||||
o = append(o, kubernetes.WithCPURequest(annotateCPURequest))
|
||||
}
|
||||
if annotateMemoryRequest != "" {
|
||||
o = append(o, kubernetes.WithMemoryRequest(annotateMemoryRequest))
|
||||
}
|
||||
if annotateListenAddresses != "" {
|
||||
o = append(o, kubernetes.WithListenAddresses(annotateListenAddresses))
|
||||
}
|
||||
if annotateLivenessProbeDelay != -1 {
|
||||
o = append(o, kubernetes.WithLivenessProbeDelay(annotateLivenessProbeDelay))
|
||||
}
|
||||
if annotateLivenessProbeTimeout != -1 {
|
||||
o = append(o, kubernetes.WithLivenessProbeTimeout(annotateLivenessProbeTimeout))
|
||||
}
|
||||
if annotateLivenessProbePeriod != -1 {
|
||||
o = append(o, kubernetes.WithLivenessProbePeriod(annotateLivenessProbePeriod))
|
||||
}
|
||||
if annotateLivenessProbeThreshold != -1 {
|
||||
o = append(o, kubernetes.WithLivenessProbeThreshold(annotateLivenessProbeThreshold))
|
||||
}
|
||||
if annotateReadinessProbeDelay != -1 {
|
||||
o = append(o, kubernetes.WithReadinessProbeDelay(annotateReadinessProbeDelay))
|
||||
}
|
||||
if annotateReadinessProbeTimeout != -1 {
|
||||
o = append(o, kubernetes.WithReadinessProbeTimeout(annotateReadinessProbeTimeout))
|
||||
}
|
||||
if annotateReadinessProbePeriod != -1 {
|
||||
o = append(o, kubernetes.WithReadinessProbePeriod(annotateReadinessProbePeriod))
|
||||
}
|
||||
if annotateReadinessProbeThreshold != -1 {
|
||||
o = append(o, kubernetes.WithReadinessProbeThreshold(annotateReadinessProbeThreshold))
|
||||
}
|
||||
if annotateDaprImage != "" {
|
||||
o = append(o, kubernetes.WithDaprImage(annotateDaprImage))
|
||||
}
|
||||
if annotateAppSSL {
|
||||
o = append(o, kubernetes.WithAppSSL())
|
||||
}
|
||||
if annotateMaxRequestBodySize != -1 {
|
||||
o = append(o, kubernetes.WithMaxRequestBodySize(annotateMaxRequestBodySize))
|
||||
}
|
||||
if annotateHTTPStreamRequestBody {
|
||||
o = append(o, kubernetes.WithHTTPStreamRequestBody())
|
||||
}
|
||||
if annotateGracefulShutdownSeconds != -1 {
|
||||
o = append(o, kubernetes.WithGracefulShutdownSeconds(annotateGracefulShutdownSeconds))
|
||||
}
|
||||
return kubernetes.NewAnnotateOptions(o...)
|
||||
}
|
||||
|
||||
func init() {
|
||||
AnnotateCmd.Flags().StringVarP(&annotateTargetResource, "resource", "r", "", "The resource to target to annotate")
|
||||
AnnotateCmd.Flags().StringVarP(&annotateTargetNamespace, "namespace", "n", "", "The namespace the resource target is in (can only be set if --resource is also set)")
|
||||
AnnotateCmd.Flags().StringVarP(&annotateAppID, "app-id", "a", "", "The app id to annotate")
|
||||
AnnotateCmd.Flags().IntVarP(&annotateAppPort, "app-port", "p", -1, "The port to expose the app on")
|
||||
AnnotateCmd.Flags().StringVarP(&annotateConfig, "config", "c", "", "The config file to annotate")
|
||||
AnnotateCmd.Flags().StringVar(&annotateAppProtocol, "app-protocol", "", "The protocol to use for the app")
|
||||
AnnotateCmd.Flags().BoolVar(&annotateEnableProfile, "enable-profile", false, "Enable profiling")
|
||||
AnnotateCmd.Flags().StringVar(&annotateLogLevel, "log-level", "", "The log level to use")
|
||||
AnnotateCmd.Flags().StringVar(&annotateAPITokenSecret, "api-token-secret", "", "The secret to use for the API token")
|
||||
AnnotateCmd.Flags().StringVar(&annotateAppTokenSecret, "app-token-secret", "", "The secret to use for the app token")
|
||||
AnnotateCmd.Flags().BoolVar(&annotateLogAsJSON, "log-as-json", false, "Log as JSON")
|
||||
AnnotateCmd.Flags().IntVar(&annotateAppMaxConcurrency, "app-max-concurrency", -1, "The maximum number of concurrent requests to allow")
|
||||
AnnotateCmd.Flags().BoolVar(&annotateEnableMetrics, "enable-metrics", false, "Enable metrics")
|
||||
AnnotateCmd.Flags().IntVar(&annotateMetricsPort, "metrics-port", -1, "The port to expose the metrics on")
|
||||
AnnotateCmd.Flags().BoolVar(&annotateEnableDebug, "enable-debug", false, "Enable debug")
|
||||
AnnotateCmd.Flags().StringVar(&annotateEnv, "env", "", "Environment variables to set (key value pairs, comma separated)")
|
||||
AnnotateCmd.Flags().StringVar(&annotateCPULimit, "cpu-limit", "", "The CPU limit to set")
|
||||
AnnotateCmd.Flags().StringVar(&annotateMemoryLimit, "memory-limit", "", "The memory limit to set")
|
||||
AnnotateCmd.Flags().StringVar(&annotateCPURequest, "cpu-request", "", "The CPU request to set")
|
||||
AnnotateCmd.Flags().StringVar(&annotateMemoryRequest, "memory-request", "", "The memory request to set")
|
||||
AnnotateCmd.Flags().StringVar(&annotateListenAddresses, "listen-addresses", "", "The addresses to listen on")
|
||||
AnnotateCmd.Flags().IntVar(&annotateLivenessProbeDelay, "liveness-probe-delay", -1, "The delay to use for the liveness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateLivenessProbeTimeout, "liveness-probe-timeout", -1, "The timeout to use for the liveness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateLivenessProbePeriod, "liveness-probe-period", -1, "The period to use for the liveness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateLivenessProbeThreshold, "liveness-probe-threshold", -1, "The threshold to use for the liveness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateReadinessProbeDelay, "readiness-probe-delay", -1, "The delay to use for the readiness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateReadinessProbeTimeout, "readiness-probe-timeout", -1, "The timeout to use for the readiness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateReadinessProbePeriod, "readiness-probe-period", -1, "The period to use for the readiness probe")
|
||||
AnnotateCmd.Flags().IntVar(&annotateReadinessProbeThreshold, "readiness-probe-threshold", -1, "The threshold to use for the readiness probe")
|
||||
AnnotateCmd.Flags().StringVar(&annotateDaprImage, "dapr-image", "", "The image to use for the dapr sidecar container")
|
||||
AnnotateCmd.Flags().BoolVar(&annotateAppSSL, "app-ssl", false, "Enable SSL for the app")
|
||||
AnnotateCmd.Flags().IntVar(&annotateMaxRequestBodySize, "max-request-body-size", -1, "The maximum request body size to use")
|
||||
AnnotateCmd.Flags().BoolVar(&annotateHTTPStreamRequestBody, "http-stream-request-body", false, "Enable streaming request body for HTTP")
|
||||
AnnotateCmd.Flags().IntVar(&annotateGracefulShutdownSeconds, "graceful-shutdown-seconds", -1, "The number of seconds to wait for the app to shutdown")
|
||||
RootCmd.AddCommand(AnnotateCmd)
|
||||
}
|
16
go.mod
16
go.mod
|
@ -3,6 +3,8 @@ module github.com/dapr/cli
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/Azure/go-autorest/autorest v0.11.23 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.16 // indirect
|
||||
github.com/Pallinder/sillyname-go v0.0.0-20130730142914-97aeae9e6ba1
|
||||
github.com/briandowns/spinner v1.6.1
|
||||
github.com/dapr/dapr v1.7.0
|
||||
|
@ -30,14 +32,15 @@ require (
|
|||
k8s.io/cli-runtime v0.23.4
|
||||
k8s.io/client-go v0.23.4
|
||||
k8s.io/helm v2.16.10+incompatible
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require github.com/evanphx/json-patch v4.12.0+incompatible
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.99.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.23 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.16 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
|
@ -52,6 +55,7 @@ require (
|
|||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||
github.com/andybalholm/brotli v1.0.2 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
|
@ -67,7 +71,6 @@ require (
|
|||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
|
@ -80,6 +83,7 @@ require (
|
|||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.6 // indirect
|
||||
|
@ -99,6 +103,7 @@ require (
|
|||
github.com/jmoiron/sqlx v1.3.4 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||
github.com/klauspost/compress v1.14.4 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
|
@ -147,10 +152,14 @@ require (
|
|||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||
github.com/tklauser/numcpus v0.2.2 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.31.1-0.20211216042702-258a4c17b4f4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.opentelemetry.io/otel v0.20.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 // indirect
|
||||
golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d // indirect
|
||||
|
@ -178,7 +187,6 @@ require (
|
|||
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
|
|
13
go.sum
13
go.sum
|
@ -146,6 +146,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
|||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
|
@ -706,12 +708,15 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
|||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/karrick/godirwalk v1.15.8 h1:7+rWAZPn9zuRxaIqqT8Ohs2Q2Ac0msBqwRdxNCr2VVs=
|
||||
github.com/karrick/godirwalk v1.15.8/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
|
||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
|
||||
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
|
@ -1081,6 +1086,11 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
|
|||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.31.1-0.20211216042702-258a4c17b4f4 h1:UKbv1Y0TRLKcgacl2+v4xPt3iJLhjP0RCGwMOkUW1ko=
|
||||
github.com/valyala/fasthttp v1.31.1-0.20211216042702-258a4c17b4f4/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
|
@ -1141,6 +1151,7 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
|||
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
|
||||
go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g=
|
||||
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
|
||||
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
|
||||
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
|
||||
|
@ -1181,6 +1192,7 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
|
|||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
|
@ -1275,6 +1287,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
|
|||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
|
|
@ -0,0 +1,495 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
yamlDecoder "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/dapr/dapr/pkg/injector"
|
||||
)
|
||||
|
||||
const (
|
||||
// Dapr annotation keys.
|
||||
daprEnabledKey = "dapr.io/enabled"
|
||||
daprAppPortKey = "dapr.io/app-port"
|
||||
daprConfigKey = "dapr.io/config"
|
||||
daprAppProtocolKey = "dapr.io/app-protocol"
|
||||
daprAppIDKey = "dapr.io/app-id"
|
||||
daprEnableProfilingKey = "dapr.io/enable-profiling"
|
||||
daprLogLevelKey = "dapr.io/log-level"
|
||||
daprAPITokenSecretKey = "dapr.io/api-token-secret" /* #nosec */
|
||||
daprAppTokenSecretKey = "dapr.io/app-token-secret" /* #nosec */
|
||||
daprLogAsJSONKey = "dapr.io/log-as-json"
|
||||
daprAppMaxConcurrencyKey = "dapr.io/app-max-concurrency"
|
||||
daprEnableMetricsKey = "dapr.io/enable-metrics"
|
||||
daprMetricsPortKey = "dapr.io/metrics-port"
|
||||
daprEnableDebugKey = "dapr.io/enable-debug"
|
||||
daprDebugPortKey = "dapr.io/debug-port"
|
||||
daprEnvKey = "dapr.io/env"
|
||||
daprCPULimitKey = "dapr.io/sidecar-cpu-limit"
|
||||
daprMemoryLimitKey = "dapr.io/sidecar-memory-limit"
|
||||
daprCPURequestKey = "dapr.io/sidecar-cpu-request"
|
||||
daprMemoryRequestKey = "dapr.io/sidecar-memory-request"
|
||||
daprListenAddressesKey = "dapr.io/sidecar-listen-addresses"
|
||||
daprLivenessProbeDelayKey = "dapr.io/sidecar-liveness-probe-delay-seconds"
|
||||
daprLivenessProbeTimeoutKey = "dapr.io/sidecar-liveness-probe-timeout-seconds"
|
||||
daprLivenessProbePeriodKey = "dapr.io/sidecar-liveness-probe-period-seconds"
|
||||
daprLivenessProbeThresholdKey = "dapr.io/sidecar-liveness-probe-threshold"
|
||||
daprReadinessProbeDelayKey = "dapr.io/sidecar-readiness-probe-delay-seconds"
|
||||
daprReadinessProbeTimeoutKey = "dapr.io/sidecar-readiness-probe-timeout-seconds"
|
||||
daprReadinessProbePeriodKey = "dapr.io/sidecar-readiness-probe-period-seconds"
|
||||
daprReadinessProbeThresholdKey = "dapr.io/sidecar-readiness-probe-threshold"
|
||||
daprImageKey = "dapr.io/sidecar-image"
|
||||
daprAppSSLKey = "dapr.io/app-ssl"
|
||||
daprMaxRequestBodySizeKey = "dapr.io/http-max-request-size"
|
||||
daprReadBufferSizeKey = "dapr.io/http-read-buffer-size"
|
||||
daprHTTPStreamRequestBodyKey = "dapr.io/http-stream-request-body"
|
||||
daprGracefulShutdownSecondsKey = "dapr.io/graceful-shutdown-seconds"
|
||||
|
||||
// K8s kinds.
|
||||
pod = "pod"
|
||||
deployment = "deployment"
|
||||
replicaset = "replicaset"
|
||||
daemonset = "daemonset"
|
||||
statefulset = "statefulset"
|
||||
cronjob = "cronjob"
|
||||
job = "job"
|
||||
list = "list"
|
||||
|
||||
cronjobAnnotationsPath = "/spec/jobTemplate/spec/template/metadata/annotations"
|
||||
podAnnotationsPath = "/metadata/annotations"
|
||||
templateAnnotationsPath = "/spec/template/metadata/annotations"
|
||||
)
|
||||
|
||||
type Annotator interface {
|
||||
Annotate(io.Reader, io.Writer) error
|
||||
}
|
||||
|
||||
type K8sAnnotator struct {
|
||||
config K8sAnnotatorConfig
|
||||
annotated bool
|
||||
}
|
||||
|
||||
type K8sAnnotatorConfig struct {
|
||||
// If TargetResource is set, we will search for it and then inject
|
||||
// annotations on that target resource. If it is not set, we will
|
||||
// update the first appropriate resource we find.
|
||||
TargetResource *string
|
||||
// If TargetNamespace is set, we will search for the target resource
|
||||
// in the provided target namespace. If it is not set, we will
|
||||
// just search for the first occurrence of the target resource.
|
||||
TargetNamespace *string
|
||||
}
|
||||
|
||||
func NewK8sAnnotator(config K8sAnnotatorConfig) *K8sAnnotator {
|
||||
return &K8sAnnotator{
|
||||
config: config,
|
||||
annotated: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Annotate injects dapr annotations into the kubernetes resource.
|
||||
func (p *K8sAnnotator) Annotate(inputs []io.Reader, out io.Writer, opts AnnotateOptions) error {
|
||||
for _, input := range inputs {
|
||||
err := p.processInput(input, out, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *K8sAnnotator) processInput(input io.Reader, out io.Writer, opts AnnotateOptions) error {
|
||||
reader := yamlDecoder.NewYAMLReader(bufio.NewReaderSize(input, 4096))
|
||||
|
||||
var result []byte
|
||||
iterations := 0
|
||||
// Read from input and process until EOF or error.
|
||||
for {
|
||||
bytes, err := reader.Read()
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the input is a list as
|
||||
// these requires additional processing.
|
||||
var metaType metav1.TypeMeta
|
||||
if err = yaml.Unmarshal(bytes, &metaType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kind := strings.ToLower(metaType.Kind)
|
||||
if kind == list {
|
||||
var sourceList corev1.List
|
||||
if err = yaml.Unmarshal(bytes, &sourceList); err != nil {
|
||||
return err
|
||||
}
|
||||
items := []runtime.RawExtension{}
|
||||
for _, item := range sourceList.Items {
|
||||
var processedYAML []byte
|
||||
processedYAML, err = p.processYAML(item.Raw, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var annotatedJSON []byte
|
||||
annotatedJSON, err = yaml.YAMLToJSON(processedYAML)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
items = append(items, runtime.RawExtension{Raw: annotatedJSON}) // nolint:exhaustivestruct
|
||||
}
|
||||
sourceList.Items = items
|
||||
result, err = yaml.Marshal(sourceList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
var processedYAML []byte
|
||||
processedYAML, err = p.processYAML(bytes, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result = processedYAML
|
||||
}
|
||||
|
||||
// Insert separator between documents.
|
||||
if iterations > 0 {
|
||||
out.Write([]byte("---\n"))
|
||||
}
|
||||
|
||||
// Write result from processing into the writer.
|
||||
_, err = out.Write(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
iterations++
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *K8sAnnotator) processYAML(yamlBytes []byte, opts AnnotateOptions) ([]byte, error) {
|
||||
var err error
|
||||
var processedYAML []byte
|
||||
if p.annotated {
|
||||
// We can only inject dapr into a single resource per execution as the configuration
|
||||
// options are scoped to a single resource e.g. app-id, port, etc. are specific to a
|
||||
// dapr enabled resource. Instead we expect multiple runs to be piped together.
|
||||
processedYAML = yamlBytes
|
||||
} else {
|
||||
var annotated bool
|
||||
processedYAML, annotated, err = p.annotateYAML(yamlBytes, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if annotated {
|
||||
// Record that we have injected into a document.
|
||||
p.annotated = annotated
|
||||
}
|
||||
}
|
||||
return processedYAML, nil
|
||||
}
|
||||
|
||||
func (p *K8sAnnotator) annotateYAML(input []byte, config AnnotateOptions) ([]byte, bool, error) {
|
||||
// We read the metadata again here so this method is encapsulated.
|
||||
var metaType metav1.TypeMeta
|
||||
if err := yaml.Unmarshal(input, &metaType); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// If the input resource is a 'kind' that
|
||||
// we want to inject dapr into, then we
|
||||
// Unmarshal the input into the appropriate
|
||||
// type and set the required fields to build
|
||||
// a patch (path, value, op).
|
||||
var path string
|
||||
var annotations map[string]string
|
||||
var name string
|
||||
var ns string
|
||||
|
||||
kind := strings.ToLower(metaType.Kind)
|
||||
switch kind {
|
||||
case pod:
|
||||
pod := &corev1.Pod{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, pod); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = pod.Name
|
||||
annotations = pod.Annotations
|
||||
path = podAnnotationsPath
|
||||
ns = getNamespaceOrDefault(pod)
|
||||
case cronjob:
|
||||
cronjob := &batchv1beta1.CronJob{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, cronjob); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = cronjob.Name
|
||||
annotations = cronjob.Spec.JobTemplate.Spec.Template.Annotations
|
||||
path = cronjobAnnotationsPath
|
||||
ns = getNamespaceOrDefault(cronjob)
|
||||
case deployment:
|
||||
deployment := &appsv1.Deployment{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, deployment); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = deployment.Name
|
||||
annotations = deployment.Spec.Template.Annotations
|
||||
path = templateAnnotationsPath
|
||||
ns = getNamespaceOrDefault(deployment)
|
||||
case replicaset:
|
||||
replicaset := &appsv1.ReplicaSet{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, replicaset); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = replicaset.Name
|
||||
annotations = replicaset.Spec.Template.Annotations
|
||||
path = templateAnnotationsPath
|
||||
ns = getNamespaceOrDefault(replicaset)
|
||||
case job:
|
||||
job := &batchv1.Job{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, job); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = job.Name
|
||||
annotations = job.Spec.Template.Annotations
|
||||
path = templateAnnotationsPath
|
||||
ns = getNamespaceOrDefault(job)
|
||||
case statefulset:
|
||||
statefulset := &appsv1.StatefulSet{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, statefulset); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = statefulset.Name
|
||||
annotations = statefulset.Spec.Template.Annotations
|
||||
path = templateAnnotationsPath
|
||||
ns = getNamespaceOrDefault(statefulset)
|
||||
case daemonset:
|
||||
daemonset := &appsv1.DaemonSet{} // nolint:exhaustivestruct
|
||||
if err := yaml.Unmarshal(input, daemonset); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
name = daemonset.Name
|
||||
annotations = daemonset.Spec.Template.Annotations
|
||||
path = templateAnnotationsPath
|
||||
ns = getNamespaceOrDefault(daemonset)
|
||||
default:
|
||||
// No annotation needed for this kind.
|
||||
return input, false, nil
|
||||
}
|
||||
|
||||
// TODO: Currently this is where we decide not to
|
||||
// annotate dapr on this resource as it isn't the
|
||||
// target we are looking for. This is a bit late
|
||||
// so it would be good to find a earlier place to
|
||||
// do this.
|
||||
if p.config.TargetResource != nil && *p.config.TargetResource != "" {
|
||||
if !strings.EqualFold(*p.config.TargetResource, name) {
|
||||
// Not the resource name we're annotating.
|
||||
return input, false, nil
|
||||
}
|
||||
if p.config.TargetNamespace != nil && *p.config.TargetNamespace != "" {
|
||||
if !strings.EqualFold(*p.config.TargetNamespace, ns) {
|
||||
// Not the namespace we're annotating.
|
||||
return input, false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the dapr annotations and set them on the
|
||||
// resources existing annotation map. This will
|
||||
// override any existing conflicting annotations.
|
||||
if annotations == nil {
|
||||
annotations = make(map[string]string)
|
||||
}
|
||||
daprAnnotations := getDaprAnnotations(&config)
|
||||
for k, v := range daprAnnotations {
|
||||
// TODO: Should we log when we are overwriting?
|
||||
// if _, exists := annotations[k]; exists {}.
|
||||
annotations[k] = v
|
||||
}
|
||||
|
||||
// Check if the app id has been set, if not, we'll
|
||||
// use the resource metadata namespace, kind and name.
|
||||
// For example: namespace-kind-name.
|
||||
if _, appIDSet := annotations[daprAppIDKey]; !appIDSet {
|
||||
annotations[daprAppIDKey] = fmt.Sprintf("%s-%s-%s", ns, kind, name)
|
||||
}
|
||||
|
||||
// Create a patch operation for the annotations.
|
||||
patchOps := []injector.PatchOperation{}
|
||||
patchOps = append(patchOps, injector.PatchOperation{
|
||||
Op: "add",
|
||||
Path: path,
|
||||
Value: annotations,
|
||||
})
|
||||
patchBytes, err := json.Marshal(patchOps)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if len(patchBytes) == 0 {
|
||||
return input, false, nil
|
||||
}
|
||||
patch, err := jsonpatch.DecodePatch(patchBytes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// As we are applying the patch as a json patch,
|
||||
// we have to convert the current YAML resource to
|
||||
// JSON, apply the patch and then convert back.
|
||||
inputAsJSON, err := yaml.YAMLToJSON(input)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
annotatedAsJSON, err := patch.Apply(inputAsJSON)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
annotatedAsYAML, err := yaml.JSONToYAML(annotatedAsJSON)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return annotatedAsYAML, true, nil
|
||||
}
|
||||
|
||||
type NamespacedObject interface {
|
||||
GetNamespace() string
|
||||
}
|
||||
|
||||
func getNamespaceOrDefault(obj NamespacedObject) string {
|
||||
ns := obj.GetNamespace()
|
||||
if ns == "" {
|
||||
return "default"
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
func getDaprAnnotations(config *AnnotateOptions) map[string]string {
|
||||
annotations := make(map[string]string)
|
||||
|
||||
annotations[daprEnabledKey] = "true"
|
||||
if config.appID != nil {
|
||||
annotations[daprAppIDKey] = *config.appID
|
||||
}
|
||||
if config.metricsEnabled != nil {
|
||||
annotations[daprEnableMetricsKey] = strconv.FormatBool(*config.metricsEnabled)
|
||||
}
|
||||
if config.metricsPort != nil {
|
||||
annotations[daprMetricsPortKey] = strconv.FormatInt(int64(*config.metricsPort), 10)
|
||||
}
|
||||
if config.appPort != nil {
|
||||
annotations[daprAppPortKey] = strconv.FormatInt(int64(*config.appPort), 10)
|
||||
}
|
||||
if config.config != nil {
|
||||
annotations[daprConfigKey] = *config.config
|
||||
}
|
||||
if config.appProtocol != nil {
|
||||
annotations[daprAppProtocolKey] = *config.appProtocol
|
||||
}
|
||||
if config.profileEnabled != nil {
|
||||
annotations[daprEnableProfilingKey] = strconv.FormatBool(*config.profileEnabled)
|
||||
}
|
||||
if config.logLevel != nil {
|
||||
annotations[daprLogLevelKey] = *config.logLevel
|
||||
}
|
||||
if config.logAsJSON != nil {
|
||||
annotations[daprLogAsJSONKey] = strconv.FormatBool(*config.logAsJSON)
|
||||
}
|
||||
if config.apiTokenSecret != nil {
|
||||
annotations[daprAPITokenSecretKey] = *config.apiTokenSecret
|
||||
}
|
||||
if config.appTokenSecret != nil {
|
||||
annotations[daprAppTokenSecretKey] = *config.appTokenSecret
|
||||
}
|
||||
if config.appMaxConcurrency != nil {
|
||||
annotations[daprAppMaxConcurrencyKey] = strconv.FormatInt(int64(*config.appMaxConcurrency), 10)
|
||||
}
|
||||
if config.debugEnabled != nil {
|
||||
annotations[daprEnableDebugKey] = strconv.FormatBool(*config.debugEnabled)
|
||||
}
|
||||
if config.debugPort != nil {
|
||||
annotations[daprDebugPortKey] = strconv.FormatInt(int64(*config.debugPort), 10)
|
||||
}
|
||||
if config.env != nil {
|
||||
annotations[daprEnvKey] = *config.env
|
||||
}
|
||||
if config.cpuLimit != nil {
|
||||
annotations[daprCPULimitKey] = *config.cpuLimit
|
||||
}
|
||||
if config.memoryLimit != nil {
|
||||
annotations[daprMemoryLimitKey] = *config.memoryLimit
|
||||
}
|
||||
if config.cpuRequest != nil {
|
||||
annotations[daprCPURequestKey] = *config.cpuRequest
|
||||
}
|
||||
if config.memoryRequest != nil {
|
||||
annotations[daprMemoryRequestKey] = *config.memoryRequest
|
||||
}
|
||||
if config.listenAddresses != nil {
|
||||
annotations[daprListenAddressesKey] = *config.listenAddresses
|
||||
}
|
||||
if config.livenessProbeDelay != nil {
|
||||
annotations[daprLivenessProbeDelayKey] = strconv.FormatInt(int64(*config.livenessProbeDelay), 10)
|
||||
}
|
||||
if config.livenessProbeTimeout != nil {
|
||||
annotations[daprLivenessProbeTimeoutKey] = strconv.FormatInt(int64(*config.livenessProbeTimeout), 10)
|
||||
}
|
||||
if config.livenessProbePeriod != nil {
|
||||
annotations[daprLivenessProbePeriodKey] = strconv.FormatInt(int64(*config.livenessProbePeriod), 10)
|
||||
}
|
||||
if config.livenessProbeThreshold != nil {
|
||||
annotations[daprLivenessProbeThresholdKey] = strconv.FormatInt(int64(*config.livenessProbeThreshold), 10)
|
||||
}
|
||||
if config.readinessProbeDelay != nil {
|
||||
annotations[daprReadinessProbeDelayKey] = strconv.FormatInt(int64(*config.readinessProbeDelay), 10)
|
||||
}
|
||||
if config.readinessProbeTimeout != nil {
|
||||
annotations[daprReadinessProbeTimeoutKey] = strconv.FormatInt(int64(*config.readinessProbeTimeout), 10)
|
||||
}
|
||||
if config.readinessProbePeriod != nil {
|
||||
annotations[daprReadinessProbePeriodKey] = strconv.FormatInt(int64(*config.readinessProbePeriod), 10)
|
||||
}
|
||||
if config.readinessProbeThreshold != nil {
|
||||
annotations[daprReadinessProbeThresholdKey] = strconv.FormatInt(int64(*config.readinessProbeThreshold), 10)
|
||||
}
|
||||
if config.image != nil {
|
||||
annotations[daprImageKey] = *config.image
|
||||
}
|
||||
if config.appSSL != nil {
|
||||
annotations[daprAppSSLKey] = strconv.FormatBool(*config.appSSL)
|
||||
}
|
||||
if config.maxRequestBodySize != nil {
|
||||
annotations[daprMaxRequestBodySizeKey] = strconv.FormatInt(int64(*config.maxRequestBodySize), 10)
|
||||
}
|
||||
if config.readBufferSize != nil {
|
||||
annotations[daprReadBufferSizeKey] = strconv.FormatInt(int64(*config.readBufferSize), 10)
|
||||
}
|
||||
if config.httpStreamRequestBody != nil {
|
||||
annotations[daprHTTPStreamRequestBodyKey] = strconv.FormatBool(*config.httpStreamRequestBody)
|
||||
}
|
||||
if config.gracefulShutdownSeconds != nil {
|
||||
annotations[daprGracefulShutdownSecondsKey] = strconv.FormatInt(int64(*config.gracefulShutdownSeconds), 10)
|
||||
}
|
||||
|
||||
return annotations
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
package kubernetes
|
||||
|
||||
// AnnotateOptions configure the injection behavior.
|
||||
type AnnotateOptions struct {
|
||||
appID *string
|
||||
metricsEnabled *bool
|
||||
metricsPort *int
|
||||
appPort *int
|
||||
config *string
|
||||
appProtocol *string
|
||||
profileEnabled *bool
|
||||
logLevel *string
|
||||
apiTokenSecret *string
|
||||
appTokenSecret *string
|
||||
logAsJSON *bool
|
||||
appMaxConcurrency *int
|
||||
debugEnabled *bool
|
||||
debugPort *int
|
||||
env *string
|
||||
cpuLimit *string
|
||||
memoryLimit *string
|
||||
cpuRequest *string
|
||||
memoryRequest *string
|
||||
listenAddresses *string
|
||||
livenessProbeDelay *int
|
||||
livenessProbeTimeout *int
|
||||
livenessProbePeriod *int
|
||||
livenessProbeThreshold *int
|
||||
readinessProbeDelay *int
|
||||
readinessProbeTimeout *int
|
||||
readinessProbePeriod *int
|
||||
readinessProbeThreshold *int
|
||||
image *string
|
||||
appSSL *bool
|
||||
maxRequestBodySize *int
|
||||
readBufferSize *int
|
||||
httpStreamRequestBody *bool
|
||||
gracefulShutdownSeconds *int
|
||||
}
|
||||
|
||||
type AnnoteOption func(*AnnotateOptions)
|
||||
|
||||
func NewAnnotateOptions(opts ...AnnoteOption) AnnotateOptions {
|
||||
config := AnnotateOptions{} // nolint:exhaustivestruct
|
||||
for _, opt := range opts {
|
||||
opt(&config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
func WithAppID(appID string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.appID = &appID
|
||||
}
|
||||
}
|
||||
|
||||
func WithMetricsEnabled() AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
enabled := true
|
||||
config.metricsEnabled = &enabled
|
||||
}
|
||||
}
|
||||
|
||||
func WithMetricsPort(port int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.metricsPort = &port
|
||||
}
|
||||
}
|
||||
|
||||
func WithAppPort(port int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.appPort = &port
|
||||
}
|
||||
}
|
||||
|
||||
func WithConfig(cfg string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.config = &cfg
|
||||
}
|
||||
}
|
||||
|
||||
func WithAppProtocol(protocol string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.appProtocol = &protocol
|
||||
}
|
||||
}
|
||||
|
||||
func WithProfileEnabled() AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
enabled := true
|
||||
config.profileEnabled = &enabled
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogLevel(logLevel string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.logLevel = &logLevel
|
||||
}
|
||||
}
|
||||
|
||||
func WithAPITokenSecret(apiTokenSecret string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.apiTokenSecret = &apiTokenSecret
|
||||
}
|
||||
}
|
||||
|
||||
func WithAppTokenSecret(appTokenSecret string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.appTokenSecret = &appTokenSecret
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogAsJSON() AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
enabled := true
|
||||
config.logAsJSON = &enabled
|
||||
}
|
||||
}
|
||||
|
||||
func WithAppMaxConcurrency(maxConcurrency int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.appMaxConcurrency = &maxConcurrency
|
||||
}
|
||||
}
|
||||
|
||||
func WithDebugEnabled() AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
enabled := true
|
||||
config.debugEnabled = &enabled
|
||||
}
|
||||
}
|
||||
|
||||
func WithDebugPort(debugPort int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.debugPort = &debugPort
|
||||
}
|
||||
}
|
||||
|
||||
func WithEnv(env string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.env = &env
|
||||
}
|
||||
}
|
||||
|
||||
func WithCPULimit(cpuLimit string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.cpuLimit = &cpuLimit
|
||||
}
|
||||
}
|
||||
|
||||
func WithMemoryLimit(memoryLimit string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.memoryLimit = &memoryLimit
|
||||
}
|
||||
}
|
||||
|
||||
func WithCPURequest(cpuRequest string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.cpuRequest = &cpuRequest
|
||||
}
|
||||
}
|
||||
|
||||
func WithMemoryRequest(memoryRequest string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.memoryRequest = &memoryRequest
|
||||
}
|
||||
}
|
||||
|
||||
func WithListenAddresses(listenAddresses string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.listenAddresses = &listenAddresses
|
||||
}
|
||||
}
|
||||
|
||||
func WithLivenessProbeDelay(livenessProbeDelay int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.livenessProbeDelay = &livenessProbeDelay
|
||||
}
|
||||
}
|
||||
|
||||
func WithLivenessProbeTimeout(livenessProbeTimeout int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.livenessProbeTimeout = &livenessProbeTimeout
|
||||
}
|
||||
}
|
||||
|
||||
func WithLivenessProbePeriod(livenessProbePeriod int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.livenessProbePeriod = &livenessProbePeriod
|
||||
}
|
||||
}
|
||||
|
||||
func WithLivenessProbeThreshold(livenessProbeThreshold int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.livenessProbeThreshold = &livenessProbeThreshold
|
||||
}
|
||||
}
|
||||
|
||||
func WithReadinessProbeDelay(readinessProbeDelay int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.readinessProbeDelay = &readinessProbeDelay
|
||||
}
|
||||
}
|
||||
|
||||
func WithReadinessProbeTimeout(readinessProbeTimeout int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.readinessProbeTimeout = &readinessProbeTimeout
|
||||
}
|
||||
}
|
||||
|
||||
func WithReadinessProbePeriod(readinessProbePeriod int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.readinessProbePeriod = &readinessProbePeriod
|
||||
}
|
||||
}
|
||||
|
||||
func WithReadinessProbeThreshold(readinessProbeThreshold int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.readinessProbeThreshold = &readinessProbeThreshold
|
||||
}
|
||||
}
|
||||
|
||||
func WithDaprImage(image string) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.image = &image
|
||||
}
|
||||
}
|
||||
|
||||
func WithAppSSL() AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
enabled := true
|
||||
config.appSSL = &enabled
|
||||
}
|
||||
}
|
||||
|
||||
func WithMaxRequestBodySize(maxRequestBodySize int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.maxRequestBodySize = &maxRequestBodySize
|
||||
}
|
||||
}
|
||||
|
||||
func WithReadBufferSize(readBufferSize int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.readBufferSize = &readBufferSize
|
||||
}
|
||||
}
|
||||
|
||||
func WithHTTPStreamRequestBody() AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
enabled := true
|
||||
config.httpStreamRequestBody = &enabled
|
||||
}
|
||||
}
|
||||
|
||||
func WithGracefulShutdownSeconds(gracefulShutdownSeconds int) AnnoteOption {
|
||||
return func(config *AnnotateOptions) {
|
||||
config.gracefulShutdownSeconds = &gracefulShutdownSeconds
|
||||
}
|
||||
}
|
|
@ -0,0 +1,451 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
annotatorTestDataDir = "testdata/annotator"
|
||||
)
|
||||
|
||||
var (
|
||||
podInDir = path.Join(annotatorTestDataDir, "pod/in")
|
||||
podOutDir = path.Join(annotatorTestDataDir, "pod/out")
|
||||
deploymentInDir = path.Join(annotatorTestDataDir, "deployment/in")
|
||||
deploymentOutDir = path.Join(annotatorTestDataDir, "deployment/out")
|
||||
multiInDir = path.Join(annotatorTestDataDir, "multi/in")
|
||||
multiOutDir = path.Join(annotatorTestDataDir, "multi/out")
|
||||
listInDir = path.Join(annotatorTestDataDir, "list/in")
|
||||
listOutDir = path.Join(annotatorTestDataDir, "list/out")
|
||||
)
|
||||
|
||||
type annotation struct {
|
||||
targetResource string
|
||||
targetNamespace string
|
||||
optionFactory func() AnnotateOptions
|
||||
}
|
||||
|
||||
// nolint
|
||||
func TestAnnotate(t *testing.T) {
|
||||
// Helper function used to order test documents.
|
||||
sortDocs := func(docs []string) {
|
||||
sort.Slice(docs, func(i, j int) bool {
|
||||
if len(docs[i]) == len(docs[j]) {
|
||||
panic("Cannot sort docs with the same length, please ensure tests docs are a unique length.")
|
||||
}
|
||||
return len(docs[i]) < len(docs[j])
|
||||
})
|
||||
}
|
||||
|
||||
configs := []struct {
|
||||
testID string
|
||||
annotations []annotation
|
||||
inputFilePath string
|
||||
expectedFilePath string
|
||||
printOutput bool
|
||||
}{
|
||||
{
|
||||
testID: "single targeted annotation of a pod (config 1)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "mypod",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("test-app"),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(podInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(podOutDir, "config_1.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single targeted annotation of a pod (config 2)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "mypod",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("test-app"),
|
||||
WithProfileEnabled(),
|
||||
WithLogLevel("info"),
|
||||
WithDaprImage("custom-image"),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(podInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(podOutDir, "config_2.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single targeted annotation of a pod without an app id in default namespace (config 3)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "mypod",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions()
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(podInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(podOutDir, "config_3.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single targeted annotation of a pod without an app id in a namespace (config 4)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "mypod",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions()
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(podInDir, "namespace.yml"),
|
||||
expectedFilePath: path.Join(podOutDir, "config_4.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single targeted annotation of a deployment (config 1)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "nodeapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("nodeapp"),
|
||||
WithAppPort(3000),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(deploymentInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(deploymentOutDir, "config_1.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "partial annotation of a deployment (config 2)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "nodeapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("nodeapp"),
|
||||
WithAppPort(3000),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(deploymentInDir, "partial.yml"),
|
||||
expectedFilePath: path.Join(deploymentOutDir, "config_1.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single targeted annotation of multiple resources (config 1)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "divideapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("divideapp"),
|
||||
WithAppPort(4000),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(multiInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(multiOutDir, "config_1.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "multiple targeted annotations of multiple resources (config 2)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "subtractapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("subtractapp"),
|
||||
WithAppPort(80),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
targetResource: "addapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("addapp"),
|
||||
WithAppPort(6000),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
targetResource: "multiplyapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("multiplyapp"),
|
||||
WithAppPort(5000),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
targetResource: "divideapp",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("divideapp"),
|
||||
WithAppPort(4000),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
targetResource: "calculator-front-end",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("calculator-front-end"),
|
||||
WithAppPort(8080),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(multiInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(multiOutDir, "config_2.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single untargeted annotations of multiple resources (config 3)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("subtractapp"),
|
||||
WithAppPort(80),
|
||||
WithConfig("appconfig"),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(multiInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(multiOutDir, "config_3.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single targeted annotations of multiple resources with a namespace (config 4)",
|
||||
annotations: []annotation{
|
||||
{
|
||||
targetResource: "subtractapp",
|
||||
targetNamespace: "test1",
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("subtractapp"),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(multiInDir, "namespace.yml"),
|
||||
expectedFilePath: path.Join(multiOutDir, "config_4.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
{
|
||||
testID: "single untargeted annotations of a list config",
|
||||
annotations: []annotation{
|
||||
{
|
||||
optionFactory: func() AnnotateOptions {
|
||||
return NewAnnotateOptions(
|
||||
WithAppID("nodeapp"),
|
||||
WithAppPort(3000),
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
inputFilePath: path.Join(listInDir, "raw.yml"),
|
||||
expectedFilePath: path.Join(listOutDir, "config_1.yml"),
|
||||
// printOutput: true, // Uncomment to debug.
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range configs {
|
||||
t.Run(tt.testID, func(t *testing.T) {
|
||||
inputFile, err := os.Open(tt.inputFilePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
err = inputFile.Close()
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
// Iterate through all the annotations and pipe them together.
|
||||
var out bytes.Buffer
|
||||
in := []io.Reader{inputFile}
|
||||
for i, annotation := range tt.annotations {
|
||||
annotator := NewK8sAnnotator(K8sAnnotatorConfig{
|
||||
TargetResource: &annotation.targetResource,
|
||||
TargetNamespace: &annotation.targetNamespace,
|
||||
})
|
||||
annotateOptions := annotation.optionFactory()
|
||||
|
||||
out.Reset()
|
||||
err = annotator.Annotate(in, &out, annotateOptions)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// if it isn't the last annotation then set input to this annotation output
|
||||
// to support testing chained resources.
|
||||
if i != len(tt.annotations)-1 {
|
||||
outReader := strings.NewReader(out.String())
|
||||
in = []io.Reader{outReader}
|
||||
}
|
||||
}
|
||||
|
||||
// Split the multi-document string into individual documents for comparison.
|
||||
outString := out.String()
|
||||
outDocs := strings.Split(outString, "---")
|
||||
|
||||
expected, err := ioutil.ReadFile(tt.expectedFilePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expectedString := string(expected)
|
||||
expectedDocs := strings.Split(expectedString, "---")
|
||||
|
||||
// We must sort the documents to ensure we are comparing the correct documents.
|
||||
// The content of the documents should be equivalent but it will not be the same
|
||||
// as the order of keys are not being preserved. Therefore, we sort on the content
|
||||
// length instead. This isn't perfect as additional character may be included but
|
||||
// as long as we have enough spread between the documents we should be ok to use this
|
||||
// to get an order. sortDocs will panic if it tries to compare content that is the
|
||||
// same length as we would lose ordering but invalid orders are still possible.
|
||||
sortDocs(outDocs)
|
||||
sortDocs(expectedDocs)
|
||||
assert.Equal(t, len(expectedDocs), len(outDocs))
|
||||
|
||||
for i := range expectedDocs {
|
||||
if tt.printOutput {
|
||||
t.Logf(outDocs[i])
|
||||
}
|
||||
assert.YAMLEq(t, expectedDocs[i], outDocs[i])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDaprAnnotations(t *testing.T) {
|
||||
t.Run("get dapr annotations", func(t *testing.T) {
|
||||
appID := "test-app"
|
||||
metricsPort := 9090
|
||||
apiTokenSecret := "test-api-token-secret" // #nosec
|
||||
appTokenSecret := "test-app-token-secret" // #nosec
|
||||
appMaxConcurrency := 2
|
||||
appPort := 8080
|
||||
appProtocol := "http"
|
||||
cpuLimit := "0.5"
|
||||
memoryLimit := "512Mi"
|
||||
cpuRequest := "0.1"
|
||||
memoryRequest := "256Mi"
|
||||
config := "appconfig"
|
||||
debugPort := 9091
|
||||
env := "key=value key1=value1"
|
||||
listenAddresses := "0.0.0.0"
|
||||
daprImage := "test-iamge"
|
||||
maxRequestBodySize := 8
|
||||
readBufferSize := 4
|
||||
livenessProbeDelay := 10
|
||||
livenessProbePeriod := 20
|
||||
livenessProbeThreshold := 3
|
||||
livenessProbeTimeout := 30
|
||||
readinessProbeDelay := 40
|
||||
readinessProbePeriod := 50
|
||||
readinessProbeThreshold := 6
|
||||
readinessProbeTimeout := 60
|
||||
logLevel := "debug"
|
||||
gracefulShutdownSeconds := 10
|
||||
|
||||
opts := NewAnnotateOptions(
|
||||
WithAppID(appID),
|
||||
WithMetricsEnabled(),
|
||||
WithMetricsPort(metricsPort),
|
||||
WithAPITokenSecret(apiTokenSecret),
|
||||
WithAppTokenSecret(appTokenSecret),
|
||||
WithAppMaxConcurrency(appMaxConcurrency),
|
||||
WithAppPort(appPort),
|
||||
WithAppProtocol(appProtocol),
|
||||
WithAppSSL(),
|
||||
WithCPULimit(cpuLimit),
|
||||
WithMemoryLimit(memoryLimit),
|
||||
WithCPURequest(cpuRequest),
|
||||
WithMemoryRequest(memoryRequest),
|
||||
WithConfig(config),
|
||||
WithDebugEnabled(),
|
||||
WithDebugPort(debugPort),
|
||||
WithEnv(env),
|
||||
WithLogAsJSON(),
|
||||
WithListenAddresses(listenAddresses),
|
||||
WithDaprImage(daprImage),
|
||||
WithProfileEnabled(),
|
||||
WithMaxRequestBodySize(maxRequestBodySize),
|
||||
WithReadBufferSize(readBufferSize),
|
||||
WithReadinessProbeDelay(readinessProbeDelay),
|
||||
WithReadinessProbePeriod(readinessProbePeriod),
|
||||
WithReadinessProbeThreshold(readinessProbeThreshold),
|
||||
WithReadinessProbeTimeout(readinessProbeTimeout),
|
||||
WithLivenessProbeDelay(livenessProbeDelay),
|
||||
WithLivenessProbePeriod(livenessProbePeriod),
|
||||
WithLivenessProbeThreshold(livenessProbeThreshold),
|
||||
WithLivenessProbeTimeout(livenessProbeTimeout),
|
||||
WithLogLevel(logLevel),
|
||||
WithHTTPStreamRequestBody(),
|
||||
WithGracefulShutdownSeconds(gracefulShutdownSeconds),
|
||||
)
|
||||
|
||||
annotations := getDaprAnnotations(&opts)
|
||||
|
||||
assert.Equal(t, "true", annotations[daprEnabledKey])
|
||||
assert.Equal(t, appID, annotations[daprAppIDKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", appPort), annotations[daprAppPortKey])
|
||||
assert.Equal(t, config, annotations[daprConfigKey])
|
||||
assert.Equal(t, appProtocol, annotations[daprAppProtocolKey])
|
||||
assert.Equal(t, "true", annotations[daprEnableProfilingKey])
|
||||
assert.Equal(t, logLevel, annotations[daprLogLevelKey])
|
||||
assert.Equal(t, apiTokenSecret, annotations[daprAPITokenSecretKey])
|
||||
assert.Equal(t, appTokenSecret, annotations[daprAppTokenSecretKey])
|
||||
assert.Equal(t, "true", annotations[daprLogAsJSONKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", appMaxConcurrency), annotations[daprAppMaxConcurrencyKey])
|
||||
assert.Equal(t, "true", annotations[daprEnableMetricsKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", metricsPort), annotations[daprMetricsPortKey])
|
||||
assert.Equal(t, "true", annotations[daprEnableDebugKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", debugPort), annotations[daprDebugPortKey])
|
||||
assert.Equal(t, env, annotations[daprEnvKey])
|
||||
assert.Equal(t, cpuLimit, annotations[daprCPULimitKey])
|
||||
assert.Equal(t, memoryLimit, annotations[daprMemoryLimitKey])
|
||||
assert.Equal(t, cpuRequest, annotations[daprCPURequestKey])
|
||||
assert.Equal(t, memoryRequest, annotations[daprMemoryRequestKey])
|
||||
assert.Equal(t, listenAddresses, annotations[daprListenAddressesKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", livenessProbeDelay), annotations[daprLivenessProbeDelayKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", livenessProbeTimeout), annotations[daprLivenessProbeTimeoutKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", livenessProbePeriod), annotations[daprLivenessProbePeriodKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", livenessProbeThreshold), annotations[daprLivenessProbeThresholdKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", readinessProbeDelay), annotations[daprReadinessProbeDelayKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", readinessProbeTimeout), annotations[daprReadinessProbeTimeoutKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", readinessProbePeriod), annotations[daprReadinessProbePeriodKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", readinessProbeThreshold), annotations[daprReadinessProbeThresholdKey])
|
||||
assert.Equal(t, daprImage, annotations[daprImageKey])
|
||||
assert.Equal(t, "true", annotations[daprAppSSLKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", maxRequestBodySize), annotations[daprMaxRequestBodySizeKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", readBufferSize), annotations[daprReadBufferSizeKey])
|
||||
assert.Equal(t, "true", annotations[daprHTTPStreamRequestBodyKey])
|
||||
assert.Equal(t, fmt.Sprintf("%d", gracefulShutdownSeconds), annotations[daprGracefulShutdownSecondsKey])
|
||||
})
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodeapp
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: node
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: node
|
||||
annotations:
|
||||
dapr.io/enabled: "false"
|
||||
dapr.io/app-id: "node-app"
|
||||
spec:
|
||||
containers:
|
||||
- name: node
|
||||
image: dapriosamples/hello-k8s-node:latest
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
imagePullPolicy: Always
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodeapp
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: node
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
containers:
|
||||
- name: node
|
||||
image: dapriosamples/hello-k8s-node:latest
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
imagePullPolicy: Always
|
|
@ -0,0 +1,26 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nodeapp
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: node
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: node
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "nodeapp"
|
||||
dapr.io/app-port: "3000"
|
||||
spec:
|
||||
containers:
|
||||
- name: node
|
||||
image: dapriosamples/hello-k8s-node:latest
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
imagePullPolicy: Always
|
|
@ -0,0 +1,46 @@
|
|||
apiVersion: v1
|
||||
items:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
deployment.kubernetes.io/revision: "1"
|
||||
creationTimestamp: "2022-01-14T17:11:56Z"
|
||||
generation: 1
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
progressDeadlineSeconds: 600
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
selector:
|
||||
matchLabels:
|
||||
app: node
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
containers:
|
||||
- image: dapriosamples/hello-k8s-node:latest
|
||||
imagePullPolicy: Always
|
||||
name: node
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
protocol: TCP
|
||||
resources: {}
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
schedulerName: default-scheduler
|
||||
securityContext: {}
|
||||
terminationGracePeriodSeconds: 30
|
||||
kind: List
|
||||
metadata: {}
|
|
@ -0,0 +1,50 @@
|
|||
apiVersion: v1
|
||||
items:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
deployment.kubernetes.io/revision: "1"
|
||||
creationTimestamp: "2022-01-14T17:11:56Z"
|
||||
generation: 1
|
||||
labels:
|
||||
app: node
|
||||
spec:
|
||||
progressDeadlineSeconds: 600
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
selector:
|
||||
matchLabels:
|
||||
app: node
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: node
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "nodeapp"
|
||||
dapr.io/app-port: "3000"
|
||||
spec:
|
||||
containers:
|
||||
- image: dapriosamples/hello-k8s-node:latest
|
||||
imagePullPolicy: Always
|
||||
name: node
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
protocol: TCP
|
||||
resources: {}
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
schedulerName: default-scheduler
|
||||
securityContext: {}
|
||||
terminationGracePeriodSeconds: 30
|
||||
kind: List
|
||||
metadata: {}
|
|
@ -0,0 +1,47 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
namespace: test
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
namespace: test1
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
|
@ -0,0 +1,162 @@
|
|||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
zipkin:
|
||||
endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: addapp
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: add
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
containers:
|
||||
- name: add
|
||||
image: dapriosamples/distributed-calculator-go:latest
|
||||
ports:
|
||||
- containerPort: 6000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: divideapp
|
||||
labels:
|
||||
app: divide
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: divide
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: divide
|
||||
spec:
|
||||
containers:
|
||||
- name: divide
|
||||
image: dapriosamples/distributed-calculator-node:latest
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: multiplyapp
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: multiply
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
containers:
|
||||
- name: multiply
|
||||
image: dapriosamples/distributed-calculator-python:latest
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
selector:
|
||||
app: calculator-front-end
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
type: LoadBalancer
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calculator-front-end
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
containers:
|
||||
- name: calculator-front-end
|
||||
image: dapriosamples/distributed-calculator-react-calculator:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: statestore
|
||||
spec:
|
||||
type: state.redis
|
||||
version: v1
|
||||
metadata:
|
||||
# These settings will work out of the box if you use `helm install
|
||||
# bitnami/redis`. If you have your own setup, replace
|
||||
# `redis-master:6379` with your own Redis master address, and the
|
||||
# Redis password with your own Secret's name. For more information,
|
||||
# see https://docs.dapr.io/operations/components/component-secrets .
|
||||
- name: redisHost
|
||||
value: redis-master:6379
|
||||
- name: redisPassword
|
||||
secretKeyRef:
|
||||
name: redis
|
||||
key: redis-password
|
||||
auth:
|
||||
secretStore: kubernetes
|
|
@ -0,0 +1,166 @@
|
|||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
zipkin:
|
||||
endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: addapp
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: add
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
containers:
|
||||
- name: add
|
||||
image: dapriosamples/distributed-calculator-go:latest
|
||||
ports:
|
||||
- containerPort: 6000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: divideapp
|
||||
labels:
|
||||
app: divide
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: divide
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: divide
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "divideapp"
|
||||
dapr.io/app-port: "4000"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: divide
|
||||
image: dapriosamples/distributed-calculator-node:latest
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: multiplyapp
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: multiply
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
containers:
|
||||
- name: multiply
|
||||
image: dapriosamples/distributed-calculator-python:latest
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
selector:
|
||||
app: calculator-front-end
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
type: LoadBalancer
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calculator-front-end
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
containers:
|
||||
- name: calculator-front-end
|
||||
image: dapriosamples/distributed-calculator-react-calculator:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: statestore
|
||||
spec:
|
||||
type: state.redis
|
||||
version: v1
|
||||
metadata:
|
||||
# These settings will work out of the box if you use `helm install
|
||||
# bitnami/redis`. If you have your own setup, replace
|
||||
# `redis-master:6379` with your own Redis master address, and the
|
||||
# Redis password with your own Secret's name. For more information,
|
||||
# see https://docs.dapr.io/operations/components/component-secrets .
|
||||
- name: redisHost
|
||||
value: redis-master:6379
|
||||
- name: redisPassword
|
||||
secretKeyRef:
|
||||
name: redis
|
||||
key: redis-password
|
||||
auth:
|
||||
secretStore: kubernetes
|
|
@ -0,0 +1,186 @@
|
|||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
zipkin:
|
||||
endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "subtractapp"
|
||||
dapr.io/app-port: "80"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: addapp
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: add
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: add
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "addapp"
|
||||
dapr.io/app-port: "6000"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: add
|
||||
image: dapriosamples/distributed-calculator-go:latest
|
||||
ports:
|
||||
- containerPort: 6000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: divideapp
|
||||
labels:
|
||||
app: divide
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: divide
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: divide
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "divideapp"
|
||||
dapr.io/app-port: "4000"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: divide
|
||||
image: dapriosamples/distributed-calculator-node:latest
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: multiplyapp
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: multiply
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: multiply
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "multiplyapp"
|
||||
dapr.io/app-port: "5000"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: multiply
|
||||
image: dapriosamples/distributed-calculator-python:latest
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
selector:
|
||||
app: calculator-front-end
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
type: LoadBalancer
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calculator-front-end
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "calculator-front-end"
|
||||
dapr.io/app-port: "8080"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: calculator-front-end
|
||||
image: dapriosamples/distributed-calculator-react-calculator:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: statestore
|
||||
spec:
|
||||
type: state.redis
|
||||
version: v1
|
||||
metadata:
|
||||
# These settings will work out of the box if you use `helm install
|
||||
# bitnami/redis`. If you have your own setup, replace
|
||||
# `redis-master:6379` with your own Redis master address, and the
|
||||
# Redis password with your own Secret's name. For more information,
|
||||
# see https://docs.dapr.io/operations/components/component-secrets .
|
||||
- name: redisHost
|
||||
value: redis-master:6379
|
||||
- name: redisPassword
|
||||
secretKeyRef:
|
||||
name: redis
|
||||
key: redis-password
|
||||
auth:
|
||||
secretStore: kubernetes
|
|
@ -0,0 +1,166 @@
|
|||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: appconfig
|
||||
spec:
|
||||
tracing:
|
||||
samplingRate: "1"
|
||||
zipkin:
|
||||
endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "subtractapp"
|
||||
dapr.io/app-port: "80"
|
||||
dapr.io/config: "appconfig"
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: addapp
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: add
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: add
|
||||
spec:
|
||||
containers:
|
||||
- name: add
|
||||
image: dapriosamples/distributed-calculator-go:latest
|
||||
ports:
|
||||
- containerPort: 6000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: divideapp
|
||||
labels:
|
||||
app: divide
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: divide
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: divide
|
||||
spec:
|
||||
containers:
|
||||
- name: divide
|
||||
image: dapriosamples/distributed-calculator-node:latest
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: multiplyapp
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: multiply
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: multiply
|
||||
spec:
|
||||
containers:
|
||||
- name: multiply
|
||||
image: dapriosamples/distributed-calculator-python:latest
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
selector:
|
||||
app: calculator-front-end
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
type: LoadBalancer
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calculator-front-end
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calculator-front-end
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calculator-front-end
|
||||
spec:
|
||||
containers:
|
||||
- name: calculator-front-end
|
||||
image: dapriosamples/distributed-calculator-react-calculator:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: statestore
|
||||
spec:
|
||||
type: state.redis
|
||||
version: v1
|
||||
metadata:
|
||||
# These settings will work out of the box if you use `helm install
|
||||
# bitnami/redis`. If you have your own setup, replace
|
||||
# `redis-master:6379` with your own Redis master address, and the
|
||||
# Redis password with your own Secret's name. For more information,
|
||||
# see https://docs.dapr.io/operations/components/component-secrets .
|
||||
- name: redisHost
|
||||
value: redis-master:6379
|
||||
- name: redisPassword
|
||||
secretKeyRef:
|
||||
name: redis
|
||||
key: redis-password
|
||||
auth:
|
||||
secretStore: kubernetes
|
|
@ -0,0 +1,50 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
namespace: test
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: subtractapp
|
||||
namespace: test1
|
||||
labels:
|
||||
app: subtract
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: subtract
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: subtract
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "subtractapp"
|
||||
spec:
|
||||
containers:
|
||||
- name: subtract
|
||||
image: dapriosamples/distributed-calculator-csharp:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
imagePullPolicy: Always
|
|
@ -0,0 +1,13 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mypod
|
||||
namespace: test
|
||||
labels:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mypod
|
||||
labels:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mypod
|
||||
labels:
|
||||
name: nginx
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "test-app"
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
|
@ -0,0 +1,18 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mypod
|
||||
labels:
|
||||
name: nginx
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "test-app"
|
||||
dapr.io/enable-profiling: "true"
|
||||
dapr.io/log-level: "info"
|
||||
dapr.io/sidecar-image: "custom-image"
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mypod
|
||||
labels:
|
||||
name: nginx
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "default-pod-mypod"
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mypod
|
||||
namespace: test
|
||||
labels:
|
||||
name: nginx
|
||||
annotations:
|
||||
dapr.io/enabled: "true"
|
||||
dapr.io/app-id: "test-pod-mypod"
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
Loading…
Reference in New Issue