mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	Fix merge conflict
This commit is contained in:
		
						commit
						052883aa55
					
				| @ -3,6 +3,7 @@ package cli | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	survey "github.com/AlecAivazis/survey/v2" | ||||||
| 	v1 "github.com/juanfont/headscale/gen/go/headscale/v1" | 	v1 "github.com/juanfont/headscale/gen/go/headscale/v1" | ||||||
| 	"github.com/pterm/pterm" | 	"github.com/pterm/pterm" | ||||||
| 	"github.com/rs/zerolog/log" | 	"github.com/rs/zerolog/log" | ||||||
| @ -77,26 +78,58 @@ var destroyNamespaceCmd = &cobra.Command{ | |||||||
| 
 | 
 | ||||||
| 		namespaceName := args[0] | 		namespaceName := args[0] | ||||||
| 
 | 
 | ||||||
|  | 		request := &v1.GetNamespaceRequest{ | ||||||
|  | 			Name: namespaceName, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		ctx, client, conn, cancel := getHeadscaleCLIClient() | 		ctx, client, conn, cancel := getHeadscaleCLIClient() | ||||||
| 		defer cancel() | 		defer cancel() | ||||||
| 		defer conn.Close() | 		defer conn.Close() | ||||||
| 
 | 
 | ||||||
| 		request := &v1.DeleteNamespaceRequest{Name: namespaceName} | 		_, err := client.GetNamespace(ctx, request) | ||||||
| 
 |  | ||||||
| 		response, err := client.DeleteNamespace(ctx, request) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			ErrorOutput( | 			ErrorOutput( | ||||||
| 				err, | 				err, | ||||||
| 				fmt.Sprintf( | 				fmt.Sprintf("Error: %s", status.Convert(err).Message()), | ||||||
| 					"Cannot destroy namespace: %s", |  | ||||||
| 					status.Convert(err).Message(), |  | ||||||
| 				), |  | ||||||
| 				output, | 				output, | ||||||
| 			) | 			) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		SuccessOutput(response, "Namespace destroyed", output) | 		confirm := false | ||||||
|  | 		force, _ := cmd.Flags().GetBool("force") | ||||||
|  | 		if !force { | ||||||
|  | 			prompt := &survey.Confirm{ | ||||||
|  | 				Message: fmt.Sprintf( | ||||||
|  | 					"Do you want to remove the namespace '%s' and any associated preauthkeys?", | ||||||
|  | 					namespaceName, | ||||||
|  | 				), | ||||||
|  | 			} | ||||||
|  | 			err := survey.AskOne(prompt, &confirm) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if confirm || force { | ||||||
|  | 			request := &v1.DeleteNamespaceRequest{Name: namespaceName} | ||||||
|  | 
 | ||||||
|  | 			response, err := client.DeleteNamespace(ctx, request) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ErrorOutput( | ||||||
|  | 					err, | ||||||
|  | 					fmt.Sprintf( | ||||||
|  | 						"Cannot destroy namespace: %s", | ||||||
|  | 						status.Convert(err).Message(), | ||||||
|  | 					), | ||||||
|  | 					output, | ||||||
|  | 				) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			SuccessOutput(response, "Namespace destroyed", output) | ||||||
|  | 		} else { | ||||||
|  | 			SuccessOutput(map[string]string{"Result": "Namespace not destroyed"}, "Namespace not destroyed", output) | ||||||
|  | 		} | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -15,9 +15,9 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	errorNamespaceExists   = Error("Namespace already exists") | 	errorNamespaceExists          = Error("Namespace already exists") | ||||||
| 	errorNamespaceNotFound = Error("Namespace not found") | 	errorNamespaceNotFound        = Error("Namespace not found") | ||||||
| 	errorNamespaceNotEmpty = Error("Namespace not empty") | 	errorNamespaceNotEmptyOfNodes = Error("Namespace not empty: node(s) found") | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Namespace is the way Headscale implements the concept of users in Tailscale
 | // Namespace is the way Headscale implements the concept of users in Tailscale
 | ||||||
| @ -60,7 +60,18 @@ func (h *Headscale) DestroyNamespace(name string) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if len(m) > 0 { | 	if len(m) > 0 { | ||||||
| 		return errorNamespaceNotEmpty | 		return errorNamespaceNotEmptyOfNodes | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	keys, err := h.ListPreAuthKeys(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	for _, p := range keys { | ||||||
|  | 		err = h.DestroyPreAuthKey(&p) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if result := h.db.Unscoped().Delete(&n); result.Error != nil { | 	if result := h.db.Unscoped().Delete(&n); result.Error != nil { | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package headscale | |||||||
| import ( | import ( | ||||||
| 	"github.com/rs/zerolog/log" | 	"github.com/rs/zerolog/log" | ||||||
| 	"gopkg.in/check.v1" | 	"gopkg.in/check.v1" | ||||||
|  | 	"gorm.io/gorm" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (s *Suite) TestCreateAndDestroyNamespace(c *check.C) { | func (s *Suite) TestCreateAndDestroyNamespace(c *check.C) { | ||||||
| @ -31,6 +32,19 @@ func (s *Suite) TestDestroyNamespaceErrors(c *check.C) { | |||||||
| 	pak, err := h.CreatePreAuthKey(n.Name, false, false, nil) | 	pak, err := h.CreatePreAuthKey(n.Name, false, false, nil) | ||||||
| 	c.Assert(err, check.IsNil) | 	c.Assert(err, check.IsNil) | ||||||
| 
 | 
 | ||||||
|  | 	err = h.DestroyNamespace("test") | ||||||
|  | 	c.Assert(err, check.IsNil) | ||||||
|  | 
 | ||||||
|  | 	result := h.db.Preload("Namespace").First(&pak, "key = ?", pak.Key) | ||||||
|  | 	// destroying a namespace also deletes all associated preauthkeys
 | ||||||
|  | 	c.Assert(result.Error, check.Equals, gorm.ErrRecordNotFound) | ||||||
|  | 
 | ||||||
|  | 	n, err = h.CreateNamespace("test") | ||||||
|  | 	c.Assert(err, check.IsNil) | ||||||
|  | 
 | ||||||
|  | 	pak, err = h.CreatePreAuthKey(n.Name, false, false, nil) | ||||||
|  | 	c.Assert(err, check.IsNil) | ||||||
|  | 
 | ||||||
| 	m := Machine{ | 	m := Machine{ | ||||||
| 		ID:             0, | 		ID:             0, | ||||||
| 		MachineKey:     "foo", | 		MachineKey:     "foo", | ||||||
| @ -45,7 +59,7 @@ func (s *Suite) TestDestroyNamespaceErrors(c *check.C) { | |||||||
| 	h.db.Save(&m) | 	h.db.Save(&m) | ||||||
| 
 | 
 | ||||||
| 	err = h.DestroyNamespace("test") | 	err = h.DestroyNamespace("test") | ||||||
| 	c.Assert(err, check.Equals, errorNamespaceNotEmpty) | 	c.Assert(err, check.Equals, errorNamespaceNotEmptyOfNodes) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *Suite) TestRenameNamespace(c *check.C) { | func (s *Suite) TestRenameNamespace(c *check.C) { | ||||||
|  | |||||||
| @ -92,7 +92,17 @@ func (h *Headscale) GetPreAuthKey(namespace string, key string) (*PreAuthKey, er | |||||||
| 	return pak, nil | 	return pak, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // MarkExpirePreAuthKey marks a PreAuthKey as expired.
 | // DestroyPreAuthKey destroys a preauthkey. Returns error if the PreAuthKey
 | ||||||
|  | // does not exist.
 | ||||||
|  | func (h *Headscale) DestroyPreAuthKey(pak *PreAuthKey) error { | ||||||
|  | 	if result := h.db.Unscoped().Delete(&pak); result.Error != nil { | ||||||
|  | 		return result.Error | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MarkExpirePreAuthKey marks a PreAuthKey as expired
 | ||||||
| func (h *Headscale) ExpirePreAuthKey(k *PreAuthKey) error { | func (h *Headscale) ExpirePreAuthKey(k *PreAuthKey) error { | ||||||
| 	if err := h.db.Model(&k).Update("Expiration", time.Now()).Error; err != nil { | 	if err := h.db.Model(&k).Update("Expiration", time.Now()).Error; err != nil { | ||||||
| 		return err | 		return err | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user