Skip to content

Commit

Permalink
add wireguard cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Despire committed Oct 6, 2023
1 parent dd6dcd4 commit 895989f
Show file tree
Hide file tree
Showing 13 changed files with 481 additions and 90 deletions.
11 changes: 0 additions & 11 deletions internal/utils/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,17 +181,6 @@ func GetDynamicNodePools(nps []*pb.NodePool) []*pb.DynamicNodePool {
return dnps
}

// GetStaticNodePools returns slice of dynamic node pools.
func GetStaticNodePools(nps []*pb.NodePool) []*pb.StaticNodePool {
snps := make([]*pb.StaticNodePool, 0, len(nps))
for _, np := range nps {
if n := np.GetStaticNodePool(); n != nil {
snps = append(snps, n)
}
}
return snps
}

// GetCommonStaticNodePools returns slice of common node pools, where every node pool is static.
func GetCommonStaticNodePools(nps []*pb.NodePool) []*pb.NodePool {
static := make([]*pb.NodePool, 0, len(nps))
Expand Down
13 changes: 13 additions & 0 deletions proto/ansibler.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ message UpdateAPIEndpointResponse{
K8scluster desired = 2;
}

message RemoveClaudieUtilitiesRequest {
K8scluster current = 1;
repeated LBcluster currentLbs = 2;
string projectName = 3;
}

message RemoveClaudieUtilitiesResponse {
K8scluster current = 1;
repeated LBcluster currentLbs = 2;
}

service AnsiblerService {
// InstallNodeRequirements installs any requirements there are on all of the nodes.
rpc InstallNodeRequirements(InstallRequest) returns (InstallResponse);
Expand All @@ -67,4 +78,6 @@ service AnsiblerService {
// UpdateAPIEndpoint handles changes of API endpoint between control nodes.
// It will update the current stage based on the information from the desired state.
rpc UpdateAPIEndpoint(UpdateAPIEndpointRequest) returns (UpdateAPIEndpointResponse);
// Removes utilities installed by claudie via ansible playbooks.
rpc RemoveClaudieUtilities(RemoveClaudieUtilitiesRequest) returns (RemoveClaudieUtilitiesResponse);
}
326 changes: 251 additions & 75 deletions proto/pb/ansibler.pb.go

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions proto/pb/ansibler_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions services/ansibler/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import (
"github.com/berops/claudie/proto/pb"
)

func RemoveClaudieUtilities(c pb.AnsiblerServiceClient, req *pb.RemoveClaudieUtilitiesRequest) (*pb.RemoveClaudieUtilitiesResponse, error) {
res, err := c.RemoveClaudieUtilities(context.Background(), req)
if err != nil {
return res, fmt.Errorf("error while calling RemoveClaudieUtilities on Ansibler: %w", err)
}
return res, nil
}

// InstallVPN installs a Wireguard VPN on the nodes in the cluster and loadbalancers
func InstallVPN(c pb.AnsiblerServiceClient, req *pb.InstallRequest) (*pb.InstallResponse, error) {
res, err := c.InstallVPN(context.Background(), req)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ type AnsiblerGrpcService struct {
usecases *usecases.Usecases
}

func (a *AnsiblerGrpcService) RemoveClaudieUtilities(_ context.Context, request *pb.RemoveClaudieUtilitiesRequest) (*pb.RemoveClaudieUtilitiesResponse, error) {
return a.usecases.RemoveUtilities(request)
}

func (a *AnsiblerGrpcService) UpdateAPIEndpoint(_ context.Context, request *pb.UpdateAPIEndpointRequest) (*pb.UpdateAPIEndpointResponse, error) {
return a.usecases.UpdateAPIEndpoint(request)
}
Expand Down
37 changes: 37 additions & 0 deletions services/ansibler/server/ansible-playbooks/wireguard-uninstall.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
- hosts: all
remote_user: root
gather_facts: false
become: yes

pre_tasks:
- name: Wait 300 seconds for target connection to become reachable/usable
wait_for_connection:
timeout: 300

# Gather facts manually after we made sure, VMs are accessible
- name: Gather facts from nodes
ansible.builtin.setup:

tasks:
- name: Bring down WireGuard interface
ansible.builtin.command: wg-quick down wg0
ignore_errors: yes

- name: Stop and disable systemd service for wg-quick@wg0
ansible.builtin.systemd:
name: "wg-quick@wg0"
enabled: no
state: stopped

- name: Delete WireGuard configuration directory
ansible.builtin.file:
path: "/etc/wireguard"
state: absent

- name: Remove WireGuard package via apt
ansible.builtin.apt:
pkg:
- wireguard
- wireguard-tools
state: absent
5 changes: 4 additions & 1 deletion services/ansibler/server/domain/usecases/install_vpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import (
"github.com/berops/claudie/services/ansibler/templates"
)

const wireguardPlaybookFilePath = "../../ansible-playbooks/wireguard.yml"
const (
wireguardPlaybookFilePath = "../../ansible-playbooks/wireguard.yml"
wireguardUninstall = "../../ansible-playbooks/wireguard-uninstall.yml"
)

type VPNInfo struct {
ClusterNetwork string
Expand Down
89 changes: 89 additions & 0 deletions services/ansibler/server/domain/usecases/remove_utilities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package usecases

import (
"fmt"
"github.com/rs/zerolog/log"
"os"
"path/filepath"

cutils "github.com/berops/claudie/internal/utils"
"github.com/berops/claudie/proto/pb"
"github.com/berops/claudie/services/ansibler/server/utils"
"github.com/berops/claudie/services/ansibler/templates"
)

func (u *Usecases) RemoveUtilities(req *pb.RemoveClaudieUtilitiesRequest) (*pb.RemoveClaudieUtilitiesResponse, error) {
logger := cutils.CreateLoggerWithProjectAndClusterName(req.ProjectName, req.Current.ClusterInfo.Name)
logger.Info().Msgf("Removing Claudie installed utilities")

vpnInfo := &VPNInfo{
ClusterNetwork: req.Current.Network,
NodepoolsInfos: []*NodepoolsInfo{
{
Nodepools: utils.NodePools{
Dynamic: cutils.GetCommonDynamicNodePools(req.Current.ClusterInfo.NodePools),
Static: cutils.GetCommonStaticNodePools(req.Current.ClusterInfo.NodePools),
},
PrivateKey: req.Current.ClusterInfo.PrivateKey,
ClusterID: cutils.GetClusterID(req.Current.ClusterInfo),
ClusterNetwork: req.Current.Network,
},
},
}

for _, lbCluster := range req.CurrentLbs {
vpnInfo.NodepoolsInfos = append(vpnInfo.NodepoolsInfos, &NodepoolsInfo{
Nodepools: utils.NodePools{
Dynamic: cutils.GetCommonDynamicNodePools(lbCluster.ClusterInfo.NodePools),
Static: cutils.GetCommonStaticNodePools(lbCluster.ClusterInfo.NodePools),
},
PrivateKey: lbCluster.ClusterInfo.PrivateKey,
ClusterID: cutils.GetClusterID(lbCluster.ClusterInfo),
ClusterNetwork: req.Current.Network,
})
}

if err := removeWireguard(cutils.GetClusterID(req.Current.ClusterInfo), vpnInfo, u.SpawnProcessLimit); err != nil {
return nil, fmt.Errorf("failed to remove wiregaurd from nodes: %w", err)
}

return &pb.RemoveClaudieUtilitiesResponse{Current: req.Current, CurrentLbs: req.CurrentLbs}, nil
}

func removeWireguard(clusterID string, vpnInfo *VPNInfo, spawnProcessLimit chan struct{}) error {
clusterDirectory := filepath.Join(baseDirectory, outputDirectory, fmt.Sprintf("%s-%s", clusterID, cutils.CreateHash(cutils.HashLength)))
if err := cutils.CreateDirectory(clusterDirectory); err != nil {
return fmt.Errorf("failed to create directory %s: %w", clusterDirectory, err)
}

err := utils.GenerateInventoryFile(templates.AllNodesInventoryTemplate, clusterDirectory, AllNodesInventoryData{
NodepoolsInfo: vpnInfo.NodepoolsInfos,
})
if err != nil {
return fmt.Errorf("error while creating inventory file for %s: %w", clusterDirectory, err)
}

for _, nodepoolInfo := range vpnInfo.NodepoolsInfos {
if err := cutils.CreateKeyFile(nodepoolInfo.PrivateKey, clusterDirectory, fmt.Sprintf("%s.%s", nodepoolInfo.ClusterID, sshPrivateKeyFileExtension)); err != nil {
return fmt.Errorf("failed to create key file for %s : %w", nodepoolInfo.ClusterID, err)
}

if err := cutils.CreateKeysForStaticNodepools(nodepoolInfo.Nodepools.Static, clusterDirectory); err != nil {
return fmt.Errorf("failed to create key file(s) for static nodes : %w", err)
}
}

ansible := utils.Ansible{
Playbook: wireguardUninstall,
Inventory: utils.InventoryFileName,
Directory: clusterDirectory,
SpawnProcessLimit: spawnProcessLimit,
}

// Subsequent calling may fail, thus simply log the error.
if err := ansible.RunAnsiblePlaybook(fmt.Sprintf("Remove Utils - %s", clusterID)); err != nil {
log.Warn().Msgf("error while uninstalling wireguard ansible for %s : %w", clusterID, err)

Check failure on line 85 in services/ansibler/server/domain/usecases/remove_utilities.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

printf: (*github.com/rs/zerolog.Event).Msgf does not support error-wrapping directive %w (govet)
}

return os.RemoveAll(clusterDirectory)
}
9 changes: 9 additions & 0 deletions services/builder/adapters/outbound/ansibler_connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ func (a *AnsiblerConnector) UpdateAPIEndpoint(builderCtx *utils.BuilderContext,
})
}

// RemoveClaudieUtilities removes claudie installed utilities from the nodes of the cluster.
func (a *AnsiblerConnector) RemoveClaudieUtilities(builderCtx *utils.BuilderContext, ansiblerGrpcClient pb.AnsiblerServiceClient) (*pb.RemoveClaudieUtilitiesResponse, error) {
return ansibler.RemoveClaudieUtilities(ansiblerGrpcClient, &pb.RemoveClaudieUtilitiesRequest{
Current: builderCtx.CurrentCluster,
CurrentLbs: builderCtx.CurrentLoadbalancers,
ProjectName: builderCtx.ProjectName,
})
}

// Disconnect closes the underlying gRPC connection to ansibler microservice
func (a *AnsiblerConnector) Disconnect() {
cutils.CloseClientConnection(a.Connection)
Expand Down
1 change: 1 addition & 0 deletions services/builder/domain/ports/ansibler_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type AnsiblerPort interface {
SetUpLoadbalancers(builderCtx *utils.BuilderContext, apiEndpoint string, ansiblerGrpcClient pb.AnsiblerServiceClient) (*pb.SetUpLBResponse, error)
TeardownLoadBalancers(builderCtx *utils.BuilderContext, ansiblerGrpcClient pb.AnsiblerServiceClient) (*pb.TeardownLBResponse, error)
UpdateAPIEndpoint(builderCtx *utils.BuilderContext, ansiblerGrpcClient pb.AnsiblerServiceClient) (*pb.UpdateAPIEndpointResponse, error)
RemoveClaudieUtilities(builderCtx *utils.BuilderContext, ansiblerGrpcClient pb.AnsiblerServiceClient) (*pb.RemoveClaudieUtilitiesResponse, error)

PerformHealthCheck() error
GetClient() pb.AnsiblerServiceClient
Expand Down
19 changes: 19 additions & 0 deletions services/builder/domain/usecases/ansibler_caller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,29 @@ import (
"github.com/berops/claudie/services/builder/domain/usecases/utils"
)

// removeClaudieUtilities removes previously installed claudie utilities.
func (u *Usecases) removeClaudieUtilities(ctx *utils.BuilderContext, cboxClient pb.ContextBoxServiceClient) error {
description := ctx.Workflow.Description
ctx.Workflow.Stage = pb.Workflow_ANSIBLER
u.saveWorkflowDescription(ctx, fmt.Sprintf("%s removing claudie installed utilities", description), cboxClient)

resp, err := u.Ansibler.RemoveClaudieUtilities(ctx, u.Ansibler.GetClient())
if err != nil {
return err
}

ctx.CurrentCluster = resp.Current
ctx.CurrentLoadbalancers = resp.CurrentLbs

u.saveWorkflowDescription(ctx, description, cboxClient)
return nil
}

// configureInfrastructure configures infrastructure via ansibler.
func (u *Usecases) configureInfrastructure(ctx *utils.BuilderContext, cboxClient pb.ContextBoxServiceClient) error {
logger := cutils.CreateLoggerWithProjectAndClusterName(ctx.ProjectName, ctx.GetClusterID())
ansClient := u.Ansibler.GetClient()

description := ctx.Workflow.Description
ctx.Workflow.Stage = pb.Workflow_ANSIBLER

Expand Down
11 changes: 8 additions & 3 deletions services/builder/domain/usecases/workflow_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ func (u *Usecases) buildCluster(ctx *utils.BuilderContext, cboxClient pb.Context

// destroyCluster destroys existing clusters infrastructure for a config and cleans up management cluster from any of the cluster data.
func (u *Usecases) destroyCluster(ctx *utils.BuilderContext, cboxClient pb.ContextBoxServiceClient) error {
// Destroy K8s cluster.
if err := u.destroyK8sCluster(ctx, cboxClient); err != nil {
return fmt.Errorf("error in destroy Kube-Eleven for config %s project %s : %w", ctx.GetClusterName(), ctx.ProjectName, err)
if s := cutils.GetCommonStaticNodePools(ctx.CurrentCluster.GetClusterInfo().GetNodePools()); len(s) > 0 {
if err := u.destroyK8sCluster(ctx, cboxClient); err != nil {
return fmt.Errorf("error in destroy Kube-Eleven for config %s project %s : %w", ctx.GetClusterName(), ctx.ProjectName, err)
}

if err := u.removeClaudieUtilities(ctx, cboxClient); err != nil {
return fmt.Errorf("error while removing claudie installed utilities for config %s project %s: %w", ctx.GetClusterName(), ctx.ProjectName, err)
}
}

// Destroy infrastructure for the given cluster.
Expand Down

0 comments on commit 895989f

Please sign in to comment.