diff --git a/control/environment_docker.go b/control/environment_docker.go index 08b1bcb..1d7daec 100644 --- a/control/environment_docker.go +++ b/control/environment_docker.go @@ -199,8 +199,8 @@ func (env *dockerEnvironment) Start() error { func (env *dockerEnvironment) Stop() error { log.WithField("server", env.server.ID).Debug("Stopping service in docker environment") - // TODO: Decide after what timeout to kill the container, currently 10min - timeout := time.Minute * 10 + // TODO: Decide after what timeout to kill the container, currently 30 seconds + timeout := 30 * time.Second if err := env.client.ContainerStop(context.TODO(), env.server.DockerContainer.ID, &timeout); err != nil { log.WithError(err).Error("Failed to stop docker container") return err @@ -211,7 +211,7 @@ func (env *dockerEnvironment) Stop() error { func (env *dockerEnvironment) Kill() error { log.WithField("server", env.server.ID).Debug("Killing service in docker environment") - if err := env.client.ContainerKill(context.TODO(), env.server.DockerContainer.ID, "SIGKILL"); err != nil { + if err := env.client.ContainerKill(context.TODO(), env.server.DockerContainer.ID, "KILL"); err != nil { log.WithError(err).Error("Failed to kill docker container") return err } @@ -220,24 +220,26 @@ func (env *dockerEnvironment) Kill() error { // Exec sends commands to the standard input of the docker container func (env *dockerEnvironment) Exec(command string) error { - //log.Debug("Command: " + command) - //_, err := env.containerInput.Write([]byte(command + "\n")) - //return err - return nil + log.Debug("Command: " + command) + _, err := env.hires.Conn.Write([]byte(command + "\n")) + return err } func (env *dockerEnvironment) pullImage(ctx context.Context) error { // Split image repository and tag - imageParts := strings.Split(env.server.GetService().DockerImage, ":") - imageRepoParts := strings.Split(imageParts[0], "/") - if len(imageRepoParts) >= 3 { - // TODO: Handle possibly required authentication - } + //imageParts := strings.Split(env.server.GetService().DockerImage, ":") + //imageRepoParts := strings.Split(imageParts[0], "/") + //if len(imageRepoParts) >= 3 { + // TODO: Handle possibly required authentication + //} // Pull docker image log.WithField("image", env.server.GetService().DockerImage).Debug("Pulling docker image") rc, err := env.client.ImagePull(ctx, env.server.GetService().DockerImage, types.ImagePullOptions{}) + if err != nil { + return err + } defer rc.Close() - return err + return nil } diff --git a/control/environment_docker_test.go b/control/environment_docker_test.go index 9d8f438..68aeb10 100644 --- a/control/environment_docker_test.go +++ b/control/environment_docker_test.go @@ -1,125 +1,133 @@ package control -// func testServer() *ServerStruct { -// return &ServerStruct{ -// ID: "testuuid-something-something", -// service: &service{ -// DockerImage: "alpine:latest", -// }, -// } -// } +import ( + "context" + "fmt" + "testing" -// func TestNewDockerEnvironment(t *testing.T) { -// env, err := createTestDockerEnv(nil) + "github.com/pterodactyl/wings/api/websockets" -// assert.Nil(t, err) -// assert.NotNil(t, env) -// assert.NotNil(t, env.client) -// } + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/pterodactyl/wings/config" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" +) -// func TestNewDockerEnvironmentExisting(t *testing.T) { -// eenv, _ := createTestDockerEnv(nil) -// eenv.Create() +func testServer() *ServerStruct { + viper.SetDefault(config.DataPath, "./data") + return &ServerStruct{ + ID: "testuuid-something-something", + Service: &Service{ + DockerImage: "alpine:latest", + }, + StartupCommand: "/bin/ash echo hello && sleep 100", + websockets: websockets.NewCollection(), + } +} -// env, err := createTestDockerEnv(eenv.server) +func TestNewDockerEnvironment(t *testing.T) { + env, err := createTestDockerEnv(nil) -// assert.Nil(t, err) -// assert.NotNil(t, env) -// assert.NotNil(t, env.container) + assert.Nil(t, err) + assert.NotNil(t, env) + assert.NotNil(t, env.client) +} -// eenv.Destroy() -// } +func TestNewDockerEnvironmentExisting(t *testing.T) { + eenv, _ := createTestDockerEnv(nil) + eenv.Create() -// func TestCreateDockerEnvironment(t *testing.T) { -// env, _ := createTestDockerEnv(nil) + env, err := createTestDockerEnv(eenv.server) -// err := env.Create() + assert.Nil(t, err) + assert.NotNil(t, env) + assert.NotNil(t, env.server.DockerContainer) -// a := assert.New(t) -// a.Nil(err) -// a.NotNil(env.container) -// a.Equal(env.container.Name, "ptdl_testuuid") + eenv.Destroy() +} -// if err := env.client.RemoveContainer(docker.RemoveContainerOptions{ -// ID: env.container.ID, -// }); err != nil { -// fmt.Println(err) -// } -// } +func TestCreateDockerEnvironment(t *testing.T) { + env, _ := createTestDockerEnv(nil) -// func TestDestroyDockerEnvironment(t *testing.T) { -// env, _ := createTestDockerEnv(nil) -// env.Create() + err := env.Create() -// err := env.Destroy() + a := assert.New(t) + a.Nil(err) + a.NotNil(env.server.DockerContainer.ID) -// _, ierr := env.client.InspectContainer(env.container.ID) + if err := env.client.ContainerRemove(context.TODO(), env.server.DockerContainer.ID, types.ContainerRemoveOptions{}); err != nil { + fmt.Println(err) + } +} -// assert.Nil(t, err) -// assert.IsType(t, ierr, &docker.NoSuchContainer{}) -// } +func TestDestroyDockerEnvironment(t *testing.T) { + env, _ := createTestDockerEnv(nil) + env.Create() -// func TestStartDockerEnvironment(t *testing.T) { -// env, _ := createTestDockerEnv(nil) -// env.Create() -// err := env.Start() + err := env.Destroy() -// i, ierr := env.client.InspectContainer(env.container.ID) + _, ierr := env.client.ContainerInspect(context.TODO(), env.server.DockerContainer.ID) -// assert.Nil(t, err) -// assert.Nil(t, ierr) -// assert.True(t, i.State.Running) + assert.Nil(t, err) + assert.True(t, client.IsErrNotFound(ierr)) +} -// env.client.KillContainer(docker.KillContainerOptions{ -// ID: env.container.ID, -// }) -// env.Destroy() -// } +func TestStartDockerEnvironment(t *testing.T) { + env, _ := createTestDockerEnv(nil) + env.Create() + err := env.Start() -// func TestStopDockerEnvironment(t *testing.T) { -// env, _ := createTestDockerEnv(nil) -// env.Create() -// env.Start() -// err := env.Stop() + i, ierr := env.client.ContainerInspect(context.TODO(), env.server.DockerContainer.ID) -// i, ierr := env.client.InspectContainer(env.container.ID) + assert.Nil(t, err) + assert.Nil(t, ierr) + assert.True(t, i.State.Running) -// assert.Nil(t, err) -// assert.Nil(t, ierr) -// assert.False(t, i.State.Running) + env.client.ContainerKill(context.TODO(), env.server.DockerContainer.ID, "KILL") + env.Destroy() +} -// env.client.KillContainer(docker.KillContainerOptions{ -// ID: env.container.ID, -// }) -// env.Destroy() -// } +func TestStopDockerEnvironment(t *testing.T) { + env, _ := createTestDockerEnv(nil) + env.Create() + env.Start() + err := env.Stop() -// func TestKillDockerEnvironment(t *testing.T) { -// env, _ := createTestDockerEnv(nil) -// env.Create() -// env.Start() -// err := env.Kill() + i, ierr := env.client.ContainerInspect(context.TODO(), env.server.DockerContainer.ID) -// i, ierr := env.client.InspectContainer(env.container.ID) + assert.Nil(t, err) + assert.Nil(t, ierr) + assert.False(t, i.State.Running) -// assert.Nil(t, err) -// assert.Nil(t, ierr) -// assert.False(t, i.State.Running) + env.client.ContainerKill(context.TODO(), env.server.DockerContainer.ID, "KILL") + env.Destroy() +} -// env.client.KillContainer(docker.KillContainerOptions{ -// ID: env.container.ID, -// }) -// env.Destroy() -// } +func TestKillDockerEnvironment(t *testing.T) { + env, _ := createTestDockerEnv(nil) + env.Create() + env.Start() + err := env.Kill() -// func TestExecDockerEnvironment(t *testing.T) { + i, ierr := env.client.ContainerInspect(context.TODO(), env.server.DockerContainer.ID) -// } + assert.Nil(t, err) + assert.Nil(t, ierr) + assert.False(t, i.State.Running) -// func createTestDockerEnv(s *ServerStruct) (*dockerEnvironment, error) { -// if s == nil { -// s = testServer() -// } -// env, err := NewDockerEnvironment(s) -// return env.(*dockerEnvironment), err -// } + env.client.ContainerKill(context.TODO(), env.server.DockerContainer.ID, "KILL") + env.Destroy() +} + +func TestExecDockerEnvironment(t *testing.T) { + +} + +func createTestDockerEnv(s *ServerStruct) (*dockerEnvironment, error) { + if s == nil { + s = testServer() + } + env, err := NewDockerEnvironment(s) + return env.(*dockerEnvironment), err +} diff --git a/control/server_persistance.go b/control/server_persistance.go index 98c93bd..14c2520 100644 --- a/control/server_persistance.go +++ b/control/server_persistance.go @@ -91,7 +91,12 @@ func (s *ServerStruct) Save() error { } func (s *ServerStruct) path() string { - return filepath.Join(viper.GetString(config.DataPath), constants.ServersPath, s.ID) + p, err := filepath.Abs(viper.GetString(config.DataPath)) + if err != nil { + log.WithError(err).WithField("server", s.ID).Error("Failed to get absolute data path for server.") + p = viper.GetString(config.DataPath) + } + return filepath.Join(p, constants.ServersPath, s.ID) } func (s *ServerStruct) dataPath() string { diff --git a/wings-api.paw b/wings-api.paw index 7894549..0df8451 100644 Binary files a/wings-api.paw and b/wings-api.paw differ