teuton-get 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+
2
+ # Teuton-Get
3
+
4
+ * Find and download _Teuton Tests_ from remote or local repositories.
5
+ * Create _Teuton Test_ repository.
6
+
7
+ ![logo](./docs/images/logo.png)
8
+
9
+ # Installation
10
+
11
+ 1. Install Ruby on your system.
12
+ 1. `gem install teuton-get`, to install **teuton-get** gem.
13
+
14
+ # Use
15
+
16
+ * At first, create config file with `teutonget init`.
17
+ * Then, search tests with `teutonget search FILTER`. Example: `teutonget search linux`, will show a list with "linux" related tests.
18
+ * `teutonget download REPONAME:TESTPATH`
19
+
20
+ # Contact
21
+
22
+ * **Email**: `teuton.software@protonmail.com`
23
+
24
+ # Documentation
25
+
26
+ * [Settings](docs/settings.md)
27
+ * [Get](docs/get.md)
28
+ * [Repository](docs/repo.md)
29
+ * [Commands](docs/commands.md)
data/bin/teutonget ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require "teuton-get/cli"
5
+
6
+ CLI.start(ARGV)
data/docs/commands.md ADDED
@@ -0,0 +1,16 @@
1
+
2
+ # Command reference
3
+
4
+ Run `teutonget` to show available commands:
5
+ ```
6
+ Commands:
7
+ teutonget create-info [TEST-PATH] # Create info data for Teuton test
8
+ teutonget create-repo [SOURCE-DIR] # Create repo into SOURCE directory
9
+ teutonget download REPONAME@TESTNAME # Download Teuton test
10
+ teutonget help [COMMAND] # Describe available commands or one specific command
11
+ teutonget init # Create ini config file
12
+ teutonget refresh # Synchronize list of tests available.
13
+ teutonget repos # Show repo list
14
+ teutonget search [REPONAME@]FILTER # Search Teuton test with FILTER
15
+ teutonget version # Show the program version
16
+ ```
data/docs/get.md ADDED
@@ -0,0 +1,50 @@
1
+ [<<back](../README.md)
2
+
3
+ # Get
4
+
5
+ Find and download local or remote files.
6
+
7
+ ## Search
8
+
9
+ At first we need to locate the files according to some criterios.
10
+
11
+ * `teutonget search FILTER` is used to find files with FILTER criterio.
12
+
13
+ Example:
14
+
15
+ ```
16
+ ❯ teutonget search debian
17
+ (3) teuton.en:en/systems.1/03-debian-conf
18
+ (2) teuton.en:en/systems.2/02-debian-basic-configuration
19
+ ```
20
+
21
+ ## Info
22
+
23
+ Show info about test. Example:
24
+ ```
25
+ ❯ teutonget info teuton.en:systems.1/03-debian-conf
26
+
27
+ name : Debian configuration
28
+ author : dvarrui
29
+ date : 2020-09-06
30
+ desc :
31
+ tags : Debian, configuration
32
+ files : README.md, config.yaml, debian.rb, network.rb, start.rb
33
+ ```
34
+
35
+ ## Download
36
+
37
+ Download test by TESTID. Example:
38
+
39
+ ```
40
+ ❯ teutonget download teuton.en:systems.1/03-debian-conf
41
+
42
+ ==> Downloading...
43
+ ==> File: README.md
44
+ ==> File: config.yaml
45
+ ==> File: debian.rb
46
+ ==> File: network.rb
47
+ ==> File: start.rb
48
+ ```
49
+
50
+ Test files will be downloaded into `systems.1_03-debian-conf` local directory.
data/docs/repo.md ADDED
@@ -0,0 +1,68 @@
1
+ [<< back](../README.md)
2
+
3
+ # Repository
4
+
5
+ Manage repositories: configure and creation.
6
+
7
+ ## Create info
8
+
9
+ Teuton test files are located into remote machines. Every Teuton test requires
10
+ a special info file that acts as manifest or test metadata.
11
+
12
+ Supose we are on remote machine (Repository host).
13
+
14
+ * Run `teutonget create-info PATH/TO/TEUTON/TEST/DIR` to create Teuton test info.
15
+
16
+ Example:
17
+ ```
18
+ ❯ teutonget create-info 03-debian-mkdir-command
19
+ name? 03-debian-mkdir-command
20
+ author? david
21
+ date? 2022-08-29
22
+ desc? Practice basic commands into Debian host.
23
+ tags? practice,basic,command,debian,host
24
+ ```
25
+
26
+ Every Teuton test that you want to be downdable, requires test info file (tt-info.yaml).
27
+
28
+ ## Create repository
29
+
30
+ We need to summarize all our test information into repo info file (tt-repo-yaml).
31
+
32
+ * Go to your remote repository server host.
33
+ * Move to your repository root directory.
34
+ * Then run `teutonget create-repo`.
35
+
36
+ Example:
37
+ ```
38
+ ❯ teutonget create-repo
39
+
40
+ ==> Creating repository
41
+ Reading systems.1/01-windows-conf
42
+ Reading systems.1/02-opensuse-conf
43
+ Reading systems.1/03-debian-conf
44
+ Reading systems.1/04-winserver-conf
45
+ Reading systems.2/01-install-w10-vbox
46
+ Reading systems.2/02-debian-basic-configuration
47
+ Reading systems.2/03-debian-mkdir-command
48
+ Created file ./tt-repo.yaml with 7 tests.
49
+ ```
50
+
51
+ ## Configure remote repository
52
+
53
+ Finaly we have to configure the new remote repo.
54
+
55
+ * Go to your local host. Where your will download tests.
56
+ * Modify repo config file (`HOME/.config/teuton/repos.ini`)
57
+ * Add your new remote repo.
58
+
59
+ Example:
60
+
61
+ ```
62
+ [REPONAME]
63
+ description = WRITE REPO DESCRIPTION
64
+ URL = https://write.here/your/repo/url
65
+ enable = true
66
+ ```
67
+
68
+ * Run `teutonget repos` to check configuration.
data/docs/settings.md ADDED
@@ -0,0 +1,40 @@
1
+ [<< back](../README.md)
2
+
3
+ # Settings
4
+
5
+ * `teutonget init`, the first time it is necessary to run this command to create the configuration files. From now on you can use the tool.
6
+
7
+ ```
8
+ ==> Creating configuration files
9
+ ✔ Create dir : /home/quigon/.config/teuton
10
+ ✔ Create file : /home/quigon/.config/teuton/repos.ini
11
+
12
+ ==> Refreshing active repos
13
+ Repo teuton.en (6 tests)
14
+ Repo teuton.es (2 tests)
15
+ ```
16
+
17
+ > Config files are saved into `HOME/.config/teuton` folder.
18
+
19
+ * `teutonget repos` will show repositories list.
20
+
21
+ ```
22
+ Repository list
23
+ +-+---------+------------------------------------+
24
+ |E|NAME |DESCRIPTION |
25
+ +-+---------+------------------------------------+
26
+ |✔|teuton.en|Main Teuton repo |
27
+ |✔|teuton.es|Repositorio principal de Teuton Test|
28
+ +-+---------+------------------------------------+
29
+ Config: /home/quigon/.config/teuton/repos.ini
30
+ ```
31
+
32
+ > Repositories are configured into HOME/.config/teuton/repos.ini
33
+
34
+ * `teutonget refresh`, from time to time it is advisable to refresh the information of the repositories using this command.
35
+
36
+ ```
37
+ ==> Refreshing active repos
38
+ Repo teuton.en (6 tests)
39
+ Repo teuton.es (2 tests)
40
+ ```
@@ -0,0 +1,9 @@
1
+ class Environment
2
+ def initialize(reader = nil)
3
+ @env = ENV
4
+ end
5
+
6
+ def get(key)
7
+ @env[key]
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ require "singleton"
2
+ require_relative "application/environment"
3
+
4
+ class Application
5
+ include Singleton
6
+
7
+ CONFIGFILE = "repos.ini"
8
+ INDEXFILENAME = "tt-repo.yaml"
9
+ INFOFILENAME = "tt-info.yaml"
10
+ MAGICNUMBER = 999
11
+ SEPARATOR = ":"
12
+
13
+ def initialize
14
+ @env = Environment.new
15
+ init_params
16
+ end
17
+
18
+ def get(key)
19
+ return @env.get(key) if key.instance_of? String
20
+
21
+ @params[key] || "NODATA"
22
+ end
23
+
24
+ private
25
+
26
+ def init_params
27
+ @params = {}
28
+ home = get("HOME")
29
+ config_dirpath = File.join(home, ".config", "teuton")
30
+ @params[:config_dirpath] = config_dirpath
31
+
32
+ filename = Application::CONFIGFILE
33
+ config_filepath = File.join(config_dirpath, filename)
34
+ @params[:config_filepath] = config_filepath
35
+
36
+ cache_dirpath = File.join(config_dirpath, "cache")
37
+ @params[:cache_dirpath] = cache_dirpath
38
+ end
39
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "application"
5
+ require_relative "version"
6
+ require_relative "../teuton-get"
7
+
8
+ class CLI < Thor
9
+ map ["h", "-h", "--help"] => "help"
10
+
11
+ map ["v", "-v", "--version"] => "version"
12
+ desc "version", "Show the program version"
13
+
14
+ def version
15
+ puts "#{Version::EXECUTABLE} (version #{Version::VERSION})"
16
+ end
17
+
18
+ map ["ci", "-ci", "--create-info"] => "create_info"
19
+ desc "create-info [DIRPATH]", "Create info data for Teuton test"
20
+ long_desc <<-LONGDESC
21
+ Create info data for Teuton test.
22
+ LONGDESC
23
+ def create_info(testpath)
24
+ TeutonGet.create_info(testpath)
25
+ end
26
+
27
+ map ["i", "-i", "--info"] => "info"
28
+ desc "info TESTID", "Show info data for Teuton test"
29
+ long_desc <<-LONGDESC
30
+ Show info data for Teuton test.
31
+ LONGDESC
32
+ def info(test_id)
33
+ TeutonGet.show_info(test_id)
34
+ end
35
+
36
+ map ["cr", "-cr", "--create-repo"] => "create_repo"
37
+ desc "create-repo", "Create repo into current directory"
38
+ long_desc <<-LONGDESC
39
+ Create index from SOURCE directory.
40
+ LONGDESC
41
+ def create_repo
42
+ TeutonGet.create_repo(".")
43
+ end
44
+
45
+ map ["i", "-i", "--init"] => "init"
46
+ desc "init", "Create ini config file"
47
+ long_desc <<-LONGDESC
48
+ Create ini config file
49
+ LONGDESC
50
+ def init
51
+ TeutonGet.init
52
+ end
53
+
54
+ map ["--repos"] => "repos"
55
+ desc "repos", "Show repo list"
56
+ long_desc <<-LONGDESC
57
+ Show repo list.
58
+ LONGDESC
59
+ def repos
60
+ TeutonGet.show_repo_list
61
+ end
62
+
63
+ map ["r", "-r", "--refresh"] => "refresh"
64
+ desc "refresh", "Synchronize list of available tests."
65
+ long_desc <<-LONGDESC
66
+ Synchronize list of tests available.
67
+ LONGDESC
68
+ def refresh
69
+ TeutonGet.refresh
70
+ end
71
+
72
+ map ["s", "-s", "--search"] => "search"
73
+ desc "search [REPONAME:]FILTER", "Search Teuton test with FILTER"
74
+ long_desc <<-LONGDESC
75
+ Search Teuton test with FILTER.
76
+ LONGDESC
77
+ def search(filter)
78
+ TeutonGet.search(filter)
79
+ end
80
+
81
+ map ["d", "-d", "--download"] => "download"
82
+ desc "download TESTID", "Download Teuton test"
83
+ long_desc <<-LONGDESC
84
+ Download Teuton test. Example: "teutonget main@system/opensuse"
85
+ LONGDESC
86
+ def download(testname)
87
+ TeutonGet.download(testname)
88
+ end
89
+ end
@@ -0,0 +1,71 @@
1
+ require "fileutils"
2
+ require_relative "writer/file_writer"
3
+ require_relative "writer/terminal_writer"
4
+ require_relative "reader/inifile_reader"
5
+ require_relative "reader/url_reader"
6
+ require_relative "repo/repo_config"
7
+ require_relative "repo/repo_data"
8
+
9
+ class Downloader
10
+ def initialize
11
+ @dev = TerminalWriter.new
12
+ @repo_config = RepoConfig.new_by_default.data
13
+ cache_dirpath = Application.instance.get(:cache_dirpath)
14
+ @repo_data = RepoData.new(
15
+ config_reader: IniFileReader.new,
16
+ progress_writer: TerminalWriter.new,
17
+ cache_dirpath: cache_dirpath
18
+ )
19
+ end
20
+
21
+ def run(id)
22
+ reponame, testpath = id.split(Application::SEPARATOR)
23
+
24
+ repo_url, status = get_url_for reponame
25
+ unless status == :ok
26
+ @dev.writeln " #{status}"
27
+ return false
28
+ end
29
+
30
+ files, status = get_files_for_test id
31
+ unless status == :ok
32
+ @dev.writeln " #{status}"
33
+ return false
34
+ end
35
+
36
+ download(reponame, repo_url, testpath, files)
37
+ end
38
+
39
+ private
40
+
41
+ def get_url_for(reponame)
42
+ repo = @repo_config[reponame]
43
+ return nil, "ERROR: undefined repo name!" if repo.nil?
44
+ url = repo["URL"]
45
+ return nil, "ERROR: undefined repo URL!" if url.nil?
46
+ [url, :ok]
47
+ end
48
+
49
+ def get_files_for_test(id)
50
+ testdata = @repo_data.get(id)
51
+ return [], "ERROR: not found!" if testdata.nil?
52
+ files = testdata["files"]
53
+ return [], "WARN: files no defined!" if files.nil?
54
+ return [], "WARN: 0 files defined!" if files.size.zero?
55
+ [files, :ok]
56
+ end
57
+
58
+ def download(reponame, url, path, files)
59
+ @dev.writeln "==> Downloading #{path} from #{reponame}...", color: :light_yellow
60
+ localpath = path.tr("/", "_")
61
+ FileUtils.mkdir(localpath) unless File.exist? localpath
62
+ files.each do |filename|
63
+ @dev.writeln "==> File: #{filename} ", color: :white
64
+ uri = "#{url}/#{path}/#{filename}"
65
+ out = FileWriter.new
66
+ out.open(File.join(localpath, filename))
67
+ out.write(URLReader.new(uri).read)
68
+ out.close
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,11 @@
1
+ # version 1
2
+
3
+ [teuton.en]
4
+ description = Main Teuton repo
5
+ URL = https://raw.githubusercontent.com/teuton-software/teuton-tests/master/en
6
+ enable = true
7
+
8
+ [teuton.es]
9
+ description = Repositorio principal de Teuton Test
10
+ URL = https://raw.githubusercontent.com/teuton-software/teuton-tests/master/es
11
+ enable = true
@@ -0,0 +1,21 @@
1
+ #####################################################
2
+ # DONT CHANGE THESE ATTRIBUTES (Created by teutonget)
3
+ #
4
+ version: 1
5
+ type: teutontest
6
+
7
+ #########################################################
8
+ # UPDATE THESE VALUES (Keep names and update their values
9
+ #
10
+ name: <%=@data[:name] + "\n"%>
11
+ author: <%=@data[:author] + "\n"%>
12
+ date: <%=@data[:date] + "\n"%>
13
+ desc: <%=@data[:desc] + "\n"%>
14
+ tags:
15
+ <% @data[:tags].each do |tag| %>
16
+ - <%=tag.strip + "\n"%>
17
+ <% end %>
18
+
19
+ ###################################
20
+ # Custom attributes after this line
21
+ #
@@ -0,0 +1,24 @@
1
+ require "inifile"
2
+ require_relative "reader"
3
+
4
+ class IniFileReader < Reader
5
+ def initialize(filepath = "")
6
+ @filepath = filepath
7
+ end
8
+
9
+ def source
10
+ @filepath
11
+ end
12
+
13
+ def read(filepath = :default)
14
+ @filepath = filepath unless filepath == :default
15
+ return {} unless File.exist? @filepath
16
+
17
+ inifile = IniFile.load(@filepath)
18
+ data = {}
19
+ inifile.sections.each do |section|
20
+ data[section] = inifile[section]
21
+ end
22
+ data
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "reader"
2
+
3
+ class LinuxEnvironmentReader < Reader
4
+ def initialize(command)
5
+ @command = command
6
+ end
7
+
8
+ def read
9
+ lines = @command.split("\n")
10
+ data = {}
11
+ lines.sort.each do |line|
12
+ items = line.split("=")
13
+ if items.size == 2
14
+ data[items[0].strip] = items[1].strip
15
+ end
16
+ end
17
+ data
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ class Reader
2
+ def source
3
+ raise "Define method"
4
+ end
5
+
6
+ def read
7
+ raise "Define method"
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require "net/http"
2
+ require "uri"
3
+ require_relative "reader"
4
+
5
+ class URLReader < Reader
6
+ def initialize(url = "")
7
+ @url = url
8
+ end
9
+
10
+ def source
11
+ @url
12
+ end
13
+
14
+ def read(url = :default)
15
+ @url = url unless url == :default
16
+ Net::HTTP.get(URI.parse(@url))
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require "date"
2
+ require "yaml"
3
+ require_relative "reader"
4
+
5
+ class YamlReader < Reader
6
+ def initialize(filepath = "")
7
+ @filepath = filepath
8
+ end
9
+
10
+ def source
11
+ @filepath
12
+ end
13
+
14
+ def read(filepath = :default)
15
+ @filepath = filepath unless filepath == :default
16
+ return {} unless File.exist? @filepath
17
+
18
+ content = File.open(@filepath)
19
+ YAML.safe_load(
20
+ content,
21
+ permitted_classes: [Array, Date, Hash, Symbol]
22
+ )
23
+ end
24
+ end
@@ -0,0 +1,71 @@
1
+ require_relative "../application"
2
+ require_relative "../writer/terminal_writer"
3
+ require_relative "../reader/yaml_reader"
4
+ require "erb"
5
+ require "tty-prompt"
6
+
7
+ class LocalInfo
8
+ def initialize(dev = TerminalWriter.new)
9
+ @dev = dev
10
+ @data = {}
11
+ end
12
+
13
+ def default_create(testpath)
14
+ set_default_data(testpath)
15
+ create(testpath)
16
+ end
17
+
18
+ def user_create(testpath)
19
+ ask_data(testpath)
20
+ create(testpath)
21
+ end
22
+
23
+ def read(filepath)
24
+ dirpath = File.dirname(filepath)
25
+ @dev.writeln " Reading #{dirpath}"
26
+ data = YamlReader.new(filepath).read
27
+
28
+ filepaths = Dir.glob("#{dirpath}/**/*.*")
29
+ files = filepaths.map { |i| i[dirpath.size + 1, i.size] }
30
+ data["files"] = files
31
+ data
32
+ end
33
+
34
+ private
35
+
36
+ def set_default_data(testpath)
37
+ @data[:name] = File.basename(testpath)
38
+ @data[:author] = ENV["USER"]
39
+ @data[:date] = Time.now.strftime("%Y-%m-%d")
40
+ @data[:desc] = "Write your description"
41
+ @data[:tags] = ["Write your", "comma separated", "tags"]
42
+ end
43
+
44
+ def ask_data(testpath)
45
+ set_default_data(testpath)
46
+ prompt = TTY::Prompt.new
47
+ @data[:name] = prompt.ask("name?", default: @data[:name])
48
+ @data[:author] = prompt.ask("author?", default: @data[:author])
49
+ @data[:date] = prompt.ask("date?", default: @data[:date])
50
+ @data[:desc] = prompt.ask("desc?", default: @data[:desc])
51
+ input = prompt.ask("tags?", default: @data[:tags].join(","))
52
+ @data[:tags] = input.split(",")
53
+ end
54
+
55
+ def create(testpath)
56
+ startfile = File.join(testpath, "start.rb")
57
+ unless File.exist?(startfile)
58
+ @dev.writeln " ERROR: File start.rb not found!", color: :light_red
59
+ return false
60
+ end
61
+
62
+ infofilename = Application::INFOFILENAME
63
+ sourcepath = File.join(File.dirname(__FILE__), "..", "files", infofilename)
64
+ template = File.read(sourcepath)
65
+ content = ERB.new(template, trim_mode: "%>")
66
+ targetpath = File.join(testpath, infofilename)
67
+ File.write(targetpath, content.result(binding))
68
+
69
+ true
70
+ end
71
+ end