Initial import
This commit is contained in:
commit
92faeb2c1b
9 changed files with 303 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
lib
|
||||
bin
|
37
Dockerfile
Normal file
37
Dockerfile
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
## Stage 1 : build binary
|
||||
FROM crystallang/crystal:1.4.1 AS builder
|
||||
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN shards build
|
||||
|
||||
## Stage 2 : include binary into final image
|
||||
FROM python:3.7-bullseye AS runner
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get -yq install \
|
||||
libevent-core-2.1-7 \
|
||||
gettext \
|
||||
jq \
|
||||
python3-aodhclient \
|
||||
python3-barbicanclient \
|
||||
python3-ceilometerclient \
|
||||
python3-cinderclient \
|
||||
python3-cloudkittyclient \
|
||||
python3-designateclient \
|
||||
python3-gnocchiclient \
|
||||
python3-octaviaclient \
|
||||
python3-osc-placement \
|
||||
python3-openstackclient \
|
||||
python3-pankoclient \
|
||||
zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# RUN wget https://github.com/sapcc/cyclone/releases/download/v0.1.28/cyclone \
|
||||
# -O /usr/bin/cyclone \
|
||||
# && chmod +x /usr/bin/cyclone
|
||||
|
||||
COPY --from=builder /app/bin/arkisto /usr/bin/arkisto
|
||||
|
||||
CMD /bin/bash
|
15
Makefile
Normal file
15
Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
build:
|
||||
shards build
|
||||
|
||||
docker: docker-build docker-test docker-push
|
||||
|
||||
docker-build:
|
||||
docker build -t glenux/openstack-arkisto .
|
||||
|
||||
docker-push:
|
||||
docker push glenux/openstack-arkisto
|
||||
|
||||
docker-test:
|
||||
docker run glenux/openstack-arkisto arkisto --version
|
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Arkisto
|
||||
|
||||
A simple tool to automate openstack snapshots
|
||||
|
22
arkisto.sample.yml
Normal file
22
arkisto.sample.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
version: "1"
|
||||
|
||||
retention:
|
||||
days: 8
|
||||
cycle: true
|
||||
max_items: 2
|
||||
|
||||
targets:
|
||||
- name: smart-app
|
||||
volume_id: x
|
||||
snapshot_prefix: y
|
||||
- name: smart-db
|
||||
volume_id: x
|
||||
snapshot_prefix: y
|
||||
- name: short-db
|
||||
volume_id: x2
|
||||
snapshot_prefix: y
|
||||
- name: collector-db
|
||||
volume_id: x2
|
||||
snapshot_prefix: y
|
||||
#
|
6
shard.lock
Normal file
6
shard.lock
Normal file
|
@ -0,0 +1,6 @@
|
|||
version: 2.0
|
||||
shards:
|
||||
tablo:
|
||||
git: https://github.com/hutou/tablo.git
|
||||
version: 0.10.1
|
||||
|
25
shard.yml
Normal file
25
shard.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
name: arkisto
|
||||
version: 0.1.0
|
||||
|
||||
authors:
|
||||
- Glenn Y. Rolland <glenn.rolland@boldcode.io>
|
||||
|
||||
description: |
|
||||
Simple and stupid utility to cycle openstack volume backups/snapshots
|
||||
|
||||
targets:
|
||||
arkisto:
|
||||
main: src/arkistoctl/main.cr
|
||||
|
||||
dependencies:
|
||||
# Text tables
|
||||
tablo:
|
||||
github: hutou/tablo
|
||||
|
||||
|
||||
# development_dependencies:
|
||||
# webmock:
|
||||
# github: manastech/webmock.cr
|
||||
|
||||
license: MIT
|
51
spec/data/openstack.sample.yml
Normal file
51
spec/data/openstack.sample.yml
Normal file
|
@ -0,0 +1,51 @@
|
|||
- Attached to: []
|
||||
ID: 7b715476-5397-48de-87ac-5a63170fff71
|
||||
Name: ovh-managed-kubernetes-e6j07m-pvc-fc264e28-94e3-43c5-afe1-3c99b6d95bfb
|
||||
Size: 1
|
||||
Status: available
|
||||
- Attached to: []
|
||||
ID: c9d05e3e-c668-47fd-8bd6-0cedc9dc02c5
|
||||
Name: ovh-managed-kubernetes-e6j07m-pvc-44bca100-2f8c-4be2-9491-d2254a42287f
|
||||
Size: 2000
|
||||
Status: available
|
||||
- Attached to: []
|
||||
ID: 8c87c196-1dd6-4190-bff5-00b543965093
|
||||
Name: ovh-managed-kubernetes-e6j07m-pvc-9fad19b4-b32c-452a-9893-524fcdc3a4b1
|
||||
Size: 50
|
||||
Status: available
|
||||
- Attached to:
|
||||
- attached_at: '2022-06-26T19:03:31.000000'
|
||||
attachment_id: 503f8552-e2f9-4aff-a489-8382bbed3883
|
||||
device: /dev/sdb
|
||||
host_name: null
|
||||
id: c9b11fcb-a6a4-4387-b55b-34121f97dac4
|
||||
server_id: 7ee31946-16ab-4759-be33-6499a339f929
|
||||
volume_id: c9b11fcb-a6a4-4387-b55b-34121f97dac4
|
||||
ID: c9b11fcb-a6a4-4387-b55b-34121f97dac4
|
||||
Name: ovh-managed-kubernetes-e6j07m-pvc-13dcac68-71c9-4794-b0ab-d48e76d843ef
|
||||
Size: 5800
|
||||
Status: in-use
|
||||
- Attached to:
|
||||
- attached_at: '2022-06-21T12:47:29.000000'
|
||||
attachment_id: 569b7110-74e1-4f87-b92d-ab5e1a2a473c
|
||||
device: /dev/sdb
|
||||
host_name: null
|
||||
id: de7b118f-413b-4962-a028-a742df4bc4fc
|
||||
server_id: e1753464-9328-4eea-ae98-21c332e94dc5
|
||||
volume_id: de7b118f-413b-4962-a028-a742df4bc4fc
|
||||
ID: de7b118f-413b-4962-a028-a742df4bc4fc
|
||||
Name: ovh-managed-kubernetes-e6j07m-pvc-dfbf1e3a-7ed6-4a90-a4e0-4b5516f88051
|
||||
Size: 50
|
||||
Status: in-use
|
||||
- Attached to:
|
||||
- attached_at: '2022-06-27T17:31:53.000000'
|
||||
attachment_id: 845a7ff2-ad54-4040-b69b-fce7fdfdece2
|
||||
device: /dev/sdb
|
||||
host_name: null
|
||||
id: 6d4492e5-6b38-4ad3-b9bf-27ba86e2506b
|
||||
server_id: 37220c33-19e7-45cc-9c6a-ddf957be3c76
|
||||
volume_id: 6d4492e5-6b38-4ad3-b9bf-27ba86e2506b
|
||||
ID: 6d4492e5-6b38-4ad3-b9bf-27ba86e2506b
|
||||
Name: ovh-managed-kubernetes-e6j07m-pvc-7bf995bf-ac82-4f42-94ca-78cd9c78959d
|
||||
Size: 1
|
||||
Status: in-use
|
141
src/arkistoctl/main.cr
Normal file
141
src/arkistoctl/main.cr
Normal file
|
@ -0,0 +1,141 @@
|
|||
require "yaml"
|
||||
require "option_parser"
|
||||
require "colorize"
|
||||
# require "xdg_basedir"
|
||||
# require "completion"
|
||||
require "log"
|
||||
|
||||
require "../lib/actions"
|
||||
require "../lib/types"
|
||||
require "../lib/models"
|
||||
require "../lib/version"
|
||||
|
||||
|
||||
module Arkisto
|
||||
class CtlCli
|
||||
property config : ConfigModel?
|
||||
property options : GlobalOptions?
|
||||
|
||||
def initialize
|
||||
# @config = nil
|
||||
@options = nil
|
||||
end
|
||||
|
||||
def self.parse_options(args) : GlobalOptions
|
||||
# default values
|
||||
action = NoneAction
|
||||
config_file = "arkisto.yml"
|
||||
verbose = true
|
||||
dry_run = false
|
||||
|
||||
# parse
|
||||
OptionParser.parse(args) do |parser|
|
||||
parser.banner = "Usage: #{Version::PROGRAM_ARKISTOCTL} [options] [commands] [arguments]"
|
||||
|
||||
parser.separator
|
||||
parser.separator "Options"
|
||||
|
||||
parser.on "-c CONFIG_FILE", "--config=CONFIG_FILE", "Use the following config file" do |file|
|
||||
config_file = file
|
||||
end
|
||||
|
||||
parser.on "-v", "--verbose", "Be verbose" do
|
||||
verbose = !verbose
|
||||
end
|
||||
|
||||
parser.on "--dry-run", "Dry run (no real openstack command is executed" do
|
||||
dry_run = true
|
||||
end
|
||||
|
||||
parser.on "--version", "Show version" do
|
||||
puts "version #{Version::VERSION}"
|
||||
exit 0
|
||||
end
|
||||
|
||||
parser.on "-h", "--help", "Show this help" do
|
||||
puts parser
|
||||
exit 0
|
||||
end
|
||||
|
||||
parser.on "--completion", "Provide autocompletion for bash" do
|
||||
# nothing here
|
||||
end
|
||||
|
||||
parser.on "plan", "Display backup plan" do
|
||||
action = PlanAction
|
||||
end
|
||||
|
||||
parser.on "apply", "Apply backup plan" do
|
||||
action = ApplyAction
|
||||
end
|
||||
|
||||
parser.separator
|
||||
|
||||
parser.missing_option do |flag|
|
||||
STDERR.puts parser
|
||||
STDERR.puts "ERROR: #{flag} requires an argument.".colorize(:red)
|
||||
exit(1)
|
||||
end
|
||||
|
||||
parser.invalid_option do |flag|
|
||||
STDERR.puts parser
|
||||
STDERR.puts "ERROR: #{flag} is not a valid option.".colorize(:red)
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# complete_with Version::PROGRAM_ARKISTOCTL, parser
|
||||
end
|
||||
|
||||
return {
|
||||
action: action,
|
||||
config_file: config_file,
|
||||
dry_run: dry_run,
|
||||
verbose: verbose,
|
||||
}.as(GlobalOptions)
|
||||
end
|
||||
|
||||
def self.parse_config(options)
|
||||
config_file = options[:config_file]
|
||||
puts "Loading configuration... #{config_file}".colorize(:yellow) if options[:verbose]
|
||||
|
||||
if ! File.exists? config_file
|
||||
STDERR.puts "ERROR: Unable to read configuration file '#{config_file}'".colorize(:red)
|
||||
exit 1
|
||||
end
|
||||
|
||||
yaml_str = File.read(config_file)
|
||||
config = ConfigModel.from_yaml(yaml_str)
|
||||
|
||||
if config.nil?
|
||||
STDERR.puts "ERROR: Invalid YAML content in '#{config_file}'"
|
||||
exit 1
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
def self.run(args)
|
||||
app = CtlCli.new
|
||||
options = CtlCli.parse_options(args)
|
||||
config = CtlCli.parse_config(options)
|
||||
app.options = options
|
||||
app.config = config
|
||||
|
||||
action = ActionFactory.build(
|
||||
options[:action],
|
||||
config,
|
||||
{
|
||||
dry_run: options[:dry_run],
|
||||
verbose: options[:verbose]
|
||||
}
|
||||
)
|
||||
action.perform
|
||||
|
||||
rescue ex : YAML::ParseException
|
||||
STDERR.puts "ERROR: #{ex.message}".colorize(:red)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Arkisto::CtlCli.run(ARGV)
|
||||
|
Loading…
Reference in a new issue