Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalie committed Sep 24, 2023
0 parents commit 336a130
Show file tree
Hide file tree
Showing 48 changed files with 1,242 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/ci.yml
@@ -0,0 +1,33 @@
name: CI

on:
push:
branches: [ master ]
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
name: Ruby ${{ matrix.ruby-version }}
strategy:
matrix:
ruby-version:
- '2.7'
- '3.0'
- '3.1'
- '3.2'
- 'ruby-head'
steps:
- uses: actions/checkout@v3
- name: Configure ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true
- name: Run unit tests
run: bundle exec rake
15 changes: 15 additions & 0 deletions .gitignore
@@ -0,0 +1,15 @@
*.gem
.bundle
Gemfile.lock
doc/
tmp
.ruby-version
.ruby-gemset
*.swp

# Yard
yardoc/
.yardoc/

# Dev files
config/
14 changes: 14 additions & 0 deletions .rubocop.yml
@@ -0,0 +1,14 @@
---

require:
- standard
- rubocop-performance
- rubocop-rake
- rubocop-minitest

inherit_gem:
standard: config/base.yml

AllCops:
NewCops: disable
TargetRubyVersion: 3.0
22 changes: 22 additions & 0 deletions .solargraph.yml
@@ -0,0 +1,22 @@
---
include:
- "**/*.rb"
exclude:
- spec/**/*
- test/**/*
- vendor/**/*
- ".bundle/**/*"
require: []
domains: []
reporters:
- rubocop
- require_not_found
formatter:
rubocop:
cops: safe
except: []
only: []
extra_args: []
require_paths: []
plugins: []
max_files: 5000
9 changes: 9 additions & 0 deletions Gemfile
@@ -0,0 +1,9 @@
source "https://rubygems.org"

gemspec

gem "standard", "~> 1.31", require: false
gem "rubocop", "~> 1.56", require: false
gem "rubocop-minitest", "~> 0.31", require: false
gem "rubocop-performance", "1.19", require: false
gem "rubocop-rake", "0.6", require: false
22 changes: 22 additions & 0 deletions LICENSE.txt
@@ -0,0 +1,22 @@
Copyright (c) 2011 Vitalie Cherpec

MIT License

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
104 changes: 104 additions & 0 deletions README.md
@@ -0,0 +1,104 @@
# LuaDNS Ruby Client

This is the Ruby client for [LuaDNS REST API](https://www.luadns.com/api.html).


[![Build Status](https://github.com/luadns/luadns-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/luadns/luadns-ruby/actions/workflows/ci.yml)


## Installation

Add to Gemfile

```
gem "luadns", "~> 0.1"
```


## Usage

Initialize the client using the account email and API key:

```
require "luadns"
# Init the client with your email and API key.
client = Luadns::Client.new("joe@example.com", "api_key")
```
Getting current user:
```
# List current zones
client.users.me()
```

Working with zones:

```
# List current zones
client.zones.list_zones()
# Create a new zone
client.zones.create_zone({name: "example.dev"})
# Get a zone
client.zones.get_zone(zone_id)
# Update a zone
client.zones.update_zone(zone.id, attributes)
# Delete a zone
client.zones.delete_zone(zone.id)
```

Working with records:

```
# List zone records
client.records.list_records()
# Create a new record
client.records.create_record(zone, {name: "example.org.", type: "TXT", content: "Hello, world!", ttl: 3600})
# Get a record
client.records.get_record(zone, record_id)
# Update a record
client.records.update_record(zone, record.id, {name: "example.org.", type: "TXT", content: "Aloha!", ttl: 3600})
# Delete a record
client.records.delete_record(zone, record.id)
```

## Rate Limits

The API requests are [rate-limited](http://www.luadns.com/api.html#rate-limiting),
when `Luadns::RateLimitError` is raised the code should be retried:

```
begin
client.list_zones()
rescue Luadns::RateLimitError => e
sleep e.reset - Time.now.to_i
retry
end
```


## Rails

The library can be initialized using ENV variables from a Rails initializer.

Example:

```
# config/initializers/luadns.rb
Luadns.configure do |config|
config.username = ENV['LUADNS_USERNAME']
config.password = ENV['LUADNS_API_KEY']
end
```

## Support and Feedback

Be sure to visit the LuadDNS official [documentation website](http://www.luadns.com/api.html) for additional information about our API.
29 changes: 29 additions & 0 deletions Rakefile
@@ -0,0 +1,29 @@
require "bundler/gem_tasks"
require "rubocop/rake_task"
require "rake/testtask"
require "rdoc/task"
require "yard"

RuboCop::RakeTask.new do |task|
task.requires << "rubocop-rake"
end

desc "Default: run tests and rubocop."
task default: [:test, :rubocop]

desc "Run luadns unit tests."
Rake::TestTask.new do |t|
t.libs << "test"
t.libs << "lib"
t.test_files = Dir["test/**/*_test.rb"]
t.verbose = true
end

YARD::Rake::YardocTask.new(:yardoc) do |y|
y.options = ["--output-dir", "yardoc"]
end

desc "Run IRB console"
task :console do
sh "bundle exec irb -r luadns -r ./config/setup"
end
36 changes: 36 additions & 0 deletions lib/luadns.rb
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# Module for interacting with LuaDNS API.
module Luadns
BASE_URL = "https://api.luadns.com/v1"
JSON_MIME = "application/json"
USER_AGENT = "luadns-ruby/#{VERSION}".freeze

class << self
attr_writer :base_url
attr_accessor :username, :password

def base_url
@base_url || BASE_URL
end

def configure
yield self
end
end
end

require "httparty"
require_relative "luadns/errors"
require_relative "luadns/schema"
require_relative "luadns/schema/base"
require_relative "luadns/schema/user"
require_relative "luadns/schema/zone"
require_relative "luadns/schema/record"
require_relative "luadns/http_client"
require_relative "luadns/endpoint"
require_relative "luadns/endpoint/base"
require_relative "luadns/endpoint/users"
require_relative "luadns/endpoint/zones"
require_relative "luadns/endpoint/records"
require_relative "luadns/client"
33 changes: 33 additions & 0 deletions lib/luadns/client.rb
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module Luadns
class Client
DEFAULT_OPTIONS = {
format: :json,
headers: {
"Accept" => JSON_MIME,
"Content-Type" => JSON_MIME,
"User-Agent" => USER_AGENT
}
}.freeze

attr_reader :http_client

attr_reader :users
attr_reader :zones
attr_reader :records

def initialize(username = Luadns.username, password = Luadns.password)
@http_client = HttpClient.new(request_options(username, password))
@users = Luadns::Endpoint::Users.new(@http_client)
@zones = Luadns::Endpoint::Zones.new(@http_client)
@records = Luadns::Endpoint::Records.new(@http_client)
end

protected

def request_options(username, password)
DEFAULT_OPTIONS.merge({basic_auth: {username: username, password: password}})
end
end
end
4 changes: 4 additions & 0 deletions lib/luadns/endpoint.rb
@@ -0,0 +1,4 @@
module Luadns
module Endpoint
end
end
37 changes: 37 additions & 0 deletions lib/luadns/endpoint/base.rb
@@ -0,0 +1,37 @@
module Luadns
module Endpoint
class Base
attr_reader :http_client

def initialize(http_client)
@http_client = http_client
end

def endpoint_url(path)
"#{Luadns.base_url}#{path}"
end

def parse_response(response, object_class)
case response.code
when 200
content_type = response.headers["Content-Type"]
raise ServerError, response unless content_type.start_with?(JSON_MIME)
when 400
raise ValidationError, response
when 401
raise AuthenticationError, response
when 403
raise RequestError, response
when 404
raise NotFoundError, response
when 429
raise RateLimitError, response
else
raise ServerError, response
end

JSON.parse(response.body, object_class: object_class)
end
end
end
end

0 comments on commit 336a130

Please sign in to comment.