diff --git a/cmd/subscriptions.go b/cmd/subscriptions.go new file mode 100644 index 000000000..b2b54e86c --- /dev/null +++ b/cmd/subscriptions.go @@ -0,0 +1,63 @@ +package cmd + +import ( + "github.com/dapr/cli/pkg/print" + "github.com/dapr/cli/pkg/standalone" + "github.com/spf13/cobra" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "os" +) + +/* +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. +*/ + +var ( + subscriptionsAppId string +) + +var SubscriptionsCmd = &cobra.Command{ + Use: "subscriptions", + Short: "List all Dapr subscriptions. Supported platforms: Supported platforms: Kubernetes and self-hosted", + PreRun: func(cmd *cobra.Command, args []string) { + if outputFormat != "" && outputFormat != "json" && outputFormat != "yaml" && outputFormat != "table" { + print.FailureStatusEvent(os.Stdout, "An invalid output format was specified.") + os.Exit(1) + } + }, + Run: func(cmd *cobra.Command, args []string) { + if kubernetesMode { + if allNamespaces { + resourceNamespace = meta_v1.NamespaceAll + } else if resourceNamespace == "" { + resourceNamespace = meta_v1.NamespaceAll + } + } else { + list, err := standalone.Subscriptions(subscriptionsAppId) + if err != nil { + return + } + outputList(list, len(list)) + } + }, + Example: ` +# List Dapr subscriptions for a given app +dapr components --app-id myapp +`, +} + +func init() { + SubscriptionsCmd.Flags().StringVarP(&subscriptionsAppId, "app-id", "a", "", "The application id to be stopped") + SubscriptionsCmd.MarkFlagRequired("app-id") + SubscriptionsCmd.Flags().StringVarP(&outputFormat, "output", "o", "", "The output format of the list. Valid values are: json, yaml, or table (default)") + RootCmd.AddCommand(SubscriptionsCmd) +} diff --git a/pkg/api/api.go b/pkg/api/api.go index c63e4e549..0820fe3c4 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -22,6 +22,7 @@ var ( type Metadata struct { ID string `json:"id"` ActiveActorsCount []MetadataActiveActorsCount `json:"actors"` + Subscriptions []Subscription `json:"subscriptions"` Extended map[string]string `json:"extended"` } @@ -30,3 +31,14 @@ type MetadataActiveActorsCount struct { Type string `json:"type"` Count int `json:"count"` } + +type Subscription struct { + PubSubName string `json:"pubsubname"` + Topic string `json:"topic"` + Rules []Rule `json:"rules"` + DeadLetterTopic string `json:"deadLetterTopic"` +} + +type Rule struct { + Path string `json:"path"` +} diff --git a/pkg/standalone/subscriptions.go b/pkg/standalone/subscriptions.go new file mode 100644 index 000000000..ebd2d62b0 --- /dev/null +++ b/pkg/standalone/subscriptions.go @@ -0,0 +1,55 @@ +package standalone + +import ( + "errors" + "github.com/dapr/cli/pkg/metadata" +) + +// ListOutput represents the application ID, application port and creation time. +type SubscriptionsOutput struct { + AppID string `csv:"APP ID" json:"appId" yaml:"appId"` + Topic string `csv:"TOPIC" json:"topic" yaml:"topic"` + PubSubName string `csv:"PUBSUBNAME" json:"pubsubname" yaml:"pubsubname"` + Paths []string `csv:"PATHS" json:"paths" yaml:"paths"` +} + +// Stop terminates the application process. +func Subscriptions(appID string) ([]SubscriptionsOutput, error) { + l, err := List() + if err != nil { + return nil, err + } + + if len(l) == 0 { + return nil, errors.New("no running Dapr sidecars found") + } + + instance, err := getDaprInstance(l, appID) + if err != nil { + return nil, err + } + + m, err := metadata.Get(instance.HTTPPort, instance.AppID, "") + + if err != nil { + return nil, err + } + + var output []SubscriptionsOutput + + for _, sub := range m.Subscriptions { + o := SubscriptionsOutput{ + AppID: appID, + Topic: sub.Topic, + PubSubName: sub.PubSubName, + } + + for _, r := range sub.Rules { + o.Paths = append(o.Paths, r.Path) + } + + output = append(output, o) + } + + return output, nil +}