1// Copyright (c) 2015-2021 MinIO, Inc.
2//
3// This file is part of MinIO Object Storage stack
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18package cmd
19
20import (
21	"context"
22	"fmt"
23
24	"github.com/fatih/color"
25	"github.com/minio/cli"
26	json "github.com/minio/colorjson"
27	"github.com/minio/mc/pkg/probe"
28	"github.com/minio/pkg/console"
29)
30
31var (
32	eventListFlags = []cli.Flag{}
33)
34
35var eventListCmd = cli.Command{
36	Name:         "list",
37	Usage:        "list bucket notifications",
38	Action:       mainEventList,
39	OnUsageError: onUsageError,
40	Before:       setGlobalsFromContext,
41	Flags:        append(eventListFlags, globalFlags...),
42	CustomHelpTemplate: `NAME:
43  {{.HelpName}} - {{.Usage}}
44
45USAGE:
46  {{.HelpName}} TARGET ARN [FLAGS]
47
48FLAGS:
49  {{range .VisibleFlags}}{{.}}
50  {{end}}
51EXAMPLES:
52  1. List notification configurations associated to a specific arn
53    {{.Prompt}} {{.HelpName}} myminio/mybucket arn:aws:sqs:us-west-2:444455556666:your-queue
54
55  2. List all notification configurations
56    {{.Prompt}} {{.HelpName}} s3/mybucket
57`,
58}
59
60// checkEventListSyntax - validate all the passed arguments
61func checkEventListSyntax(ctx *cli.Context) {
62	if len(ctx.Args()) != 2 && len(ctx.Args()) != 1 {
63		cli.ShowCommandHelpAndExit(ctx, "list", 1) // last argument is exit code
64	}
65}
66
67// eventListMessage container
68type eventListMessage struct {
69	Status string   `json:"status"`
70	ID     string   `json:"id"`
71	Event  []string `json:"event"`
72	Prefix string   `json:"prefix"`
73	Suffix string   `json:"suffix"`
74	Arn    string   `json:"arn"`
75}
76
77func (u eventListMessage) JSON() string {
78	u.Status = "success"
79	eventListMessageJSONBytes, e := json.MarshalIndent(u, "", " ")
80	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
81	return string(eventListMessageJSONBytes)
82}
83
84func (u eventListMessage) String() string {
85	msg := console.Colorize("ARN", fmt.Sprintf("%s   ", u.Arn))
86	for i, event := range u.Event {
87		msg += console.Colorize("Event", event)
88		if i != len(u.Event)-1 {
89			msg += ","
90		}
91	}
92	msg += console.Colorize("Filter", "   Filter: ")
93	if u.Prefix != "" {
94		msg += console.Colorize("Filter", fmt.Sprintf("prefix=\"%s\"", u.Prefix))
95	}
96	if u.Suffix != "" {
97		msg += console.Colorize("Filter", fmt.Sprintf("suffix=\"%s\"", u.Suffix))
98	}
99	return msg
100}
101
102func mainEventList(cliCtx *cli.Context) error {
103	ctx, cancelEventList := context.WithCancel(globalContext)
104	defer cancelEventList()
105
106	console.SetColor("ARN", color.New(color.FgGreen, color.Bold))
107	console.SetColor("Event", color.New(color.FgCyan, color.Bold))
108	console.SetColor("Filter", color.New(color.Bold))
109
110	checkEventListSyntax(cliCtx)
111
112	args := cliCtx.Args()
113	path := args[0]
114	arn := ""
115	if len(args) > 1 {
116		arn = args[1]
117	}
118
119	client, err := newClient(path)
120	if err != nil {
121		fatalIf(err.Trace(), "Unable to parse the provided url.")
122	}
123
124	s3Client, ok := client.(*S3Client)
125	if !ok {
126		fatalIf(errDummy().Trace(), "The provided url doesn't point to a S3 server.")
127	}
128
129	configs, err := s3Client.ListNotificationConfigs(ctx, arn)
130	fatalIf(err, "Unable to list notifications on the specified bucket.")
131
132	for _, config := range configs {
133		printMsg(eventListMessage{
134			Event:  config.Events,
135			Prefix: config.Prefix,
136			Suffix: config.Suffix,
137			Arn:    config.Arn,
138			ID:     config.ID})
139	}
140
141	return nil
142}
143