lib/gandi_v5/template.rb
# frozen_string_literal: true
class GandiV5
# Manage configuration templates.
# @!attribute [r] description
# @return [String] template purpose's description.
# @!attribute [r] editable
# @return [Boolean]
# @!attribute [r] uuid
# @return [String]
# @!attribute [r] name
# @return [String]
# @!attribute [r] orgname
# @return [String]
# @!attribute [r] sharing_space
# @return [GandiV5::SharingSpace]
# @!attribute [r] variables
# @return [Array<String>, nil]
# @!attribute [r] payload
# @return [Array<GandiV5::Template::Payload] the settings which will be applied
# when this template is used.
class Template
include GandiV5::Data
members :name, :description, :editable, :variables
member :uuid, gandi_key: 'id'
member :organisation_name, gandi_key: 'orgname'
member :payload, converter: GandiV5::Template::Payload
member(
:sharing_space,
gandi_key: 'sharing_space',
converter: GandiV5::SharingSpace
)
# Requery Gandi for this template's information.
# @return [GandiV5::Template]
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
def refresh
_response, data = GandiV5.get url
from_gandi data
self
end
# Delete this template from Gandi.
# @see https://api.gandi.net/docs/template/#delete-v5-template-templates-id
# @return [nil]
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
def delete
GandiV5.delete url
nil
end
# Applies the template to a domain.
# @see https://api.gandi.net/v5/template/dispatch/{id}
# @return [String] The UUID of the dispatch,
# keep hold of this you'll need it if you want to check the progress.
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
def apply(domain_uuid)
body = { 'object_type' => 'domain', 'object_id' => domain_uuid }.to_json
_response, data = GandiV5.post url, body
data.fetch('dispatch_href').split('/').last
end
# Update the template in Gandi.
# @see https://api.gandi.net/docs/template/#patch-v5-template-templates-id
# @param name [String, #to_s] the name to give the created template.
# @param description [String, #to_s] description of what the template achieves.
# @param dns_records [Array<Hash>, :default] The DNS records to create (as Gandi's docs)
# @option dns_records [String] :name The name of the DNS record to create.
# @option dns_records [String] :type The type of the DNS record to create.
# @option dns_records [Array<String>] :values The values for the created DNS record.
# @option dns_records [Integer] :ttl The TTL for the created record (300-2592000)
# @param mailboxes [Array<String>] The mailboxes to create (as Gandi's docs)
# @param name_servers [Array<String>, :livedns] The name servers to create (as Gandi's docs)
# @param web_forwardings [Array<Hash>] The web redirects to create (as Gandi's docs)
# @option web_forwardings [:cloak, :http301, :http302, :permanent, :temporary, :found] :type
# @option web_forwardings [String] :target
# @option web_forwardings [String] :source_host (optional)
# @option web_forwardings [Boolean] :override (optional, default false)
# When you create a redirection on a domain, a DNS record is created if it does not exist.
# When the record already exists and this parameter is set to true it will overwrite the
# record. Otherwise it will trigger an error.
# @option web_forwardings [:http, :https, :https_only] :protocol (optional)
# @return [GandiV5::Template]
# @raise [GandiV5::Error::GandiError] if Gandi returns an error
# rubocop:disable Metrics/AbcSize
def update(
name: nil,
description: nil,
dns_records: nil,
mailboxes: nil,
name_servers: nil,
web_forwardings: nil
)
body = Hash.new { |hash, key| hash[key] = {} }
body['name'] = name if name
body['description'] = description if description
body['payload']['dns:records'] = gandify_dns_records(dns_records) if dns_records
body['payload']['domain:mailboxes'] = gandify_mailboxes(mailboxes) if mailboxes
body['payload']['domain:nameservers'] = gandify_name_servers(name_servers) if name_servers
if web_forwardings
body['payload']['domain:webredirs'] = gandify_web_forwardings(web_forwardings)
end
GandiV5.patch url, body.to_json
refresh
end
# rubocop:enable Metrics/AbcSize
# Get information for a template.
# @see https://api.gandi.net/docs/template/#get-v5-template-templates-id
# @param uuid [String, #to_s] unique identifier of the template.
# @return [GandiV5::Template]
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
def self.fetch(uuid)
_response, data = GandiV5.get url(uuid)
from_gandi data
end
# List templates.
# @see https://api.gandi.net/docs/template/#get-v5-template-templates
# @param page [Integer, #each<Integer>] which page(s) of results to get.
# If page is not provided keep querying until an empty list is returned.
# If page responds to .each then iterate until an empty list is returned.
# @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
# @return [Array<GandiV5::Template>]
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
def self.list(page: (1..), per_page: 100)
templates = []
GandiV5.paginated_get(url, page, per_page) do |data|
templates += data.map { |template| from_gandi template }
end
templates
end
# Create a new template.
# @see https://api.gandi.net/docs/template/#post-v5-template-templates
# @param name [String, #to_s] the name to give the created template.
# @param description [String, #to_s] description of what the template achieves.
# @param sharing_id [String] either:
# * nil (default) - nothing special happens,
# the template belongs to the user making the request.
# * an organization ID - the template will belong to the organization.
# * a reseller ID - the template will belong to the reseller.
# @param payload [Hash, #to_h]
# @option payload [Hash] 'dns:records' The DNS records to create (as Gandi's docs)
# @option payload [Hash] 'domain:mailboxes' The mailboxes to create (as Gandi's docs)
# @option payload [Hash] 'domain:nameservers' The name servers to create (as Gandi's docs)
# @option payload [Hash] 'domain:webredirs' The web redirects to create (as Gandi's docs)
# @option payload [Array<Hash>, :default] :dns_records
# Generate dns:records from the passed list or use Gandi's default records.
# @option dns_records [String] :name The name of the DNS record to create.
# @option dns_records [String] :type The type of the DNS record to create.
# @option dns_records [Array<String>] :values The values for the created DNS record.
# @option dns_records [Integer] :ttl The TTL for the created record (300-2592000)
# @option payload [Array<String>] :mailboxes
# Generate domain:mailboxes from the passed list of mail names.
# @option payload [Array<String>, :livedns] :name_servers
# Generate domain:nameservers from the passed list of addresses, or set to Gandi's livedns.
# @option payload [Array<Hash>] :web_forwardings Generate domain:webredirs from the passed list.
# @option web_forwardings [:cloak, :http301, :http302, :permanent, :temporary, :found] :type
# @option web_forwardings [String] :target
# @option web_forwardings [String] :host (optional)
# @option web_forwardings [Boolean] :override (optional, default false)
# When you create a redirection on a domain, a DNS record is created if it does not exist.
# When the record already exists and this parameter is set to true it will overwrite the
# record. Otherwise it will trigger an error.
# @option web_forwardings [:http, :https, :https_only] :protocol (optional)
# @return [GandiV5::Template] the created template
# @raise [GandiV5::Error::GandiError] if Gandi returns an error
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def self.create(name:, description:, sharing_id: nil, **payload)
if payload.key? :dns_records
payload['dns:records'] = gandify_dns_records(payload.delete(:dns_records))
end
if payload.key? :mailboxes
payload['domain:mailboxes'] = gandify_mailboxes(payload.delete(:mailboxes))
end
if payload.key? :name_servers
payload['domain:nameservers'] = gandify_name_servers(payload.delete(:name_servers))
end
if payload.key? :web_forwardings
payload['domain:webredirs'] = gandify_web_forwardings(payload.delete(:web_forwardings))
end
url_ = sharing_id ? "#{url}?sharing_id=#{sharing_id}" : url
body = { name: name, description: description, payload: payload }.to_json
response, _data = GandiV5.post url_, body
fetch response.headers[:location].split('/').last
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
private
def self.gandify_dns_records(value)
if value == :default
{ default: true }
else
{
default: false,
records: value
}
end
end
private_class_method :gandify_dns_records
def gandify_dns_records(value)
self.class.send :gandify_dns_records, value
end
def self.gandify_mailboxes(value)
{ values: value.map { |name| { login: name } } }
end
private_class_method :gandify_mailboxes
def gandify_mailboxes(value)
self.class.send :gandify_mailboxes, value
end
def self.gandify_name_servers(value)
if value == :livedns
{ service: :livedns }
else
{
service: :custom,
addresses: value
}
end
end
private_class_method :gandify_name_servers
def gandify_name_servers(value)
self.class.send :gandify_name_servers, value
end
def self.gandify_web_forwardings(value)
type_map = {
'permanent' => 'http301',
'temporary' => 'http302',
'found' => 'http302'
}
{
values: value.map do |redirect|
type = redirect.fetch(:type).to_s
new_redirect = { type: type_map.fetch(type, type), url: redirect.fetch(:target) }
new_redirect[:host] = redirect[:host] if redirect.key?(:host)
new_redirect[:override] = redirect[:override] if redirect.key?(:override)
new_redirect[:protocol] = redirect[:protocol].to_s.delete('_') if redirect.key?(:protocol)
new_redirect
end
}
end
private_class_method :gandify_web_forwardings
def gandify_web_forwardings(value)
self.class.send :gandify_web_forwardings, value
end
def url
"#{BASE}template/templates/#{CGI.escape uuid}"
end
def self.url(uuid = nil)
"#{BASE}template/templates" + (uuid ? "/#{CGI.escape uuid}" : '')
end
private_class_method :url
end
end