github.com/Redstoneguy129/cli@v0.0.0-20230211220159-15dca4e91917/internal/stop/stop_test.go (about)

     1  package stop
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/http"
     7  	"os"
     8  	"testing"
     9  
    10  	"github.com/docker/docker/api/types"
    11  	"github.com/spf13/afero"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  	"github.com/Redstoneguy129/cli/internal/testing/apitest"
    15  	"github.com/Redstoneguy129/cli/internal/utils"
    16  	"gopkg.in/h2non/gock.v1"
    17  )
    18  
    19  func TestStopCommand(t *testing.T) {
    20  	t.Run("stops containers with backup", func(t *testing.T) {
    21  		// Setup in-memory fs
    22  		fsys := afero.NewMemMapFs()
    23  		require.NoError(t, utils.WriteConfig(fsys, false))
    24  		// Setup mock docker
    25  		require.NoError(t, apitest.MockDocker(utils.Docker))
    26  		defer gock.OffAll()
    27  		gock.New(utils.Docker.DaemonHost()).
    28  			Get("/v" + utils.Docker.ClientVersion() + "/containers/json").
    29  			Reply(http.StatusOK).
    30  			JSON([]types.Container{})
    31  		gock.New(utils.Docker.DaemonHost()).
    32  			Post("/v" + utils.Docker.ClientVersion() + "/containers/prune").
    33  			Reply(http.StatusOK).
    34  			JSON(types.ContainersPruneReport{})
    35  		gock.New(utils.Docker.DaemonHost()).
    36  			Post("/v" + utils.Docker.ClientVersion() + "/networks/prune").
    37  			Reply(http.StatusOK).
    38  			JSON(types.NetworksPruneReport{})
    39  		// Run test
    40  		err := Run(context.Background(), true, fsys)
    41  		// Check error
    42  		assert.NoError(t, err)
    43  		assert.Empty(t, apitest.ListUnmatchedRequests())
    44  	})
    45  
    46  	t.Run("throws error on invalid config", func(t *testing.T) {
    47  		// Setup in-memory fs
    48  		fsys := afero.NewMemMapFs()
    49  		// Run test
    50  		err := Run(context.Background(), false, fsys)
    51  		// Check error
    52  		assert.ErrorIs(t, err, os.ErrNotExist)
    53  	})
    54  
    55  	t.Run("throws error on stop failure", func(t *testing.T) {
    56  		// Setup in-memory fs
    57  		fsys := afero.NewMemMapFs()
    58  		require.NoError(t, utils.WriteConfig(fsys, false))
    59  		// Setup mock docker
    60  		require.NoError(t, apitest.MockDocker(utils.Docker))
    61  		defer gock.OffAll()
    62  		gock.New(utils.Docker.DaemonHost()).
    63  			Get("/v" + utils.Docker.ClientVersion() + "/containers/json").
    64  			Reply(http.StatusServiceUnavailable)
    65  		// Run test
    66  		err := Run(context.Background(), false, afero.NewReadOnlyFs(fsys))
    67  		// Check error
    68  		assert.ErrorContains(t, err, "request returned Service Unavailable for API route and version")
    69  		assert.Empty(t, apitest.ListUnmatchedRequests())
    70  	})
    71  }
    72  
    73  func TestStopServices(t *testing.T) {
    74  	t.Run("stops all services", func(t *testing.T) {
    75  		containers := []types.Container{{ID: "c1", State: "running"}, {ID: "c2"}}
    76  		// Setup mock docker
    77  		require.NoError(t, apitest.MockDocker(utils.Docker))
    78  		defer gock.OffAll()
    79  		gock.New(utils.Docker.DaemonHost()).
    80  			Get("/v" + utils.Docker.ClientVersion() + "/containers/json").
    81  			Reply(http.StatusOK).
    82  			JSON(containers)
    83  		gock.New(utils.Docker.DaemonHost()).
    84  			Post("/v" + utils.Docker.ClientVersion() + "/containers/" + containers[0].ID + "/stop").
    85  			Reply(http.StatusOK)
    86  		gock.New(utils.Docker.DaemonHost()).
    87  			Post("/v" + utils.Docker.ClientVersion() + "/containers/prune").
    88  			Reply(http.StatusOK).
    89  			JSON(types.ContainersPruneReport{})
    90  		gock.New(utils.Docker.DaemonHost()).
    91  			Post("/v" + utils.Docker.ClientVersion() + "/networks/prune").
    92  			Reply(http.StatusOK).
    93  			JSON(types.NetworksPruneReport{})
    94  		// Run test
    95  		err := stop(context.Background(), true)
    96  		// Check error
    97  		assert.NoError(t, err)
    98  		assert.Empty(t, apitest.ListUnmatchedRequests())
    99  	})
   100  
   101  	t.Run("removes data volumes", func(t *testing.T) {
   102  		utils.DbId = "test-db"
   103  		utils.StorageId = "test-storage"
   104  		// Setup mock docker
   105  		require.NoError(t, apitest.MockDocker(utils.Docker))
   106  		defer gock.OffAll()
   107  		gock.New(utils.Docker.DaemonHost()).
   108  			Get("/v" + utils.Docker.ClientVersion() + "/containers/json").
   109  			Reply(http.StatusOK).
   110  			JSON([]types.Container{})
   111  		gock.New(utils.Docker.DaemonHost()).
   112  			Post("/v" + utils.Docker.ClientVersion() + "/containers/prune").
   113  			Reply(http.StatusOK).
   114  			JSON(types.ContainersPruneReport{})
   115  		gock.New(utils.Docker.DaemonHost()).
   116  			Delete("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.DbId).
   117  			Reply(http.StatusOK)
   118  		gock.New(utils.Docker.DaemonHost()).
   119  			Delete("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.StorageId).
   120  			Reply(http.StatusNotFound)
   121  		gock.New(utils.Docker.DaemonHost()).
   122  			Post("/v" + utils.Docker.ClientVersion() + "/networks/prune").
   123  			Reply(http.StatusOK).
   124  			JSON(types.NetworksPruneReport{})
   125  		// Run test
   126  		err := stop(context.Background(), false)
   127  		// Check error
   128  		assert.NoError(t, err)
   129  		assert.Empty(t, apitest.ListUnmatchedRequests())
   130  	})
   131  
   132  	t.Run("throws error on prune failure", func(t *testing.T) {
   133  		// Setup mock docker
   134  		require.NoError(t, apitest.MockDocker(utils.Docker))
   135  		defer gock.OffAll()
   136  		gock.New(utils.Docker.DaemonHost()).
   137  			Get("/v" + utils.Docker.ClientVersion() + "/containers/json").
   138  			Reply(http.StatusOK).
   139  			JSON([]types.Container{})
   140  		gock.New(utils.Docker.DaemonHost()).
   141  			Post("/v" + utils.Docker.ClientVersion() + "/containers/prune").
   142  			ReplyError(errors.New("network error"))
   143  		// Run test
   144  		err := stop(context.Background(), true)
   145  		// Check error
   146  		assert.ErrorContains(t, err, "network error")
   147  		assert.Empty(t, apitest.ListUnmatchedRequests())
   148  	})
   149  }