16298: "arvados-server killcollection" command.
[arvados.git] / lib / killcollection / killcollection.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package killcollection
6
7 import (
8         "flag"
9         "fmt"
10         "io"
11         "os"
12
13         "git.arvados.org/arvados.git/lib/config"
14         "git.arvados.org/arvados.git/sdk/go/arvados"
15         "git.arvados.org/arvados.git/sdk/go/arvadosclient"
16         "git.arvados.org/arvados.git/sdk/go/ctxlog"
17         "git.arvados.org/arvados.git/sdk/go/keepclient"
18         "github.com/sirupsen/logrus"
19 )
20
21 var Command command
22
23 type command struct{}
24
25 func (command) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
26         var err error
27         logger := ctxlog.New(stderr, "text", "info")
28         defer func() {
29                 if err != nil {
30                         logger.WithError(err).Error("fatal")
31                 }
32                 logger.Info("exiting")
33         }()
34
35         loader := config.NewLoader(stdin, logger)
36
37         flags := flag.NewFlagSet("", flag.ContinueOnError)
38         flags.SetOutput(stderr)
39         loader.SetupFlags(flags)
40         projectName := flags.String("project-name", "placeholder collections with lost data", "name of project to move collections into")
41         placeholderFilename := flags.String("placeholder-filename", ".contents_removed", "name of empty file in replacement collection")
42         loglevel := flags.String("log-level", "info", "logging level (debug, info, ...)")
43         err = flags.Parse(args)
44         if err == flag.ErrHelp {
45                 err = nil
46                 return 0
47         } else if err != nil {
48                 return 2
49         }
50
51         if len(flags.Args()) == 0 {
52                 fmt.Fprintf(stderr, "Usage: %s [options] uuid ...\n", prog)
53                 flags.PrintDefaults()
54                 return 2
55         }
56
57         lvl, err := logrus.ParseLevel(*loglevel)
58         if err != nil {
59                 return 2
60         }
61         logger.SetLevel(lvl)
62
63         cfg, err := loader.Load()
64         if err != nil {
65                 return 1
66         }
67         cluster, err := cfg.GetCluster("")
68         if err != nil {
69                 return 1
70         }
71         client, err := arvados.NewClientFromConfig(cluster)
72         if err != nil {
73                 return 1
74         }
75         client.AuthToken = cluster.SystemRootToken
76
77         arv, err := arvadosclient.New(client)
78         if err != nil {
79                 return 1
80         }
81         kc, err := keepclient.MakeKeepClient(arv)
82         if err != nil {
83                 return 1
84         }
85         fs, err := (&arvados.Collection{}).FileSystem(client, kc)
86         if err != nil {
87                 return 1
88         }
89         f, err := fs.OpenFile(*placeholderFilename, os.O_CREATE|os.O_WRONLY, 0777)
90         if err != nil {
91                 return 1
92         }
93         err = f.Close()
94         if err != nil {
95                 return 1
96         }
97         manifest, err := fs.MarshalManifest(".")
98         if err != nil {
99                 return 1
100         }
101         logger.WithField("manifest_text", manifest).Debug("replacement manifest")
102
103         var systemUser arvados.User
104         err = client.RequestAndDecode(&systemUser, "GET", "arvados/v1/users/current", nil, nil)
105         if err != nil {
106                 return 1
107         }
108         logger.Printf("system user uuid is %s", systemUser.UUID)
109         var projectList arvados.GroupList
110         err = client.RequestAndDecode(&projectList, "GET", "arvados/v1/groups", nil, arvados.ListOptions{
111                 Limit: 1,
112                 Filters: []arvados.Filter{
113                         {"name", "=", *projectName},
114                         {"owner_uuid", "=", systemUser.UUID},
115                 },
116         })
117         if err != nil {
118                 return 1
119         }
120         var project arvados.Group
121         if len(projectList.Items) > 0 {
122                 project = projectList.Items[0]
123                 logger.WithField("UUID", project.UUID).Info("using existing project")
124         } else {
125                 logger.Info("creating new project")
126                 err = client.RequestAndDecode(&project, "POST", "arvados/v1/groups", nil, map[string]interface{}{
127                         "group": map[string]interface{}{
128                                 "name":        *projectName,
129                                 "owner_uuid":  systemUser.UUID,
130                                 "group_class": "project",
131                         },
132                 })
133                 if err != nil {
134                         return 1
135                 }
136                 logger.WithField("UUID", project.UUID).Info("created new project")
137         }
138
139         for _, uuid := range flags.Args() {
140                 logger := logger.WithField("UUID", uuid)
141                 var coll arvados.Collection
142                 err := client.RequestAndDecode(&coll, "PATCH", "arvados/v1/collections/"+uuid, nil, map[string]interface{}{
143                         "collection": map[string]interface{}{
144                                 "owner_uuid":    project.UUID,
145                                 "manifest_text": manifest,
146                                 "name":          "placeholder for collection " + uuid,
147                         },
148                 })
149                 if err != nil {
150                         logger.WithError(err).Error("error updating collection")
151                         return 1
152                 }
153                 logger.Info("done")
154         }
155         return 0
156 }