Merge branch 'develop' of https://github.com/pterodactyl/wings into develop
This commit is contained in:
		
						commit
						044c46fc9a
					
				|  | @ -406,7 +406,7 @@ __ [blue][bold]Pterodactyl[reset] _____/___/_______ _______ ______ | ||||||
| \_____\    \/\/    /   /       /  __   /   ___/ | \_____\    \/\/    /   /       /  __   /   ___/ | ||||||
|    \___\          /   /   /   /  /_/  /___   / |    \___\          /   /   /   /  /_/  /___   / | ||||||
|         \___/\___/___/___/___/___    /______/ |         \___/\___/___/___/___/___    /______/ | ||||||
|                             /_______/ [bold]v%s[reset] |                             /_______/ [bold]%s[reset] | ||||||
| 
 | 
 | ||||||
| Copyright © 2018 - 2021 Dane Everitt & Contributors | Copyright © 2018 - 2021 Dane Everitt & Contributors | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ func (e *Environment) Attach() error { | ||||||
| 
 | 
 | ||||||
| 		// Block the completion of this routine until the container is no longer running. This allows
 | 		// Block the completion of this routine until the container is no longer running. This allows
 | ||||||
| 		// the pollResources function to run until it needs to be stopped. Because the container
 | 		// the pollResources function to run until it needs to be stopped. Because the container
 | ||||||
| 		// can be polled for resource usage, even when sropped, we need to have this logic present
 | 		// can be polled for resource usage, even when stopped, we need to have this logic present
 | ||||||
| 		// in order to cancel the context and therefore stop the routine that is spawned.
 | 		// in order to cancel the context and therefore stop the routine that is spawned.
 | ||||||
| 		//
 | 		//
 | ||||||
| 		// For now, DO NOT use client#ContainerWait from the Docker package. There is a nasty
 | 		// For now, DO NOT use client#ContainerWait from the Docker package. There is a nasty
 | ||||||
|  | @ -278,6 +278,8 @@ func (e *Environment) Destroy() error { | ||||||
| 		Force:         true, | 		Force:         true, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | 	e.SetState(environment.ProcessOfflineState) | ||||||
|  | 
 | ||||||
| 	// Don't trigger a destroy failure if we try to delete a container that does not
 | 	// Don't trigger a destroy failure if we try to delete a container that does not
 | ||||||
| 	// exist on the system. We're just a step ahead of ourselves in that case.
 | 	// exist on the system. We're just a step ahead of ourselves in that case.
 | ||||||
| 	//
 | 	//
 | ||||||
|  | @ -286,8 +288,6 @@ func (e *Environment) Destroy() error { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	e.SetState(environment.ProcessOfflineState) |  | ||||||
| 
 |  | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -313,17 +313,37 @@ func (e *Environment) followOutput() error { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	go func(reader io.ReadCloser) { | 
 | ||||||
|  | 	go e.scanOutput(reader) | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (e *Environment) scanOutput(reader io.ReadCloser) { | ||||||
| 	defer reader.Close() | 	defer reader.Close() | ||||||
| 		evts := e.Events() | 
 | ||||||
|  | 	events := e.Events() | ||||||
|  | 
 | ||||||
| 	err := system.ScanReader(reader, func(line string) { | 	err := system.ScanReader(reader, func(line string) { | ||||||
| 			evts.Publish(environment.ConsoleOutputEvent, line) | 		events.Publish(environment.ConsoleOutputEvent, line) | ||||||
| 	}) | 	}) | ||||||
|  | 
 | ||||||
| 	if err != nil && err != io.EOF { | 	if err != nil && err != io.EOF { | ||||||
| 		log.WithField("error", err).WithField("container_id", e.Id).Warn("error processing scanner line in console output") | 		log.WithField("error", err).WithField("container_id", e.Id).Warn("error processing scanner line in console output") | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
| 	}(reader) | 
 | ||||||
| 	return nil | 	// Return here if the server is offline or currently stopping.
 | ||||||
|  | 	if e.State() == environment.ProcessStoppingState || e.State() == environment.ProcessOfflineState { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Close the current reader before starting a new one, the defer will still run
 | ||||||
|  | 	// but it will do nothing if we already closed the stream.
 | ||||||
|  | 	_ = reader.Close() | ||||||
|  | 
 | ||||||
|  | 	// Start following the output of the server again.
 | ||||||
|  | 	go e.followOutput() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Pulls the image from Docker. If there is an error while pulling the image from the source
 | // Pulls the image from Docker. If there is an error while pulling the image from the source
 | ||||||
|  | @ -409,9 +429,11 @@ func (e *Environment) ensureImageExists(image string) error { | ||||||
| 	// I'm not sure what the best approach here is, but this will block execution until the image
 | 	// I'm not sure what the best approach here is, but this will block execution until the image
 | ||||||
| 	// is done being pulled, which is what we need.
 | 	// is done being pulled, which is what we need.
 | ||||||
| 	scanner := bufio.NewScanner(out) | 	scanner := bufio.NewScanner(out) | ||||||
|  | 
 | ||||||
| 	for scanner.Scan() { | 	for scanner.Scan() { | ||||||
| 		s := imagePullStatus{} | 		s := imagePullStatus{} | ||||||
| 		fmt.Println(scanner.Text()) | 		fmt.Println(scanner.Text()) | ||||||
|  | 
 | ||||||
| 		if err := json.Unmarshal(scanner.Bytes(), &s); err == nil { | 		if err := json.Unmarshal(scanner.Bytes(), &s); err == nil { | ||||||
| 			e.Events().Publish(environment.DockerImagePullStatus, s.Status+" "+s.Progress) | 			e.Events().Publish(environment.DockerImagePullStatus, s.Status+" "+s.Progress) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -82,8 +82,9 @@ func (e *Environment) Type() string { | ||||||
| // Set if this process is currently attached to the process.
 | // Set if this process is currently attached to the process.
 | ||||||
| func (e *Environment) SetStream(s *types.HijackedResponse) { | func (e *Environment) SetStream(s *types.HijackedResponse) { | ||||||
| 	e.mu.Lock() | 	e.mu.Lock() | ||||||
|  | 	defer e.mu.Unlock() | ||||||
|  | 
 | ||||||
| 	e.stream = s | 	e.stream = s | ||||||
| 	e.mu.Unlock() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Determine if the this process is currently attached to the container.
 | // Determine if the this process is currently attached to the container.
 | ||||||
|  | @ -98,6 +99,7 @@ func (e *Environment) Events() *events.EventBus { | ||||||
| 	e.eventMu.Do(func() { | 	e.eventMu.Do(func() { | ||||||
| 		e.emitter = events.New() | 		e.emitter = events.New() | ||||||
| 	}) | 	}) | ||||||
|  | 
 | ||||||
| 	return e.emitter | 	return e.emitter | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -174,12 +176,14 @@ func (e *Environment) Config() *environment.Configuration { | ||||||
| // Sets the stop configuration for the environment.
 | // Sets the stop configuration for the environment.
 | ||||||
| func (e *Environment) SetStopConfiguration(c api.ProcessStopConfiguration) { | func (e *Environment) SetStopConfiguration(c api.ProcessStopConfiguration) { | ||||||
| 	e.mu.Lock() | 	e.mu.Lock() | ||||||
|  | 	defer e.mu.Unlock() | ||||||
|  | 
 | ||||||
| 	e.meta.Stop = c | 	e.meta.Stop = c | ||||||
| 	e.mu.Unlock() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (e *Environment) SetImage(i string) { | func (e *Environment) SetImage(i string) { | ||||||
| 	e.mu.Lock() | 	e.mu.Lock() | ||||||
|  | 	defer e.mu.Unlock() | ||||||
|  | 
 | ||||||
| 	e.meta.Image = i | 	e.meta.Image = i | ||||||
| 	e.mu.Unlock() |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,10 +20,9 @@ import ( | ||||||
| //
 | //
 | ||||||
| // This process will also confirm that the server environment exists and is in a bootable
 | // This process will also confirm that the server environment exists and is in a bootable
 | ||||||
| // state. This ensures that unexpected container deletion while Wings is running does
 | // state. This ensures that unexpected container deletion while Wings is running does
 | ||||||
| // not result in the server becoming unbootable.
 | // not result in the server becoming un-bootable.
 | ||||||
| func (e *Environment) OnBeforeStart() error { | func (e *Environment) OnBeforeStart() error { | ||||||
| 	// Always destroy and re-create the server container to ensure that synced data from
 | 	// Always destroy and re-create the server container to ensure that synced data from the Panel is used.
 | ||||||
| 	// the Panel is usee.
 |  | ||||||
| 	if err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{RemoveVolumes: true}); err != nil { | 	if err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{RemoveVolumes: true}); err != nil { | ||||||
| 		if !client.IsErrNotFound(err) { | 		if !client.IsErrNotFound(err) { | ||||||
| 			return errors.WithMessage(err, "failed to remove server docker container during pre-boot") | 			return errors.WithMessage(err, "failed to remove server docker container during pre-boot") | ||||||
|  | @ -49,6 +48,7 @@ func (e *Environment) OnBeforeStart() error { | ||||||
| // call to OnBeforeStart().
 | // call to OnBeforeStart().
 | ||||||
| func (e *Environment) Start() error { | func (e *Environment) Start() error { | ||||||
| 	sawError := false | 	sawError := false | ||||||
|  | 
 | ||||||
| 	// If sawError is set to true there was an error somewhere in the pipeline that
 | 	// If sawError is set to true there was an error somewhere in the pipeline that
 | ||||||
| 	// got passed up, but we also want to ensure we set the server to be offline at
 | 	// got passed up, but we also want to ensure we set the server to be offline at
 | ||||||
| 	// that point.
 | 	// that point.
 | ||||||
|  | @ -235,7 +235,7 @@ func (e *Environment) Terminate(signal os.Signal) error { | ||||||
| 
 | 
 | ||||||
| 	sig := strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed") | 	sig := strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed") | ||||||
| 
 | 
 | ||||||
| 	if err := e.client.ContainerKill(context.Background(), e.Id, sig); err != nil { | 	if err := e.client.ContainerKill(context.Background(), e.Id, sig); err != nil && !client.IsErrNotFound(err) { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,8 +19,9 @@ var ErrNotAttached = errors.New("not attached to instance") | ||||||
| 
 | 
 | ||||||
| func (e *Environment) setStream(s *types.HijackedResponse) { | func (e *Environment) setStream(s *types.HijackedResponse) { | ||||||
| 	e.mu.Lock() | 	e.mu.Lock() | ||||||
|  | 	defer e.mu.Unlock() | ||||||
|  | 
 | ||||||
| 	e.stream = s | 	e.stream = s | ||||||
| 	e.mu.Unlock() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Sends the specified command to the stdin of the running container instance. There is no
 | // Sends the specified command to the stdin of the running container instance. There is no
 | ||||||
|  | @ -71,7 +72,7 @@ func (e *Environment) Readlog(lines int) ([]string, error) { | ||||||
| // Docker stores the logs for server output in a JSON format. This function will iterate over the JSON
 | // Docker stores the logs for server output in a JSON format. This function will iterate over the JSON
 | ||||||
| // that was read from the log file and parse it into a more human readable format.
 | // that was read from the log file and parse it into a more human readable format.
 | ||||||
| func (e *Environment) parseLogToStrings(b []byte) ([]string, error) { | func (e *Environment) parseLogToStrings(b []byte) ([]string, error) { | ||||||
| 	var hasError = false | 	hasError := false | ||||||
| 	var out []string | 	var out []string | ||||||
| 
 | 
 | ||||||
| 	scanner := bufio.NewScanner(bytes.NewReader(b)) | 	scanner := bufio.NewScanner(bytes.NewReader(b)) | ||||||
|  |  | ||||||
|  | @ -64,9 +64,11 @@ func (s *Server) StartEventListeners() { | ||||||
| 			// to terminate again.
 | 			// to terminate again.
 | ||||||
| 			if s.Environment.State() != environment.ProcessStoppingState { | 			if s.Environment.State() != environment.ProcessStoppingState { | ||||||
| 				s.Environment.SetState(environment.ProcessStoppingState) | 				s.Environment.SetState(environment.ProcessStoppingState) | ||||||
|  | 
 | ||||||
| 				go func() { | 				go func() { | ||||||
| 					s.Log().Warn("stopping server instance, violating throttle limits") | 					s.Log().Warn("stopping server instance, violating throttle limits") | ||||||
| 					s.PublishConsoleOutputFromDaemon("Your server is being stopped for outputting too much data in a short period of time.") | 					s.PublishConsoleOutputFromDaemon("Your server is being stopped for outputting too much data in a short period of time.") | ||||||
|  | 
 | ||||||
| 					// Completely skip over server power actions and terminate the running instance. This gives the
 | 					// Completely skip over server power actions and terminate the running instance. This gives the
 | ||||||
| 					// server 15 seconds to finish stopping gracefully before it is forcefully terminated.
 | 					// server 15 seconds to finish stopping gracefully before it is forcefully terminated.
 | ||||||
| 					if err := s.Environment.WaitForStop(config.Get().Throttles.StopGracePeriod, true); err != nil { | 					if err := s.Environment.WaitForStop(config.Get().Throttles.StopGracePeriod, true); err != nil { | ||||||
|  |  | ||||||
|  | @ -2,5 +2,5 @@ package system | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
| 	// The current version of this software.
 | 	// The current version of this software.
 | ||||||
| 	Version = "0.0.1" | 	Version = "v0.0.1" | ||||||
| ) | ) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user