Add abra app remove command #43
@ -3,8 +3,8 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/client"
|
"coopcloud.tech/abra/client"
|
||||||
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,11 +26,20 @@ var VolumesFlag = &cli.BoolFlag{
|
|||||||
Destination: &Volumes,
|
Destination: &Volumes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Force bool
|
||||||
|
|
||||||
|
var ForceFlag = &cli.BoolFlag{
|
||||||
knoflook marked this conversation as resolved
Outdated
|
|||||||
|
Name: "force",
|
||||||
|
Value: false,
|
||||||
|
Destination: &Force,
|
||||||
|
}
|
||||||
|
|
||||||
var appRemoveCommand = &cli.Command{
|
var appRemoveCommand = &cli.Command{
|
||||||
Name: "remove",
|
Name: "remove",
|
||||||
Aliases: []string{"rm", "delete"},
|
Aliases: []string{"rm", "delete"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
VolumesFlag,
|
VolumesFlag,
|
||||||
|
ForceFlag,
|
||||||
},
|
},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
// Check if app name was provided by user
|
// Check if app name was provided by user
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
We haven't discussed this but the existing convention that I see is that we don't add comments to code to explain what it is doing unless it is doing something strange or difficult. Otherwise, we comment to explain why we're doing something (context, not what it is doing). The issue is, that when the code changes, you might forget to change the comment and then the next person might be caught reading the comment which describes code that doesn'te exist anymore. I would say have a look around the rest of the codebase at comment usage and perhaps remove the obvious ones in this function. For example the We haven't discussed this but the existing convention that I see is that we don't add comments to code to explain what it is doing unless it is doing something strange or difficult. Otherwise, we comment to explain why we're doing something (context, not what it is doing).
The issue is, that when the code changes, you might forget to change the comment and then the next person might be caught reading the comment which describes code that doesn'te exist anymore. I would say have a look around the rest of the codebase at comment usage and perhaps remove the obvious ones in this function.
For example the `// we have to map the names to ID's` comment is a good one, I'd keep that.
|
|||||||
@ -38,15 +48,17 @@ var appRemoveCommand = &cli.Command{
|
|||||||
internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!"))
|
internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!"))
|
||||||
}
|
}
|
||||||
// Make sure that the user really wants to delete the app
|
// Make sure that the user really wants to delete the app
|
||||||
response := false
|
if !Force {
|
||||||
prompt := &survey.Confirm{
|
response := false
|
||||||
Message: "About to delete " + AppName + ", are you sure?",
|
prompt := &survey.Confirm{
|
||||||
|
Message: "About to delete " + AppName + ", are you sure?",
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
`Message: fmt.Sprintf("About to delete %s, are you sure?", appName)`
|
|||||||
|
}
|
||||||
|
survey.AskOne(prompt, &response)
|
||||||
|
if response == false {
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
```golang
if !response {
logrus.Fatal(errors.New("User aborted app removal"))
}
```
|
|||||||
|
return errors.New("User aborted app removal")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
survey.AskOne(prompt, &response)
|
// Get app list
|
||||||
if response == false {
|
|
||||||
return errors.New("User aborted app removal")
|
|
||||||
}
|
|
||||||
// Remove the file
|
|
||||||
AppFiles, err := config.LoadAppFiles("")
|
AppFiles, err := config.LoadAppFiles("")
|
||||||
decentral1se marked this conversation as resolved
Outdated
decentral1se
commented
`appFiles, err := config.LoadAppFiles()`
knoflook
commented
Can't do it that way, if you remove "" LoadAppFiles returns an empty map[] Can't do it that way, if you remove "" LoadAppFiles returns an empty map[]
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
`logrus.Fatal(err)`
|
|||||||
@ -59,68 +71,88 @@ var appRemoveCommand = &cli.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Remove the file
|
||||||
err = os.Remove(AppPath)
|
err = os.Remove(AppPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
knoflook marked this conversation as resolved
decentral1se
commented
```golang
if err != nil {
logrus.Fatal(err)
}
logrus.Info(fmt.Sprintf("File: %s removed", appPath))
```
|
|||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
logrus.Info("File :" + AppPath + " removed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the app has secrets and remove them too
|
// Check if the app has secrets
|
||||||
fs := filters.NewArgs()
|
fs := filters.NewArgs()
|
||||||
fs.Add("name", AppName)
|
fs.Add("name", AppName)
|
||||||
SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs})
|
SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
`logrus.Fatal(err)`
|
|||||||
}
|
}
|
||||||
// TODO: Actually remove secrets
|
|
||||||
Secrets := make(map[string]string)
|
Secrets := make(map[string]string)
|
||||||
SecretNames := []string{}
|
SecretNames := []string{}
|
||||||
for _, cont := range SecretList {
|
for _, cont := range SecretList {
|
||||||
Secrets[cont.Spec.Annotations.Name] = cont.ID //we have to map the names to ID's
|
Secrets[cont.Spec.Annotations.Name] = cont.ID //we have to map the names to ID's
|
||||||
SecretNames = append(SecretNames, cont.Spec.Annotations.Name)
|
SecretNames = append(SecretNames, cont.Spec.Annotations.Name)
|
||||||
//cl.SecretRemove(ctx, cont.ID)
|
|
||||||
}
|
}
|
||||||
SecretNamesToRemove := []string{}
|
SecretNamesToRemove := []string{}
|
||||||
SecretsPrompt := &survey.MultiSelect{
|
|
||||||
Message: "Which secrets do you want to remove?",
|
// Ask if the user really wants to remove the apps
|
||||||
Options: SecretNames,
|
if Force {
|
||||||
Default: SecretNames,
|
SecretNamesToRemove = SecretNames
|
||||||
|
} else {
|
||||||
|
SecretsPrompt := &survey.MultiSelect{
|
||||||
|
Message: "Which secrets do you want to remove?",
|
||||||
|
Options: SecretNames,
|
||||||
|
Default: SecretNames,
|
||||||
|
}
|
||||||
|
survey.AskOne(SecretsPrompt, &SecretNamesToRemove)
|
||||||
}
|
}
|
||||||
survey.AskOne(SecretsPrompt, &SecretNamesToRemove)
|
|
||||||
|
// Actually remove the secrets
|
||||||
for _, name := range SecretNamesToRemove {
|
for _, name := range SecretNamesToRemove {
|
||||||
|
// DEBUG: SecretIDsToRemove = append(SecretIDsToRemove, Secrets[name])
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
Let's remove that 🙃 Let's remove that 🙃
|
|||||||
err := cl.SecretRemove(ctx, Secrets[name])
|
err := cl.SecretRemove(ctx, Secrets[name])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
```golang
if err != nil {
logrus.Fatal(err)
}
logrus.Info(fmt.Sprintf("Secret: %s removed", name))
```
|
|||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
logrus.Info("Secret: " + name + " removed")
|
||||||
}
|
}
|
||||||
// SecretIDsToRemove = append(SecretIDsToRemove, Secrets[name])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get volumes associated with the app
|
||||||
|
VolumeListOKBody, err := cl.VolumeList(ctx, fs)
|
||||||
|
VolumeList := VolumeListOKBody.Volumes
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
knoflook marked this conversation as resolved
decentral1se
commented
`logrus.Fatal(err)`
|
|||||||
|
}
|
||||||
|
Vols := []string{}
|
||||||
|
for _, vol := range VolumeList {
|
||||||
|
Vols = append(Vols, vol.Name)
|
||||||
|
}
|
||||||
// Remove the volumes if desired
|
// Remove the volumes if desired
|
||||||
if Volumes == true {
|
if Volumes == true {
|
||||||
knoflook marked this conversation as resolved
Outdated
decentral1se
commented
`if Volumes {`
|
|||||||
VolumeListOKBody, err := cl.VolumeList(ctx, fs)
|
|
||||||
VolumeList := VolumeListOKBody.Volumes
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Vols := []string{}
|
|
||||||
for _, vol := range VolumeList {
|
|
||||||
Vols = append(Vols, vol.Name)
|
|
||||||
}
|
|
||||||
RemoveVols := []string{}
|
RemoveVols := []string{}
|
||||||
VolumesPrompt := &survey.MultiSelect{
|
// If there's no --force, ask if the user wants to remove
|
||||||
Message: "Which volumes do you want to remove?",
|
if Force {
|
||||||
Options: Vols,
|
RemoveVols = Vols
|
||||||
Default: Vols,
|
} else {
|
||||||
|
VolumesPrompt := &survey.MultiSelect{
|
||||||
|
Message: "Which volumes do you want to remove?",
|
||||||
|
Options: Vols,
|
||||||
|
Default: Vols,
|
||||||
|
}
|
||||||
|
survey.AskOne(VolumesPrompt, &RemoveVols)
|
||||||
}
|
}
|
||||||
survey.AskOne(VolumesPrompt, &RemoveVols)
|
// Remove the volumes
|
||||||
fmt.Println("Volumes to remove: ", RemoveVols) //TODO: Replace with a remove method
|
|
||||||
for _, vol := range RemoveVols {
|
for _, vol := range RemoveVols {
|
||||||
err := cl.VolumeRemove(ctx, vol, false) // false is for force removing
|
err := cl.VolumeRemove(ctx, vol, Force) // false is for force removing
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
logrus.Info("Volume " + vol + " removed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Volumes will not be removed")
|
logrus.Info("No volumes were removed. Volumes left: " + strings.Join(Vols, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
This is a general flag we'll add to other sub-commands, it can live in cli/internal/common.go?