Compare commits

...

2 commits

Author SHA1 Message Date
3f0a0adddd feat: add base structure for commands
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-11-26 16:37:22 +01:00
44bb2763b0 feat: add scaffold for operations (command design pattern) 2023-11-26 16:37:22 +01:00
26 changed files with 298 additions and 91 deletions

View file

@ -8,6 +8,8 @@ require "./config"
require "./fzf" require "./fzf"
require "./version" require "./version"
require "./operations"
module GX module GX
class Cli class Cli
Log = ::Log.for("cli") Log = ::Log.for("cli")
@ -149,8 +151,13 @@ module GX
return false return false
end end
alias FsTuple = NamedTuple(
filesystem: Models::Filesystems::AbstractConfig,
ansi_name: String
)
def choose_filesystem() def choose_filesystem()
names_display = {} of String => NamedTuple(filesystem: Models::AbstractFilesystemConfig, ansi_name: String) names_display = {} of String => FsTuple
config_root = @config.root config_root = @config.root
return if config_root.nil? return if config_root.nil?

View file

@ -26,7 +26,6 @@ module GX
record AddArgs, name : String, path : String record AddArgs, name : String, path : String
record DelArgs, name : String record DelArgs, name : String
# getter filesystems : Array(Models::AbstractFilesystemConfig)
getter home_dir : String getter home_dir : String
getter root : Models::RootConfig? getter root : Models::RootConfig?
@ -44,7 +43,7 @@ module GX
@auto_open = false @auto_open = false
@mode = Mode::Mount @mode = Mode::Mount
@filesystems = [] of Models::AbstractFilesystemConfig @filesystems = [] of Models::Filesystems::AbstractConfig
@path = nil @path = nil
@args = NoArgs @args = NoArgs
@ -62,10 +61,10 @@ module GX
possible_files.each do |file_path| possible_files.each do |file_path|
if File.exists?(file_path) if File.exists?(file_path)
Log.info { "Configuration file found: #{file_path}" } Log.info { "Configuration file found: #{file_path}" } if @verbose
return file_path if File.exists?(file_path) return file_path if File.exists?(file_path)
else else
Log.debug { "Configuration file not found: #{file_path}" } Log.debug { "Configuration file not found: #{file_path}" } if @verbose
end end
end end

View file

@ -5,7 +5,8 @@
require "./models/root_config" require "./models/root_config"
require "./models/global_config" require "./models/global_config"
require "./models/gocryptfs_config" require "./models/filesystems/gocryptfs_config"
require "./models/sshfs_config" require "./models/filesystems/sshfs_config"
require "./models/httpdirfs_config" require "./models/filesystems/httpdirfs_config"
require "./models/abstract_filesystem_config" require "./models/filesystems/abstract_config"
require "./models/exceptions"

View file

@ -1,56 +0,0 @@
module GX::Models::Concerns
module Base
def mounted?() : Bool
mount_point_safe = @mount_point
raise InvalidMountpointError.new("Invalid mountpoint value") if mount_point_safe.nil?
`mount`.includes?(" on #{mount_point_safe} type ")
end
def umount() : Nil
mount_point_safe = @mount_point
raise InvalidMountpointError.new("Invalid mountpoint value") if mount_point_safe.nil?
system("fusermount -u #{mount_point_safe.shellescape}")
fusermount_status = $?
if fusermount_status.success?
puts "Models #{name} is now closed.".colorize(:green)
else
puts "Error: Unable to unmount filesystem #{name} (exit code: #{fusermount_status.exit_code}).".colorize(:red)
end
end
def mount_point?()
!mount_point.nil?
end
def mount()
_mount_wrapper() do
_mount_action
end
end
def _mount_wrapper(&block) : Nil
mount_point_safe = mount_point
return if mount_point_safe.nil?
Dir.mkdir_p(mount_point_safe) unless Dir.exists?(mount_point_safe)
if mounted?
puts "Already mounted. Skipping.".colorize(:yellow)
return
end
result_status = yield
if result_status.success?
puts "Models #{name} is now available on #{mount_point_safe}".colorize(:green)
else
puts "Error mounting the vault".colorize(:red)
return
end
end
end
end

15
src/models/exceptions.cr Normal file
View file

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "yaml"
module GX::Models
class InvalidFilesystemError < Exception
end
class InvalidMountpointError < Exception
end
end

View file

@ -5,14 +5,8 @@
require "yaml" require "yaml"
module GX::Models module GX::Models::Filesystems
class InvalidFilesystemError < Exception abstract class AbstractConfig
end
class InvalidMountpointError < Exception
end
abstract class AbstractFilesystemConfig
include YAML::Serializable include YAML::Serializable
# include YAML::Serializable::Strict # include YAML::Serializable::Strict

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
module GX::Models::Concerns
module Mount
def mount()
_mount_wrapper() do
_mount_action
end
end
end
end

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
module GX::Models::Concerns
module MountPoint
def mount_point?()
!mount_point.nil?
end
end
end

View file

@ -0,0 +1,29 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
module GX::Models::Concerns
module MountWrapper
def _mount_wrapper(&block) : Nil
mount_point_safe = mount_point
return if mount_point_safe.nil?
Dir.mkdir_p(mount_point_safe) unless Dir.exists?(mount_point_safe)
if mounted?
puts "Already mounted. Skipping.".colorize(:yellow)
return
end
result_status = yield
if result_status.success?
puts "Models #{name} is now available on #{mount_point_safe}".colorize(:green)
else
puts "Error mounting the vault".colorize(:red)
return
end
end
end
end

View file

@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
module GX::Models::Concerns
module Mounted
def mounted?() : Bool
mount_point_safe = @mount_point
raise InvalidMountpointError.new("Invalid mountpoint value") if mount_point_safe.nil?
`mount`.includes?(" on #{mount_point_safe} type ")
end
end
end

View file

@ -0,0 +1,23 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
module GX::Models::Concerns
module Umount
def umount() : Nil
mount_point_safe = @mount_point
raise InvalidMountpointError.new("Invalid mountpoint value") if mount_point_safe.nil?
system("fusermount -u #{mount_point_safe.shellescape}")
fusermount_status = $?
if fusermount_status.success?
puts "Models #{name} is now closed.".colorize(:green)
else
puts "Error: Unable to unmount filesystem #{name} (exit code: #{fusermount_status.exit_code}).".colorize(:red)
end
end
end
end

View file

@ -4,14 +4,22 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "shellwords" require "shellwords"
require "./abstract_filesystem_config" require "./abstract_config"
require "./concerns/base" require "./concerns/mount_wrapper"
require "./concerns/mounted"
require "./concerns/mount"
require "./concerns/umount"
require "./concerns/mount_point"
module GX::Models module GX::Models::Filesystems
class GoCryptFSConfig < AbstractFilesystemConfig class GoCryptFSConfig < AbstractConfig
getter encrypted_path : String = "" getter encrypted_path : String = ""
include Concerns::Base include Concerns::Mount
include Concerns::Mounted
include Concerns::MountPoint
include Concerns::MountWrapper
include Concerns::Umount
def _mounted_prefix() def _mounted_prefix()
"#{encrypted_path}" "#{encrypted_path}"

View file

@ -4,14 +4,23 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "shellwords" require "shellwords"
require "./abstract_filesystem_config"
require "./concerns/base"
module GX::Models require "./abstract_config"
class HttpDirFSConfig < AbstractFilesystemConfig require "./concerns/mount_wrapper"
require "./concerns/mounted"
require "./concerns/mount"
require "./concerns/umount"
require "./concerns/mount_point"
module GX::Models::Filesystems
class HttpDirFSConfig < AbstractConfig
getter url : String = "" getter url : String = ""
include Concerns::Base include Concerns::Mount
include Concerns::Mounted
include Concerns::MountPoint
include Concerns::MountWrapper
include Concerns::Umount
def _mounted_prefix() def _mounted_prefix()
"httpdirfs" "httpdirfs"

View file

@ -4,17 +4,25 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "shellwords" require "shellwords"
require "./abstract_filesystem_config" require "./abstract_config"
require "./concerns/base" require "./concerns/mount_wrapper"
require "./concerns/mounted"
require "./concerns/mount"
require "./concerns/umount"
require "./concerns/mount_point"
module GX::Models module GX::Models::Filesystems
class SshFSConfig < AbstractFilesystemConfig class SshFSConfig < AbstractConfig
getter remote_path : String = "" getter remote_path : String = ""
getter remote_user : String = "" getter remote_user : String = ""
getter remote_host : String = "" getter remote_host : String = ""
getter remote_port : String = "22" getter remote_port : String = "22"
include Concerns::Base include Concerns::Mount
include Concerns::Mounted
include Concerns::MountPoint
include Concerns::MountWrapper
include Concerns::Umount
def _mounted_prefix() def _mounted_prefix()
"#{@remote_user}@#{@remote_host}:#{@remote_path}" "#{@remote_user}@#{@remote_host}:#{@remote_path}"

View file

@ -4,7 +4,7 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "yaml" require "yaml"
require "./abstract_filesystem_config" require "./filesystems/abstract_config"
module GX::Models module GX::Models
class InvalidEnvironmentError < Exception class InvalidEnvironmentError < Exception

View file

@ -4,7 +4,7 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "yaml" require "yaml"
require "./abstract_filesystem_config" require "./filesystems/abstract_config"
require "./global_config" require "./global_config"
module GX::Models module GX::Models
@ -35,7 +35,7 @@ module GX::Models
getter global : GlobalConfig getter global : GlobalConfig
@[YAML::Field(key: "filesystems")] @[YAML::Field(key: "filesystems")]
getter filesystems : Array(AbstractFilesystemConfig) getter filesystems : Array(Filesystems::AbstractConfig)
end end
end end

2
src/operations.cr Normal file
View file

@ -0,0 +1,2 @@
require "./operations/*"

View file

@ -0,0 +1,8 @@
module GX
module Operations
abstract class AbstractCommand
abstract def execute()
end
end
end

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class CreateCommand < AbstractCommand
def execute()
raise NotImplementedError.new("CreateCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class DeleteCommand < AbstractCommand
def execute()
raise NotImplementedError.new("DeleteCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class EditCommand < AbstractCommand
def execute()
raise NotImplementedError.new("EditCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class ListCommand < AbstractCommand
def execute()
raise NotImplementedError.new("ListCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class MountCommand < AbstractCommand
def execute()
raise NotImplementedError.new("MountCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class SelectCommand < AbstractCommand
def execute()
raise NotImplementedError.new("SelectCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Filesystems
class UmountCommand < AbstractCommand
def execute()
raise NotImplementedError.new("UmountCommand is not Implemented")
end
end
end

View file

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "../abstract_command"
module GX::Operations::Global
class EditCommand < AbstractCommand
def execute()
raise NotImplementedError.new("EditCommand is not Implemented")
end
end
end