add docs
This commit is contained in:
		
							parent
							
								
									40ff6408f3
								
							
						
					
					
						commit
						7681f346bd
					
				| @ -31,6 +31,9 @@ var ( | |||||||
| 	ErrSSHExecute         = errors.New("unable to execute command") | 	ErrSSHExecute         = errors.New("unable to execute command") | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // NewSSHConn instanciates a new SSH connection. | ||||||
|  | // The `privkey` arg is the path of private key where the corresponding | ||||||
|  | // public has been deployed on the `user` server. | ||||||
| func NewSSHConn(addr, user string, port int, privkey string) (SSHConn, error) { | func NewSSHConn(addr, user string, port int, privkey string) (SSHConn, error) { | ||||||
| 	var newconn SSHConn | 	var newconn SSHConn | ||||||
| 
 | 
 | ||||||
| @ -75,6 +78,13 @@ func (c *SSHConn) Close() error { | |||||||
| 	return c.client.Close() | 	return c.client.Close() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // CopyFile copies a local `src` file to the remote `dest` server. | ||||||
|  | // | ||||||
|  | // NOTE: for now the `dest` filepath (absolute or relative) does not | ||||||
|  | // create a push the file to the desired location. | ||||||
|  | // All the files are copied in the remote user HOME. | ||||||
|  | // | ||||||
|  | // TODO: create the `dest` if not exist. | ||||||
| func (c *SSHConn) CopyFile(src, dest string) error { | func (c *SSHConn) CopyFile(src, dest string) error { | ||||||
| 	sshSession, err := c.client.NewSession() | 	sshSession, err := c.client.NewSession() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -134,6 +144,7 @@ func (c *SSHConn) CopyFile(src, dest string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Execute executes a shell command remotly and returns the output. | ||||||
| func (c *SSHConn) Execute(cmd string) (string, error) { | func (c *SSHConn) Execute(cmd string) (string, error) { | ||||||
| 	sshSession, err := c.client.NewSession() | 	sshSession, err := c.client.NewSession() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | |||||||
| @ -30,6 +30,14 @@ const ( | |||||||
| 	GracefulTimeout = 10 * time.Second | 	GracefulTimeout = 10 * time.Second | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // Base struct of the deployers. | ||||||
|  | // It handles the main informations to build a deployer. | ||||||
|  | // | ||||||
|  | // "Inherited" deployers must implement three methods in order | ||||||
|  | // to satify the `IDeployer` contract: | ||||||
|  | //   - `Deploy() error`: run shell command to deploy the archive remotly | ||||||
|  | //   - `Build() error`: build the archive | ||||||
|  | //   - `Clear() error`: clean all the ressources locally and remotly | ||||||
| type deployer struct { | type deployer struct { | ||||||
| 	ctx      context.Context | 	ctx      context.Context | ||||||
| 	fnCancel context.CancelFunc | 	fnCancel context.CancelFunc | ||||||
| @ -63,6 +71,12 @@ func (d *deployer) setDone(err error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // SetCancellationFunc sets a context cancellation function for the deployer. | ||||||
|  | // | ||||||
|  | // If two deployers are related on the same context, one failed and you want | ||||||
|  | // to stop the execution of the others. Then, associate a cancel function | ||||||
|  | // for the deployer and the cancel func will be fired if error occurred | ||||||
|  | // during a deployment step. Stopping all the deployers. | ||||||
| func (d *deployer) SetCancellationFunc(fnCancel context.CancelFunc) { | func (d *deployer) SetCancellationFunc(fnCancel context.CancelFunc) { | ||||||
| 	d.fnCancel = fnCancel | 	d.fnCancel = fnCancel | ||||||
| } | } | ||||||
| @ -75,6 +89,13 @@ func (d *deployer) Error() error { | |||||||
| 	return d.errFlag | 	return d.errFlag | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Done returns a channel providing the shutdown or the termination | ||||||
|  | // of the deployer. | ||||||
|  | // | ||||||
|  | // If the context is done, it will wait until all the current actions are done | ||||||
|  | // for a graceful shutdown. It has a graceful timeout (see: `GracefulTimeout`). | ||||||
|  | // | ||||||
|  | // If the deployer is done, succeed or failed, it simply returns. | ||||||
| func (d *deployer) Done() <-chan struct{} { | func (d *deployer) Done() <-chan struct{} { | ||||||
| 	chDone := make(chan struct{}) | 	chDone := make(chan struct{}) | ||||||
| 	go func() { | 	go func() { | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ import ( | |||||||
| 	"github.com/rs/zerolog/log" | 	"github.com/rs/zerolog/log" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // NginxDeployer handles the deployment of an Nginx configuration. | ||||||
| type NginxDeployer struct { | type NginxDeployer struct { | ||||||
| 	*deployer | 	*deployer | ||||||
| 	conn connection.IConnection | 	conn connection.IConnection | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import ( | |||||||
| 
 | 
 | ||||||
| var ErrSwarmDeployerNoArchive = errors.New("no archive found to be deployed") | var ErrSwarmDeployerNoArchive = errors.New("no archive found to be deployed") | ||||||
| 
 | 
 | ||||||
|  | // SwarmDeployer handles the deployment of a Docker service on the swarm instance. | ||||||
| type SwarmDeployer struct { | type SwarmDeployer struct { | ||||||
| 	*deployer | 	*deployer | ||||||
| 	conn        connection.IConnection | 	conn        connection.IConnection | ||||||
| @ -78,6 +79,10 @@ func (sd *SwarmDeployer) Clear() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Build builds the archive with mandatory files to deploy a swarm service. | ||||||
|  | // | ||||||
|  | // After the build, the path of the local archive built is set in | ||||||
|  | // the `archivePath` field. | ||||||
| func (sd *SwarmDeployer) Build() error { | func (sd *SwarmDeployer) Build() error { | ||||||
| 	sd.processing.Store(true) | 	sd.processing.Store(true) | ||||||
| 	defer sd.processing.Store(false) | 	defer sd.processing.Store(false) | ||||||
|  | |||||||
| @ -14,6 +14,11 @@ type IClient interface { | |||||||
| 
 | 
 | ||||||
| var ErrDockerClientSave = errors.New("unable to save image into tar") | var ErrDockerClientSave = errors.New("unable to save image into tar") | ||||||
| 
 | 
 | ||||||
|  | // Client is a simple Docker client wrapping the local Docker daemon. | ||||||
|  | // It does not use the Docker API but instead shell command and collect the output. | ||||||
|  | // | ||||||
|  | // NOTE: for now, it's ok, it only needs one command so, no need to add a fat dedicated | ||||||
|  | // library with full Docker client API. | ||||||
| type Client struct{} | type Client struct{} | ||||||
| 
 | 
 | ||||||
| var _ IClient = (*Client)(nil) | var _ IClient = (*Client)(nil) | ||||||
| @ -22,6 +27,8 @@ func NewClient() Client { | |||||||
| 	return Client{} | 	return Client{} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Save saves the `imageName` (tag included) in tar format in the target directory: `dest`. | ||||||
|  | // The `dest` directory must exist with correct permissions. | ||||||
| func (c *Client) Save(imageName, dest string) (string, error) { | func (c *Client) Save(imageName, dest string) (string, error) { | ||||||
| 	destInfo, err := os.Stat(dest) | 	destInfo, err := os.Stat(dest) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								main.go
									
									
									
									
									
								
							| @ -11,12 +11,13 @@ import ( | |||||||
| 	"path" | 	"path" | ||||||
| 	"sync" | 	"sync" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/rs/zerolog" | ||||||
|  | 	"github.com/rs/zerolog/log" | ||||||
|  | 
 | ||||||
| 	"gitea.thegux.fr/hmdeploy/deployers" | 	"gitea.thegux.fr/hmdeploy/deployers" | ||||||
| 	"gitea.thegux.fr/hmdeploy/docker" | 	"gitea.thegux.fr/hmdeploy/docker" | ||||||
| 	"gitea.thegux.fr/hmdeploy/models" | 	"gitea.thegux.fr/hmdeploy/models" | ||||||
| 	"gitea.thegux.fr/hmdeploy/scheduler" | 	"gitea.thegux.fr/hmdeploy/scheduler" | ||||||
| 	"github.com/rs/zerolog" |  | ||||||
| 	"github.com/rs/zerolog/log" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ type ( | |||||||
| 	HMLXC map[string]*HMNetInfo | 	HMLXC map[string]*HMNetInfo | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // HMMap handles all the informations of your home server instances. | ||||||
| type HMMap struct { | type HMMap struct { | ||||||
| 	*HMNetInfo | 	*HMNetInfo | ||||||
| 	VM  HMVM  `json:"vm,omitempty"` | 	VM  HMVM  `json:"vm,omitempty"` | ||||||
|  | |||||||
| @ -47,6 +47,7 @@ func getFileInfo(baseDir, filePath string) (fs.FileInfo, error) { | |||||||
| 	return fInf, nil | 	return fInf, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Project handles the details and file informations of your project. | ||||||
| type Project struct { | type Project struct { | ||||||
| 	Name      string `json:"name"` | 	Name      string `json:"name"` | ||||||
| 	Dir       string | 	Dir       string | ||||||
| @ -89,6 +90,10 @@ func (p *Project) validate() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // ProjectFromDir instantiates a new project from a directory path. | ||||||
|  | // | ||||||
|  | // The directory path must refers to the path including the `.homeserver` dir not | ||||||
|  | // the `.homeserver` path itself. | ||||||
| func ProjectFromDir(dir string) (Project, error) { | func ProjectFromDir(dir string) (Project, error) { | ||||||
| 	var p Project | 	var p Project | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ const ( | |||||||
| 
 | 
 | ||||||
| type FnJob func() error | type FnJob func() error | ||||||
| 
 | 
 | ||||||
|  | // taskStore is a thread safe `Task` store. | ||||||
| type taskStore struct { | type taskStore struct { | ||||||
| 	l     sync.RWMutex | 	l     sync.RWMutex | ||||||
| 	tasks map[string]*Task | 	tasks map[string]*Task | ||||||
| @ -62,6 +63,9 @@ func (ts *taskStore) len() int { | |||||||
| 	return len(ts.tasks) | 	return len(ts.tasks) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Task represents an execution unit handle by the scheduler. | ||||||
|  | // | ||||||
|  | // Next field links to next executable tasks (tree kind). | ||||||
| type Task struct { | type Task struct { | ||||||
| 	Name   string | 	Name   string | ||||||
| 	Job    FnJob | 	Job    FnJob | ||||||
| @ -78,6 +82,8 @@ func NewTask(name string, job FnJob, next ...*Task) *Task { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Scheduler is a simple scheduler. | ||||||
|  | // Handling tasks and executes them, that's all. | ||||||
| type Scheduler struct { | type Scheduler struct { | ||||||
| 	ctx      context.Context | 	ctx      context.Context | ||||||
| 	fnCancel context.CancelFunc | 	fnCancel context.CancelFunc | ||||||
| @ -90,6 +96,10 @@ type Scheduler struct { | |||||||
| 	tasks   taskStore | 	tasks   taskStore | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // NewScheduler instantiates a new `Scheduler`. | ||||||
|  | // | ||||||
|  | // If you want to run tasks immediately after the scheduler creation, you can pass a list of | ||||||
|  | // `Task` with `tasks` argument. | ||||||
| func NewScheduler(ctx context.Context, capacity uint32, workers uint8, tasks ...*Task) *Scheduler { | func NewScheduler(ctx context.Context, capacity uint32, workers uint8, tasks ...*Task) *Scheduler { | ||||||
| 	ctxChild, fnCancel := context.WithCancel(ctx) | 	ctxChild, fnCancel := context.WithCancel(ctx) | ||||||
| 	s := Scheduler{ | 	s := Scheduler{ | ||||||
|  | |||||||
| @ -37,6 +37,7 @@ func addToArchive(tw *tar.Writer, filename string) error { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // CreateArchive creates a gzip tar archive in the `destDir` path including `files`. | ||||||
| func CreateArchive(destDir, name string, files ...string) (string, error) { | func CreateArchive(destDir, name string, files ...string) (string, error) { | ||||||
| 	now := time.Now().UTC() | 	now := time.Now().UTC() | ||||||
| 	archivePath := filepath.Join( | 	archivePath := filepath.Join( | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 rmanach
						rmanach