From 7681f346bd80023b59dc0139e33e88a3f0d5510d Mon Sep 17 00:00:00 2001 From: rmanach Date: Fri, 4 Apr 2025 12:22:30 +0200 Subject: [PATCH] add docs --- connection/ssh_connection.go | 11 +++++++++++ deployers/commons.go | 21 +++++++++++++++++++++ deployers/nginx.go | 1 + deployers/swarm.go | 5 +++++ docker/client.go | 7 +++++++ main.go | 5 +++-- models/hm.go | 1 + models/project.go | 5 +++++ scheduler/scheduler.go | 10 ++++++++++ utils/utils.go | 1 + 10 files changed, 65 insertions(+), 2 deletions(-) diff --git a/connection/ssh_connection.go b/connection/ssh_connection.go index 6eb03d2..3204f26 100644 --- a/connection/ssh_connection.go +++ b/connection/ssh_connection.go @@ -31,6 +31,9 @@ var ( 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) { var newconn SSHConn @@ -75,6 +78,13 @@ func (c *SSHConn) Close() error { 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 { sshSession, err := c.client.NewSession() if err != nil { @@ -134,6 +144,7 @@ func (c *SSHConn) CopyFile(src, dest string) error { return nil } +// Execute executes a shell command remotly and returns the output. func (c *SSHConn) Execute(cmd string) (string, error) { sshSession, err := c.client.NewSession() if err != nil { diff --git a/deployers/commons.go b/deployers/commons.go index 2f9b33c..58e4a6c 100644 --- a/deployers/commons.go +++ b/deployers/commons.go @@ -30,6 +30,14 @@ const ( 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 { ctx context.Context 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) { d.fnCancel = fnCancel } @@ -75,6 +89,13 @@ func (d *deployer) Error() error { 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{} { chDone := make(chan struct{}) go func() { diff --git a/deployers/nginx.go b/deployers/nginx.go index 7cd2911..7059b7f 100644 --- a/deployers/nginx.go +++ b/deployers/nginx.go @@ -10,6 +10,7 @@ import ( "github.com/rs/zerolog/log" ) +// NginxDeployer handles the deployment of an Nginx configuration. type NginxDeployer struct { *deployer conn connection.IConnection diff --git a/deployers/swarm.go b/deployers/swarm.go index 98ffd2a..762b793 100644 --- a/deployers/swarm.go +++ b/deployers/swarm.go @@ -16,6 +16,7 @@ import ( 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 { *deployer conn connection.IConnection @@ -78,6 +79,10 @@ func (sd *SwarmDeployer) Clear() error { 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 { sd.processing.Store(true) defer sd.processing.Store(false) diff --git a/docker/client.go b/docker/client.go index b161a25..c007e00 100644 --- a/docker/client.go +++ b/docker/client.go @@ -14,6 +14,11 @@ type IClient interface { 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{} var _ IClient = (*Client)(nil) @@ -22,6 +27,8 @@ func NewClient() 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) { destInfo, err := os.Stat(dest) if err != nil { diff --git a/main.go b/main.go index 6ea224f..3c64b33 100644 --- a/main.go +++ b/main.go @@ -11,12 +11,13 @@ import ( "path" "sync" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "gitea.thegux.fr/hmdeploy/deployers" "gitea.thegux.fr/hmdeploy/docker" "gitea.thegux.fr/hmdeploy/models" "gitea.thegux.fr/hmdeploy/scheduler" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" ) const ( diff --git a/models/hm.go b/models/hm.go index 46e4edc..fab3554 100644 --- a/models/hm.go +++ b/models/hm.go @@ -19,6 +19,7 @@ type ( HMLXC map[string]*HMNetInfo ) +// HMMap handles all the informations of your home server instances. type HMMap struct { *HMNetInfo VM HMVM `json:"vm,omitempty"` diff --git a/models/project.go b/models/project.go index ad11128..2582ff7 100644 --- a/models/project.go +++ b/models/project.go @@ -47,6 +47,7 @@ func getFileInfo(baseDir, filePath string) (fs.FileInfo, error) { return fInf, nil } +// Project handles the details and file informations of your project. type Project struct { Name string `json:"name"` Dir string @@ -89,6 +90,10 @@ func (p *Project) validate() error { 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) { var p Project diff --git a/scheduler/scheduler.go b/scheduler/scheduler.go index 659e72a..476e3a0 100644 --- a/scheduler/scheduler.go +++ b/scheduler/scheduler.go @@ -25,6 +25,7 @@ const ( type FnJob func() error +// taskStore is a thread safe `Task` store. type taskStore struct { l sync.RWMutex tasks map[string]*Task @@ -62,6 +63,9 @@ func (ts *taskStore) len() int { 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 { Name string 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 { ctx context.Context fnCancel context.CancelFunc @@ -90,6 +96,10 @@ type Scheduler struct { 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 { ctxChild, fnCancel := context.WithCancel(ctx) s := Scheduler{ diff --git a/utils/utils.go b/utils/utils.go index c86f3ff..fd9a25c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -37,6 +37,7 @@ func addToArchive(tw *tar.Writer, filename string) error { return err } +// CreateArchive creates a gzip tar archive in the `destDir` path including `files`. func CreateArchive(destDir, name string, files ...string) (string, error) { now := time.Now().UTC() archivePath := filepath.Join(