teuton-get 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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