Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix integration tests for client #930

Merged
merged 9 commits into from
Mar 12, 2024
12 changes: 9 additions & 3 deletions .github/workflows/grid-client-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@ jobs:
sudo apt-get update
sudo apt-get install yggdrasil
sudo systemctl enable yggdrasil
PEERS=$(curl https://raw.githubusercontent.com/threefoldtech/zos-config/main/development.json | jq '.yggdrasil.peers[]' -r | sed 's/\//\\\//g' | sed -z 's/\n/\\n/g')
sudo sed -i -- 's/Peers\: \[\]/Peers: [\n'"$PEERS"']/g' /etc/yggdrasil/yggdrasil.conf
PEERS=$(curl https://raw.githubusercontent.com/AhmedHanafy725/yggdrasil-config/main/config.json | jq '.yggdrasil.peers[]' -r | sed 's/\//\\\//g' | sed -z 's/\n/\\n/g')
sudo sed -i -- 's/Peers\: \[\]/Peers: [\n'"$PEERS"']/g' /etc/yggdrasil/yggdrasil.conf
sudo systemctl stop yggdrasil
sudo systemctl start yggdrasil

- name: Test
env:
MNEMONICS: ${{ secrets.MNEMONICS }}
NETWORK: ${{ matrix.network }}
run: go test -v ./integration_tests -timeout 1800s
# run: make integration
run: |
for test in $(go run scripts/scrap_tests.go)
do
go test -v ./integration_tests -run $test
done
2 changes: 2 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
Expand Down Expand Up @@ -1672,6 +1673,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
5 changes: 4 additions & 1 deletion grid-client/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
PWD := $(shell pwd)
GOPATH := $(shell go env GOPATH)
integration_tests := $(shell go run scripts/scrap_tests.go)

all: verifiers test

Expand All @@ -9,7 +10,9 @@ test:

integration:
@echo "Running integration tests"
go test -v ./integration_tests
@for test in ${integration_tests} ; do \
go test -v ./integration_tests -run $$test ; \
done

coverage: clean
@echo "Installing gopherbadger" && go get -u github.com/jpoles1/gopherbadger && go install github.com/jpoles1/gopherbadger
Expand Down
11 changes: 2 additions & 9 deletions grid-client/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ func (d *Deployer) deploy(
}

dl.ContractID = contractID
ctx, cancel := context.WithTimeout(ctx, 4*time.Minute)
defer cancel()
err = client.DeploymentDeploy(ctx, dl)

if err != nil {
Expand Down Expand Up @@ -245,9 +243,7 @@ func (d *Deployer) deploy(
return currentDeployments, errors.Wrap(err, "failed to update deployment")
}
dl.ContractID = contractID
sub, cancel := context.WithTimeout(ctx, 4*time.Minute)
defer cancel()
err = client.DeploymentUpdate(sub, dl)
err = client.DeploymentUpdate(ctx, dl)
if err != nil {
// cancel previous contract
return currentDeployments, errors.Wrapf(err, "failed to send deployment update request to node %d", node)
Expand Down Expand Up @@ -286,10 +282,7 @@ func (d *Deployer) GetDeployments(ctx context.Context, dls map[uint32]uint64) (m
return nil, errors.Wrapf(err, "failed to get a client for node %d", nodeID)
}

sub, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()

dl, err := nc.DeploymentGet(sub, dlID)
dl, err := nc.DeploymentGet(ctx, dlID)
if err != nil {
return nil, errors.Wrapf(err, "failed to get deployment %d of node %d", dlID, nodeID)
}
Expand Down
4 changes: 0 additions & 4 deletions grid-client/deployer/gateway_name_deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ func (d *GatewayNameDeployer) BatchDeploy(ctx context.Context, gws []*workloads.

// Cancel cancels the gatewayName deployment
func (d *GatewayNameDeployer) Cancel(ctx context.Context, gw *workloads.GatewayNameProxy) (err error) {
if err := d.Validate(ctx, gw); err != nil {
return err
}

contractID := gw.NodeDeploymentID[gw.NodeID]
err = d.deployer.Cancel(ctx, contractID)
if err != nil {
Expand Down
12 changes: 2 additions & 10 deletions grid-client/deployer/k8s_deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,9 @@ func (d *K8sDeployer) Deploy(ctx context.Context, k8sCluster *workloads.K8sClust
// update deployments state
// error is not returned immediately before updating state because of untracked failed deployments
if contractID, ok := k8sCluster.NodeDeploymentID[k8sCluster.Master.Node]; ok && contractID != 0 {
if !workloads.Contains(d.tfPluginClient.State.CurrentNodeDeployments[k8sCluster.Master.Node], contractID) {
d.tfPluginClient.State.CurrentNodeDeployments[k8sCluster.Master.Node] = append(d.tfPluginClient.State.CurrentNodeDeployments[k8sCluster.Master.Node], contractID)
}
d.tfPluginClient.State.StoreContractIDs(k8sCluster.Master.Node, contractID)
for _, w := range k8sCluster.Workers {
if !workloads.Contains(d.tfPluginClient.State.CurrentNodeDeployments[w.Node], k8sCluster.NodeDeploymentID[w.Node]) {
d.tfPluginClient.State.CurrentNodeDeployments[w.Node] = append(d.tfPluginClient.State.CurrentNodeDeployments[w.Node], k8sCluster.NodeDeploymentID[w.Node])
}
d.tfPluginClient.State.StoreContractIDs(w.Node, k8sCluster.NodeDeploymentID[w.Node])
}
}

Expand Down Expand Up @@ -194,10 +190,6 @@ func (d *K8sDeployer) BatchDeploy(ctx context.Context, k8sClusters []*workloads.

// Cancel cancels a k8s cluster deployment
func (d *K8sDeployer) Cancel(ctx context.Context, k8sCluster *workloads.K8sCluster) (err error) {
if err := d.Validate(ctx, k8sCluster); err != nil {
return err
}

for nodeID, contractID := range k8sCluster.NodeDeploymentID {
if k8sCluster.Master.Node == nodeID {
err = d.deployer.Cancel(ctx, contractID)
Expand Down
30 changes: 22 additions & 8 deletions grid-client/deployer/network_deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,16 +432,27 @@ func (d *NetworkDeployer) Deploy(ctx context.Context, znet *workloads.ZNet) erro
newDeploymentsSolutionProvider[nodeID] = nil
}

oldDeployments := znet.NodeDeploymentID
znet.NodeDeploymentID, err = d.deployer.Deploy(ctx, znet.NodeDeploymentID, newDeployments, newDeploymentsSolutionProvider)

// update deployment and plugin state
// error is not returned immediately before updating state because of untracked failed deployments
for _, nodeID := range znet.Nodes {
nodesUsed := znet.Nodes
if znet.PublicNodeID != 0 && !slices.Contains(znet.Nodes, znet.PublicNodeID) {
nodesUsed = append(znet.Nodes, znet.PublicNodeID)
}

for _, nodeID := range nodesUsed {
if contractID, ok := znet.NodeDeploymentID[nodeID]; ok && contractID != 0 {
d.tfPluginClient.State.Networks.UpdateNetworkSubnets(znet.Name, znet.NodesIPRange)
if !workloads.Contains(d.tfPluginClient.State.CurrentNodeDeployments[nodeID], znet.NodeDeploymentID[nodeID]) {
d.tfPluginClient.State.CurrentNodeDeployments[nodeID] = append(d.tfPluginClient.State.CurrentNodeDeployments[nodeID], znet.NodeDeploymentID[nodeID])
}
d.tfPluginClient.State.StoreContractIDs(nodeID, contractID)
}
}

for nodeID, contract := range oldDeployments {
// public node is removed
if _, ok := znet.NodeDeploymentID[nodeID]; !ok {
d.tfPluginClient.State.RemoveContractIDs(nodeID, contract)
}
}

Expand Down Expand Up @@ -555,7 +566,12 @@ func (d *NetworkDeployer) BatchCancel(ctx context.Context, znets []*workloads.ZN
func (d *NetworkDeployer) updateStateFromDeployments(ctx context.Context, znet *workloads.ZNet, dls map[uint32][]gridtypes.Deployment, updateMetadata bool) error {
znet.NodeDeploymentID = map[uint32]uint64{}

for _, nodeID := range znet.Nodes {
nodesUsed := znet.Nodes
if znet.PublicNodeID != 0 && !slices.Contains(znet.Nodes, znet.PublicNodeID) {
nodesUsed = append(znet.Nodes, znet.PublicNodeID)
}

for _, nodeID := range nodesUsed {
// assign NodeDeploymentIDs
for _, dl := range dls[nodeID] {
dlData, err := workloads.ParseDeploymentData(dl.Metadata)
Expand All @@ -569,9 +585,7 @@ func (d *NetworkDeployer) updateStateFromDeployments(ctx context.Context, znet *

if contractID, ok := znet.NodeDeploymentID[nodeID]; ok && contractID != 0 {
d.tfPluginClient.State.Networks.UpdateNetworkSubnets(znet.Name, znet.NodesIPRange)
if !workloads.Contains(d.tfPluginClient.State.CurrentNodeDeployments[nodeID], znet.NodeDeploymentID[nodeID]) {
d.tfPluginClient.State.CurrentNodeDeployments[nodeID] = append(d.tfPluginClient.State.CurrentNodeDeployments[nodeID], znet.NodeDeploymentID[nodeID])
}
d.tfPluginClient.State.StoreContractIDs(nodeID, contractID)
}
}

Expand Down
3 changes: 1 addition & 2 deletions grid-client/deployer/node_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ func FilterNodes(ctx context.Context, tfPlugin TFPluginClient, options types.Nod
for node := range nodesOutput {
nodes = append(nodes, node)
if uint64(len(nodes)) == nodesCount {
log.Debug().Uint64("reached nodes page", limit.Page).Int("total pages", totalPagesCount).Send()
return nodes, nil
}
}
Expand Down Expand Up @@ -237,7 +236,7 @@ func GetPublicNode(ctx context.Context, tfPlugin TFPluginClient, preferredNodes
}

for _, node := range nodes {
log.Printf("found a node with ipv4 public config: %d %s\n", node.NodeID, node.PublicConfig.Ipv4)
log.Printf("found a node with ipv4 public config: %d %s", node.NodeID, node.PublicConfig.Ipv4)
ip, _, err := net.ParseCIDR(node.PublicConfig.Ipv4)
if err != nil {
log.Printf("could not parse public ip %s of node %d: %s", node.PublicConfig.Ipv4, node.NodeID, err.Error())
Expand Down
134 changes: 81 additions & 53 deletions grid-client/integration_tests/batch_gateway_name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,78 @@ package integration
import (
"context"
"fmt"
"net"
"io"
"net/http"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/threefoldtech/tfgrid-sdk-go/grid-client/deployer"
"github.com/threefoldtech/tfgrid-sdk-go/grid-client/workloads"

"github.com/threefoldtech/zos/pkg/gridtypes"
"github.com/threefoldtech/zos/pkg/gridtypes/zos"
)

func TestBatchGatewayNameDeployment(t *testing.T) {
tfPluginClient, err := setup()
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
if err != nil {
t.Skipf("plugin creation failed: %v", err)
}

publicKey, _, err := GenerateSSHKeyPair()
publicKey, privateKey, err := GenerateSSHKeyPair()
require.NoError(t, err)

nodeFilter := nodeFilter
nodeFilter.Domain = &trueVal

nodes, err := deployer.FilterNodes(ctx, tfPluginClient, nodeFilter, nil, nil, []uint64{minRootfs})
if err != nil || len(nodes) < 2 {
t.Skip("no available nodes found")
nodes, err := deployer.FilterNodes(
context.Background(),
tfPluginClient,
generateNodeFilter(WithDomain()),
nil,
nil,
nil,
2,
)
if err != nil {
t.Skipf("no available nodes found: %v", err)
}

nodeID1 := uint32(nodes[0].NodeID)
nodeID2 := uint32(nodes[1].NodeID)

network := workloads.ZNet{
Name: fmt.Sprintf("net_%s", generateRandString(10)),
Description: "network for testing",
Nodes: []uint32{nodeID1, nodeID2},
IPRange: gridtypes.NewIPNet(net.IPNet{
IP: net.IPv4(10, 20, 0, 0),
Mask: net.CIDRMask(16, 32),
}),
AddWGAccess: false,
}
network := generateBasicNetwork([]uint32{nodeID1, nodeID2})

vm := workloads.VM{
Name: "vm",
Flist: "https://hub.grid.tf/tf-official-apps/base:latest.flist",
CPU: 2,
Planetary: true,
Memory: 1024,
Entrypoint: "/sbin/zinit init",
Name: "vm",
NetworkName: network.Name,
CPU: minCPU,
Memory: int(minMemory) * 1024,
Planetary: true,
Flist: "https://hub.grid.tf/tf-official-apps/base:latest.flist",
Entrypoint: "/sbin/zinit init",
EnvVars: map[string]string{
"SSH_KEY": publicKey,
},
NetworkName: network.Name,
}

err = tfPluginClient.NetworkDeployer.Deploy(ctx, &network)
err = tfPluginClient.NetworkDeployer.Deploy(context.Background(), &network)
require.NoError(t, err)

defer func() {
err = tfPluginClient.NetworkDeployer.Cancel(ctx, &network)
assert.NoError(t, err)
}()
t.Cleanup(func() {
err = tfPluginClient.NetworkDeployer.Cancel(context.Background(), &network)
require.NoError(t, err)
})

dl := workloads.NewDeployment(fmt.Sprintf("dl_%s", generateRandString(10)), nodeID1, "", nil, network.Name, nil, nil, []workloads.VM{vm}, nil)
err = tfPluginClient.DeploymentDeployer.Deploy(ctx, &dl)
err = tfPluginClient.DeploymentDeployer.Deploy(context.Background(), &dl)
require.NoError(t, err)

defer func() {
err = tfPluginClient.DeploymentDeployer.Cancel(ctx, &dl)
assert.NoError(t, err)
}()
t.Cleanup(func() {
err = tfPluginClient.DeploymentDeployer.Cancel(context.Background(), &dl)
require.NoError(t, err)
})

v, err := tfPluginClient.State.LoadVMFromGrid(ctx, nodeID1, vm.Name, dl.Name)
v, err := tfPluginClient.State.LoadVMFromGrid(context.Background(), nodeID1, vm.Name, dl.Name)
require.NoError(t, err)

backend := fmt.Sprintf("http://[%s]:9000", v.PlanetaryIP)
Expand All @@ -98,22 +93,55 @@ func TestBatchGatewayNameDeployment(t *testing.T) {
Backends: []zos.Backend{zos.Backend(backend)},
}

err = tfPluginClient.GatewayNameDeployer.BatchDeploy(ctx, []*workloads.GatewayNameProxy{&gw1, &gw2})
err = tfPluginClient.GatewayNameDeployer.BatchDeploy(context.Background(), []*workloads.GatewayNameProxy{&gw1, &gw2})
require.NoError(t, err)

defer func() {
err = tfPluginClient.GatewayNameDeployer.Cancel(ctx, &gw1)
assert.NoError(t, err)
t.Cleanup(func() {
err = tfPluginClient.GatewayNameDeployer.Cancel(context.Background(), &gw1)
require.NoError(t, err)

err = tfPluginClient.GatewayNameDeployer.Cancel(context.Background(), &gw2)
require.NoError(t, err)
})

err = tfPluginClient.GatewayNameDeployer.Cancel(ctx, &gw2)
assert.NoError(t, err)
}()
g1, err := tfPluginClient.State.LoadGatewayNameFromGrid(context.Background(), nodeID1, gw1.Name, gw1.Name)
require.NoError(t, err)
require.NotEmpty(t, g1.FQDN)

result, err := tfPluginClient.State.LoadGatewayNameFromGrid(ctx, nodeID1, gw1.Name, gw1.Name)
g2, err := tfPluginClient.State.LoadGatewayNameFromGrid(context.Background(), nodeID2, gw2.Name, gw2.Name)
require.NoError(t, err)
require.NotEmpty(t, result.FQDN)
require.NotEmpty(t, g2.FQDN)

result, err = tfPluginClient.State.LoadGatewayNameFromGrid(ctx, nodeID2, gw2.Name, gw2.Name)
_, err = RemoteRun("root", v.PlanetaryIP, "apk add python3; python3 -m http.server 9000 --bind :: &> /dev/null &", privateKey)
require.NoError(t, err)
require.NotEmpty(t, result.FQDN)

time.Sleep(3 * time.Second)
require.NoError(t, testFQDN(g1.FQDN))
require.NoError(t, testFQDN(g2.FQDN))
}

func testFQDN(fqdn string) error {
cl := &http.Client{
Timeout: 10 * time.Second,
}

response, err := cl.Get(fmt.Sprintf("https://%s", fqdn))
if err != nil {
return err
}

body, err := io.ReadAll(response.Body)
if err != nil {
return err
}

if body != nil {
defer response.Body.Close()
}

if !strings.Contains(string(body), "Directory listing for") {
return fmt.Errorf("response body doesn't contain 'Directory listing for'")
}

return nil
}
Loading
Loading