This commit refactors the CryptPad Kubernetes installer to be more dynamic and configurable structure. Key changes include: - **Dynamic Configuration**: The installer now generates its configuration based on parameters passed from the `.vsh` script, with sensible defaults for any unspecifie d values. - **Templated `config.js`**: Introduced a new `config.js` template to allow for greater flexibility and easier maintenance of the CryptPad configuration. - **Improved Code Structure**: The source code has been updated to be more modular and maintainable. - **Updated Documentation**: The `README.md` has been updated to include instructions on how to run the installer and customize the installation. Co-authored-by: Mahmoud-Emad <mahmmoud.hassanein@gmail.com>
190 lines
6.0 KiB
V
190 lines
6.0 KiB
V
module cryptpad
|
|
|
|
import incubaid.herolib.osal.core as osal
|
|
import incubaid.herolib.ui.console
|
|
import incubaid.herolib.installers.ulist
|
|
import time
|
|
|
|
const max_deployment_retries = 30
|
|
const deployment_check_interval_seconds = 2
|
|
|
|
//////////////////// following actions are not specific to instance of the object
|
|
|
|
// checks if a certain version or above is installed
|
|
fn installed() !bool {
|
|
installer := get()!
|
|
mut k8s := installer.kube_client
|
|
|
|
// Try to get the cryptpad deployment
|
|
deployments := k8s.get_deployments(installer.namespace) or {
|
|
// If we can't get deployments, it's not running
|
|
return false
|
|
}
|
|
|
|
// Check if cryptpad deployment exists
|
|
for deployment in deployments {
|
|
if deployment.name == 'cryptpad' {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// get the Upload List of the files
|
|
fn ulist_get() !ulist.UList {
|
|
// optionally build a UList which is all paths which are result of building, is then used e.g. in upload
|
|
return ulist.UList{}
|
|
}
|
|
|
|
// uploads to S3 server if configured
|
|
fn upload() ! {
|
|
// installers.upload(
|
|
// cmdname: 'cryptpad'
|
|
// source: '${gitpath}/target/x86_64-unknown-linux-musl/release/cryptpad'
|
|
// )!
|
|
}
|
|
|
|
fn install() ! {
|
|
console.print_header('Installing CryptPad...')
|
|
|
|
// Get installer config to access namespace
|
|
installer := get()!
|
|
mut k8s := installer.kube_client
|
|
configure()!
|
|
|
|
// 1. Check for dependencies.
|
|
console.print_info('Checking for kubectl...')
|
|
kubectl_installed()!
|
|
console.print_info('kubectl is installed and configured.')
|
|
|
|
// 4. Apply the YAML files using kubernetes client
|
|
console.print_info('Applying Gateway YAML file to the cluster...')
|
|
res1 := k8s.apply_yaml(installer.tfgw_cryptpad_path)!
|
|
if !res1.success {
|
|
return error('Failed to apply tfgw-cryptpad.yaml: ${res1.stderr}')
|
|
}
|
|
console.print_info('Gateway YAML file applied successfully.')
|
|
|
|
// 5. Verify TFGW deployments
|
|
verify_tfgw_deployment(tfgw_name: 'cryptpad-main', namespace: installer.namespace)!
|
|
verify_tfgw_deployment(tfgw_name: 'cryptpad-sandbox', namespace: installer.namespace)!
|
|
|
|
// 6. Apply Cryptpad YAML
|
|
console.print_info('Applying Cryptpad YAML file to the cluster...')
|
|
res2 := k8s.apply_yaml(installer.cryptpad_path)!
|
|
if !res2.success {
|
|
return error('Failed to apply cryptpad.yaml: ${res2.stderr}')
|
|
}
|
|
console.print_info('Cryptpad YAML file applied successfully.')
|
|
|
|
// 7. Verify deployment status
|
|
console.print_info('Verifying deployment status...')
|
|
mut is_running := false
|
|
for i in 0 .. max_deployment_retries {
|
|
if installed()! {
|
|
is_running = true
|
|
break
|
|
}
|
|
console.print_info('Waiting for CryptPad deployment to be ready... (${i + 1}/${max_deployment_retries})')
|
|
time.sleep(deployment_check_interval_seconds * time.second)
|
|
}
|
|
|
|
if is_running {
|
|
console.print_header('CryptPad installation successful!')
|
|
} else {
|
|
return error('CryptPad deployment failed to start.')
|
|
}
|
|
}
|
|
|
|
// params for verifying the generating of the FQDN using tfgw crd
|
|
@[params]
|
|
struct VerifyTfgwDeployment {
|
|
pub mut:
|
|
tfgw_name string // tfgw serivce generating the FQDN
|
|
namespace string // namespace name for cryptpad deployments/services
|
|
retry int = 30
|
|
}
|
|
|
|
// Function for verifying the generating of of the FQDN using tfgw crd
|
|
fn verify_tfgw_deployment(args VerifyTfgwDeployment) ! {
|
|
console.print_info('Verifying TFGW deployment for ${args.tfgw_name}...')
|
|
installer := get()!
|
|
mut k8s := installer.kube_client
|
|
mut is_fqdn_generated := false
|
|
|
|
for i in 0 .. args.retry {
|
|
// Use kubectl_exec for custom resource (TFGW) with jsonpath
|
|
result := k8s.kubectl_exec(
|
|
command: 'get tfgw ${args.tfgw_name} -n ${args.namespace} -o jsonpath="{.status.fqdn}"'
|
|
) or {
|
|
console.print_info('Waiting for FQDN to be generated for ${args.tfgw_name}... (${i + 1}/${args.retry})')
|
|
time.sleep(2 * time.second)
|
|
continue
|
|
}
|
|
|
|
if result.success && result.stdout != '' {
|
|
is_fqdn_generated = true
|
|
break
|
|
}
|
|
console.print_info('Waiting for FQDN to be generated for ${args.tfgw_name}... (${i + 1}/${args.retry})')
|
|
time.sleep(2 * time.second)
|
|
}
|
|
|
|
if !is_fqdn_generated {
|
|
console.print_stderr('Failed to get FQDN for ${args.tfgw_name}.')
|
|
// Use describe_resource to get detailed information about the TFGW resource
|
|
result := k8s.describe_resource(
|
|
resource: 'tfgw'
|
|
resource_name: args.tfgw_name
|
|
namespace: args.namespace
|
|
) or { return error('TFGW deployment failed for ${args.tfgw_name}.') }
|
|
console.print_stderr(result.stdout)
|
|
return error('TFGW deployment failed for ${args.tfgw_name}.')
|
|
}
|
|
console.print_info('TFGW deployment for ${args.tfgw_name} verified successfully.')
|
|
}
|
|
|
|
fn destroy() ! {
|
|
console.print_header('Destroying CryptPad...')
|
|
installer := get()!
|
|
mut k8s := installer.kube_client
|
|
|
|
console.print_debug('Attempting to delete namespace: ${installer.namespace}')
|
|
|
|
// Delete the namespace using kubernetes client
|
|
result := k8s.delete_resource('namespace', installer.namespace, '') or {
|
|
console.print_stderr('Failed to delete namespace ${installer.namespace}: ${err}')
|
|
return error('Failed to delete namespace ${installer.namespace}: ${err}')
|
|
}
|
|
|
|
console.print_debug('Delete command completed. Exit code: ${result.exit_code}, Success: ${result.success}')
|
|
|
|
if !result.success {
|
|
// Namespace not found is OK - it means it's already deleted
|
|
if result.stderr.contains('NotFound') {
|
|
console.print_info('Namespace ${installer.namespace} does not exist (already deleted).')
|
|
} else {
|
|
console.print_stderr('Failed to delete namespace ${installer.namespace}: ${result.stderr}')
|
|
return error('Failed to delete namespace ${installer.namespace}: ${result.stderr}')
|
|
}
|
|
} else {
|
|
console.print_info('Namespace ${installer.namespace} deleted successfully.')
|
|
}
|
|
}
|
|
|
|
fn kubectl_installed() ! {
|
|
// Check if kubectl command exists
|
|
if !osal.cmd_exists('kubectl') {
|
|
return error('kubectl is not installed. Please install it to continue.')
|
|
}
|
|
|
|
// Check if kubectl is configured to connect to a cluster
|
|
installer := get()!
|
|
mut k8s := installer.kube_client
|
|
|
|
if !k8s.test_connection()! {
|
|
return error('kubectl is not configured to connect to a Kubernetes cluster. Please check your kubeconfig.')
|
|
}
|
|
}
|