Installer: Handle VM uninstall before it has had a time to boot

Change-Id: I615bc949b5054b301899b1e0b7eae94a98126e61
diff --git a/core/headscale/client.go b/core/headscale/client.go
index 159fffb..f4d0f51 100644
--- a/core/headscale/client.go
+++ b/core/headscale/client.go
@@ -111,7 +111,7 @@
 			return strconv.Itoa(n.Id), nil
 		}
 	}
-	return "", fmt.Errorf("not found")
+	return "", ErrorNotFound
 }
 
 func (c *client) getNodeAddresses(user, node string) ([]net.IP, error) {
diff --git a/core/headscale/main.go b/core/headscale/main.go
index 194da06..c2cfcf5 100644
--- a/core/headscale/main.go
+++ b/core/headscale/main.go
@@ -167,7 +167,11 @@
 		return
 	}
 	if err := s.client.expirePreAuthKey(user, req.AuthKey); err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		if errors.Is(err, ErrorNotFound) {
+			http.Error(w, err.Error(), http.StatusNotFound)
+		} else {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
 		return
 	}
 }
@@ -185,8 +189,11 @@
 		return
 	}
 	if err := s.client.expireUserNode(user, node); err != nil {
-		fmt.Println(err)
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		if errors.Is(err, ErrorNotFound) {
+			http.Error(w, err.Error(), http.StatusNotFound)
+		} else {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
 		return
 	}
 }
@@ -203,7 +210,11 @@
 		return
 	}
 	if err := s.client.removeUserNode(user, node); err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		if errors.Is(err, ErrorNotFound) {
+			http.Error(w, err.Error(), http.StatusNotFound)
+		} else {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
 		return
 	}
 }
diff --git a/core/installer/app_manager.go b/core/installer/app_manager.go
index 8bb072e..fbee783 100644
--- a/core/installer/app_manager.go
+++ b/core/installer/app_manager.go
@@ -83,7 +83,7 @@
 
 func (m *AppManager) GetAllInstances() ([]AppInstanceConfig, error) {
 	m.repo.Pull()
-	kust, err := soft.ReadKustomization(m.repo, filepath.Join(m.appDirRoot, "kustomization.yaml"))
+	kust, err := soft.ReadKustomization(m.repo, filepath.Join(m.appDirRoot, kustomizationFileName))
 	if err != nil {
 		if errors.Is(err, fs.ErrNotExist) {
 			return nil, nil
@@ -103,7 +103,7 @@
 }
 
 func (m *AppManager) GetAllAppInstances(name string) ([]AppInstanceConfig, error) {
-	kust, err := soft.ReadKustomization(m.repo, filepath.Join(m.appDirRoot, "kustomization.yaml"))
+	kust, err := soft.ReadKustomization(m.repo, filepath.Join(m.appDirRoot, kustomizationFileName))
 	if err != nil {
 		if errors.Is(err, fs.ErrNotExist) {
 			return nil, nil
@@ -269,7 +269,7 @@
 func createKustomizationChain(r soft.RepoFS, path string) error {
 	for p := filepath.Clean(path); p != "/"; {
 		parent, child := filepath.Split(p)
-		kustPath := filepath.Join(parent, "kustomization.yaml")
+		kustPath := filepath.Join(parent, kustomizationFileName)
 		kust, err := soft.ReadKustomization(r, kustPath)
 		if err != nil {
 			if errors.Is(err, fs.ErrNotExist) {
@@ -350,7 +350,7 @@
 				return err
 			}
 			for name, contents := range data {
-				if name == "config.json" || name == "kustomization.yaml" || name == "resources" {
+				if name == "config.json" || name == kustomizationFileName || name == "resources" {
 					return fmt.Errorf("%s is forbidden", name)
 				}
 				w, err := r.Writer(path.Join(appDir, name))
@@ -382,7 +382,7 @@
 					return err
 				}
 			}
-			if err := soft.WriteYaml(r, path.Join(resourcesDir, "kustomization.yaml"), appKust); err != nil {
+			if err := soft.WriteYaml(r, path.Join(resourcesDir, kustomizationFileName), appKust); err != nil {
 				return err
 			}
 			return nil
@@ -699,7 +699,7 @@
 				break
 			}
 			n := filepath.Base(curr)
-			kustPath := filepath.Join(p, "kustomization.yaml")
+			kustPath := filepath.Join(p, kustomizationFileName)
 			kust, err := soft.ReadKustomization(r, kustPath)
 			if err != nil {
 				return "", err
@@ -729,13 +729,14 @@
 	}
 	for vmName, vmCfg := range cfg.Out.VM {
 		if vmCfg.VPN.Enabled {
-			if err := m.vpnAPIClient.ExpireNode(vmCfg.Username, vmName); err != nil {
+			// Not found error is ignored as VM might have not had enough time to boot before uninstalling it.
+			if err := m.vpnAPIClient.ExpireNode(vmCfg.Username, vmName); err != nil && !errors.Is(err, ErrorNotFound) {
 				return err
 			}
 			if err := m.vpnAPIClient.ExpireKey(vmCfg.Username, vmCfg.VPN.AuthKey); err != nil {
 				return err
 			}
-			if err := m.vpnAPIClient.RemoveNode(vmCfg.Username, vmName); err != nil {
+			if err := m.vpnAPIClient.RemoveNode(vmCfg.Username, vmName); err != nil && !errors.Is(err, ErrorNotFound) {
 				return err
 			}
 		}
@@ -934,7 +935,7 @@
 }
 
 func (m *InfraAppManager) FindInstance(id string) (InfraAppInstanceConfig, error) {
-	kust, err := soft.ReadKustomization(m.repoIO, filepath.Join("/infrastructure", "kustomization.yaml"))
+	kust, err := soft.ReadKustomization(m.repoIO, filepath.Join("/infrastructure", kustomizationFileName))
 	if err != nil {
 		return InfraAppInstanceConfig{}, err
 	}
diff --git a/core/installer/soft/repoio.go b/core/installer/soft/repoio.go
index de2f75a..0d5f67f 100644
--- a/core/installer/soft/repoio.go
+++ b/core/installer/soft/repoio.go
@@ -209,7 +209,6 @@
 	if len(st) == 0 {
 		return "", nil // TODO(gio): maybe return ErrorNothingToCommit
 	}
-	fmt.Printf("@@@ %+v\n", st)
 	hash, err := wt.Commit(message, &git.CommitOptions{
 		Author: &object.Signature{
 			Name: "pcloud-installer",
@@ -229,7 +228,6 @@
 	if o.Force {
 		gopts.Force = true
 	}
-	fmt.Println(3333)
 	return hash.String(), r.repo.Push(gopts)
 }
 
@@ -261,7 +259,6 @@
 	if o.ToBranch != "" {
 		popts = append(popts, WithToBranch(o.ToBranch))
 	}
-	fmt.Println(2222)
 	return r.CommitAndPush(msg, popts...)
 }
 
diff --git a/core/installer/vpn.go b/core/installer/vpn.go
index beeb8e4..0176383 100644
--- a/core/installer/vpn.go
+++ b/core/installer/vpn.go
@@ -65,10 +65,11 @@
 	if err != nil {
 		return err
 	}
-	if resp.StatusCode != http.StatusOK {
-		var buf bytes.Buffer
-		io.Copy(&buf, resp.Body)
-		return errors.New(buf.String())
+	if resp.StatusCode == http.StatusOK {
+		return nil
+	}
+	if resp.StatusCode == http.StatusNotFound {
+		return ErrorNotFound
 	}
 	return nil
 }
@@ -82,10 +83,11 @@
 	if err != nil {
 		return err
 	}
-	if resp.StatusCode != http.StatusOK {
-		var buf bytes.Buffer
-		io.Copy(&buf, resp.Body)
-		return errors.New(buf.String())
+	if resp.StatusCode == http.StatusOK {
+		return nil
+	}
+	if resp.StatusCode == http.StatusNotFound {
+		return ErrorNotFound
 	}
 	return nil
 }
@@ -103,10 +105,11 @@
 	if err != nil {
 		return err
 	}
-	if resp.StatusCode != http.StatusOK {
-		var buf bytes.Buffer
-		io.Copy(&buf, resp.Body)
-		return errors.New(buf.String())
+	if resp.StatusCode == http.StatusOK {
+		return nil
+	}
+	if resp.StatusCode == http.StatusNotFound {
+		return ErrorNotFound
 	}
 	return nil
 }