diff --git a/.clog.toml b/.clog.toml new file mode 100644 index 0000000..c56b222 --- /dev/null +++ b/.clog.toml @@ -0,0 +1,10 @@ +[clog] +repository = "https://github.com/kbknapp/docli-rs" +outfile = "CHANGELOG.md" +from-latest-tag = true + +[sections] +Performance = ["perf"] +Improvements = ["impr", "im", "imp"] +Documentation = ["docs"] +Deprecations = ["depr"] diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..233cb1b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: rust +rust: + - nightly +before_script: + - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH +script: + - travis-cargo build + - travis-cargo test + - travis-cargo doc +after_success: + - travis-cargo doc-upload +env: + global: + secure: JLBlgHY6OEmhJ8woewNJHmuBokTNUv7/WvLkJGV8xk0t6bXBwSU0jNloXwlH7FiQTc4TccX0PumPDD4MrMgxIAVFPmmmlQOCmdpYP4tqZJ8xo189E5zk8lKF5OyaVYCs5SMmFC3cxCsKjfwGIexNu3ck5Uhwe9jI0tqgkgM3URA= diff --git a/Cargo.lock b/Cargo.lock index 5c2c67e..df5199e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,10 +1,10 @@ [root] name = "docli" -version = "0.1.0" +version = "0.1.0-alpha" dependencies = [ "ansi_term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "doapi 0.1.0", + "doapi 0.1.0-alpha (git+https://github.com/kbknapp/doapi-rs)", ] [[package]] @@ -33,20 +33,21 @@ dependencies = [ [[package]] name = "cookie" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "openssl 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "doapi" -version = "0.1.0" +version = "0.1.0-alpha" +source = "git+https://github.com/kbknapp/doapi-rs#52e0d4937aea286f08f5674f3a08643606a9a6f4" dependencies = [ - "hyper 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.3.2 (git+https://github.com/kbknapp/serde)", "serde_macros 0.3.2 (git+https://github.com/kbknapp/serde_macros)", @@ -54,7 +55,7 @@ dependencies = [ [[package]] name = "gcc" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -64,21 +65,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cookie 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -122,7 +123,7 @@ dependencies = [ [[package]] name = "num" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -153,7 +154,7 @@ name = "openssl-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libressl-pnacl-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -206,12 +207,12 @@ name = "regex" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex-syntax 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -224,7 +225,7 @@ name = "serde" version = "0.3.2" source = "git+https://github.com/kbknapp/serde#ccc82e033e54999cd7eeece73e89bf0e89ced8fa" dependencies = [ - "num 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -252,10 +253,10 @@ dependencies = [ [[package]] name = "time" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -276,7 +277,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "url" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index b707d07..3c9a62b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "docli" -version = "0.1.0" +version = "0.1.0-alpha" authors = ["Kevin K "] -description = "A command line interface to managing DigitalOcean infrastructure" +description = "A command line utility to managing DigitalOcean infrastructure" license = "MIT" repository = "https://github.com/kbknapp/docli-rs.git" documentation = "http://kbknapp.github.io/docli-rs" @@ -12,11 +12,7 @@ keywords = ["do", "cli", "digitalocean", "digital", "ocean"] [dependencies] clap = "*" - - -[dependencies.doapi] -# git = "https://github.com/kbknapp/doapi-rs" -path = "../doapi-rs" +doapi = {git = "https://github.com/kbknapp/doapi-rs"} [features] diff --git a/LICENSE b/LICENSE-MIT similarity index 100% rename from LICENSE rename to LICENSE-MIT diff --git a/README.md b/README.md index 2afd0d1..b75120a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,124 @@ -# docli-rs -Command-line utility for managing DigitalOcean infrastructure +# docli-rs (pronounced "dockly") + +[![Build Status](https://travis-ci.org/kbknapp/docli-rs.svg?branch=master)](https://travis-ci.org/kbknapp/docli-rs) [![Crates.io](https://img.shields.io/crates/v/docli.svg)]() [![Crates.io](https://img.shields.io/crates/l/docli.svg)]() [![Join the chat at https://gitter.im/kbknapp/docli-rs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kbknapp/docli-rs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +A command-line utility for managing DigitalOcean infrastructure via the [DigitalOcean API v2](https://developers.digitalocean.com/documentation/) + +## Disclaimer +This library is in alpha - it may do anything up to, and including, eating your laundry. You can check the request being sent to DigitalOcean without sending via the `--nosend --verbose` flags + +## Installation + +### Linux / OSX + +If you are on Arch linux, you can install from the AUR via the `docli-git` (requires a nightly Rust compiler) or `docli-bin` package. Otherwise you can try one of the pre-compiled binaries: + +#### Linux x86_64 + +Assuming you're familiar `$PATH`, download the tar.gz, unzip, and copy to somewhere in your `$PATH` + +```sh +$ wget http://wod.twentyfives.net/bin/docli/docli-v0.1.0-alpha_linux-x64.tar.gz +$ tar xvf docli-v0.1.0-alpha_linux-x64.tar.gz +$ cp docli ~/.bin +``` +In the example `~/.bin` is in `$PATH` + +#### OSX x86_64 + +Assuming you're familiar `$PATH`, download the tar.gz, unzip, and copy to somewhere in your `$PATH` + +```sh +$ wget http://wod.twentyfives.net/bin/docli/docli-v0.1.0-alpha_osx-x64.tar.gz +$ tar xvf docli-v0.1.0-alpha_osx-x64.tar.gz +$ cp docli ~/.bin +``` +In the example `~/.bin` is in `$PATH` + +### Windows + +I have not tried compiling on Windows yet. Feel free to clone the repository and attempt to compile with a nightly Rust compiler + +## Compile from source + +If you'd rather compile from source (takes about 2 minutes on a decent machine) use the following (Assuming you already have a nightly Rust compiler): + +```sh +$ git clone https://github.com/kbknapp/docli-rs +$ cd docli-rs +$ cargo build --release +$ cp target/release/docli ~/.bin +``` + +## Usage + +You can run `docli` from the command line and various subcommands. In order to see what commands are available, run `docli --help` or `docli --help` + +```sh +docli v0.1.0alpha +Kevin K. +A utility for managing DigitalOcean infrastructure + +USAGE: + docli [FLAGS] [OPTIONS] [SUBCOMMANDS] + +FLAGS: + -h, --help Prints help information + -n, --nosend Does NOT send request over the network (useful with --verbose) + --version Prints version information + -v, --verbose Displays the request being sent to server + +OPTIONS: + -t, --token Digital Ocean Auth Token (Defaults to contents of DO_AUTH_TOKEN env var if omitted) + +SUBCOMMANDS: + account Commands related to a single account + dns Commands for managing DNS records on a specific domain + domains Commands for managing domains + droplet Commands for managing a single droplet + droplets Commands for managing droplets + help Prints this message + image Commands for managing images + list Commands for displaying available information + ssh-keys Commands for managing SSH keys +``` + +### DigitalOcean Personal Auth Token + +In order to use the DigitalOcean v2 API (which is what `docli` uses under the covers, you must generate a Personal Authentication Token. This token can then either be passed to `docli` directly with `--token ` or you can set a `DO_AUTH_TOKEN` environmental variable before using `docli`. To do using Linux or OSX, open a terminal and run the following (test with `docli account` which lists your account information): + +```sh +$ export DO_AUTH_TOKEN= +$ docli account +``` + +Personal Auth Token's can be Read/Write, or Read Only/Write Only. In order to process destructive API calls (i.e. ones that modify existing information) you *must* have a token with Write priviledges. + +To generate a new Personal Auth Token see the [following DigitalOcean details](https://developers.digitalocean.com/documentation/v2/#authentication) + +## Contributing + +Contributions are always welcome! And there is a multitude of ways in which you can help depending on what you like to do, or are good at. Anything from documentation, code cleanup, issue completion, new features, you name it, even filing issues is contributing and greatly appreciated! + +**NOTE:** One of the best ways to help right now is to simply use the utility and report issues! + +1. Fork `docli` +2. Clone your fork (`git clone https://github.com/$YOUR_USERNAME/docli-rs && cd docli-rs`) +3. Create new branch (`git checkout -b new-branch`) +4. Make your changes, and commit (`git commit -am "your message"`) + * I use a [conventional](https://github.com/ajoslin/conventional-changelog/blob/master/CONVENTIONS.md) changelog format so I can update my changelog using [clog](https://github.com/thoughtram/clog) + * Format your commit subject line using the following format: `TYPE(COMPONENT): MESSAGE` where `TYPE` is one of the following: + - `feat` - A new feature + - `imp` - An improvement to an existing feature + - `perf` - A performance improvement + - `docs` - Changes to documentation only + - `tests` - Changes to the testing framework or tests only + - `fix` - A bug fix + - `refactor` - Code functionality doesn't change, but underlying structure may + - `style` - Stylistic changes only, no functionality changes + - `wip` - A work in progress commit (Should typically be `git rebase`'ed away) + - `chore` - Catch all or things that have to do with the build system, etc + * The `COMPONENT` is optional, and may be a single file, directory, or logical component. Can be omitted if commit applies globally +5. `git rebase` into concise commits and remove `--fixup`s (`git rebase -i HEAD~NUM` where `NUM` is number of commits back) +6. Push your changes back to your fork (`git push origin $your-branch`) +7. Create a pull request! (You can also create the pull request first, and we'll merge when ready. This a good way to discuss proposed changes.) \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..b1e5433 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ + diff --git a/pkg/os/arch/PKGBUILD b/pkg/os/arch/PKGBUILD new file mode 100644 index 0000000..b5413dd --- /dev/null +++ b/pkg/os/arch/PKGBUILD @@ -0,0 +1,31 @@ +# Maintainer: Kevin K. + +_pkgname=docli +pkgname=${_pkgname}-git +pkgver=0.1.0-alpha +pkgrel=1 +pkgdesc='command line utility for managing digitalocean infrastructure' +arch=('i686' 'x86_64') +url="https://github.com/kbknapp/${_pkgname}-rs" +license=('MIT') +makedepends=('git' 'cargo' 'rust') +provides=("${_pkgname}") +conflicts=("${_pkgname}") +source=("git://github.com/kbknapp/${_pkgname}-rs.git") +md5sums=('SKIP') + +pkgver() { + cd "$srcdir/$_pkgname" + git rev-list --count HEAD +} + +build() { + cd "$srcdir/$_pkgname" + cargo build --release +} + +package() { + cd "$srcdir/$_pkgname" + mkdir -p "${pkgdir}/usr/bin" + cp -p "target/release/${_pkgname}" "${pkgdir}/usr/bin" +} \ No newline at end of file diff --git a/src/cli/droplet.rs b/src/cli/droplet.rs index daa6154..d10057f 100644 --- a/src/cli/droplet.rs +++ b/src/cli/droplet.rs @@ -71,7 +71,7 @@ pub fn run(m: &ArgMatches, cfg: &mut Config) { } } } - CliMessage::DropletKernels(id).display(); + CliMessage::DropletSnapshots(id).display(); match domgr.droplet(id).snapshots().retrieve() { Ok(v) => { CliMessage::Success.display(); @@ -752,7 +752,7 @@ pub fn run(m: &ArgMatches, cfg: &mut Config) { } } } - CliMessage::SnapshotDroplet(id).display(); + CliMessage::SnapshotDroplet(id, name).display(); match domgr.droplet(id).snapshot(name).retrieve() { Ok(s) => { CliMessage::Success.display(); diff --git a/src/message.rs b/src/message.rs index c1b1742..f310118 100644 --- a/src/message.rs +++ b/src/message.rs @@ -22,11 +22,11 @@ pub enum CliMessage<'a> { CreateDroplet(&'a Droplet), Droplet(&'a str), DropletKernels(&'a str), - DropletSnapshots(&'a str), DropletBackups(&'a str), DropletActions(&'a str), DeleteDroplet(&'a str), DropletNeighbors(&'a str), + DropletSnapshots(&'a str), DisableBackups(&'a str), RebootDroplet(&'a str), PowerCycleDroplet(&'a str), @@ -40,7 +40,7 @@ pub enum CliMessage<'a> { ChangeKernel(&'a str, &'a str), EnableIpv6(&'a str), EnablePrivateNetworking(&'a str), - SnapshotDroplet(&'a str), + SnapshotDroplet(&'a str, &'a str), DropletAction(&'a str, &'a str), UpgradeDroplet(&'a str), Kernel, @@ -62,7 +62,6 @@ pub enum CliMessage<'a> { AllDropletNeighbors, NamelessDroplet, DestroySshKey(&'a str), - CreateDnsRec(&'a str), Snapshot, Backup, DnsRecords, @@ -79,7 +78,6 @@ pub enum CliMessage<'a> { } impl<'a> CliMessage<'a> { - #[cfg(feature="color")] pub fn display(&self) { match *self { CliMessage::Account => { @@ -380,11 +378,13 @@ impl<'a> CliMessage<'a> { White.bold().underline().paint(id), White.bold().paint("...")); }, - CliMessage::SnapshotDroplet(id) => { - print!("{} {} {}{}", + CliMessage::SnapshotDroplet(id, name) => { + print!("{} {} {} {} {}{}", Blue.bold().paint("::"), White.bold().paint("Taking a snapshot of droplet"), White.bold().underline().paint(id), + White.bold().paint("with name"), + White.bold().underline().paint(name), White.bold().paint("...")); }, CliMessage::UpgradeDroplet(id) => { @@ -546,12 +546,6 @@ impl<'a> CliMessage<'a> { White.bold().underline().paint(id), White.bold().paint("...")); }, - CliMessage::CreateDnsRec(rec) => { - print!("{} {}\n\t{}\n", - Blue.bold().paint("::"), - White.bold().paint("Creating DNS record with the following configuration..."), - rec.to_string().replace("\n", "\n\t")); - }, CliMessage::Confirm => { print!("{} {} {}\n\n{}[Y/n]: ", Blue.bold().paint("::"), @@ -561,77 +555,40 @@ impl<'a> CliMessage<'a> { }, } } +} - #[cfg(not(feature="color"))] - pub fn display(&self) { - print!("::"); - match *self { - CliMessage::Account => { - print!(" Displaying account information..."); - }, - CliMessage::Action => { - println!(" Displaying account action...\n\t"); - }, - CliMessage::Actions => { - print!(" Displaying all account actions...\n"); - }, - CliMessage::ActionId(id) => { - print!(" Displaying account action ID {}...", id); - }, - CliMessage::Failure => { - println!("Failed"); - }, - CliMessage::JsonResponse => { - print!(" Displaying JSON response from DigitalOcean..."); - }, - CliMessage::Request(req) => { - println!(" Displaying sent request...\n\t{}\n", req); - }, - CliMessage::Success => { - println!("Success"); - }, - CliMessage::Token(tok) => { - println!(" Displaying account token...\n\t{}\n", tok); - }, - CliMessage::Regions => { - print!(":: Displaying all regions..."); - }, - CliMessage::Sizes => { - print!("::Displaying all sizes..."); - }, - CliMessage::Images => { - print!("::Displaying all images..."); - }, - CliMessage::SshKeys => { - print!(":: Displaying all SSH keys..."); - }, - CliMessage::Dropets => { - print!(":: Displaying all droplets..."); - }, - CliMessage::Domains => { - print!(":: Displaying all domains..."); - }, - CliMessage::ImageActions(id) => { - print!(":: Displaying all actions for image {}...", id); - }, - CliMessage::Image(id) => { - print!(":: Displaying image {}...", id); - }, - CliMessage::UpdateImage(id) => { - print!(":: Updating image {}...", id); - }, - CliMessage::DeleteImage(id) => { - print!(":: Deleting image {}...", id); - }, - CliMessage::ConvertImage(id) => { - print!(":: Converting image {}...", id); - }, - CliMessage::TransferImage(id, region) => { - print!(":: Transferring image {} to region {}...", id, region); - }, - CliMessage::ImageAction(id, a_id) => { - print!(":: Displaying action {} for image {}...", a_id, id); - } - } +#[cfg(not(feature = "color"))] +struct Red; +#[cfg(not(feature = "color"))] +struct Green; +#[cfg(not(feature = "color"))] +struct Blue; +#[cfg(not(feature = "color"))] +struct White; +#[cfg(not(feature = "color"))] +struct Yellow; + +#[cfg(not(feature = "color"))] +trait Paint { + fn bold(&self) -> &Self { + self + } + fn paint<'a>(&self, s: &'a str) -> &'a str { + s + } + fn underline(&self) -> &Self { + self } } + + +#[cfg(not(feature = "color"))] +impl Paint for Red {} +#[cfg(not(feature = "color"))] +impl Paint for Green {} +#[cfg(not(feature = "color"))] +impl Paint for Blue {} +#[cfg(not(feature = "color"))] +impl Paint for White {} +#[cfg(not(feature = "color"))] +impl Paint for Yellow {} \ No newline at end of file