#!/usr/bin/env ruby require 'optparse' require 'methadone' require 'generator.rb' require 'yaml' require 'nokogiri' require 'generator' require 'validator' require 'api' require 'login' require 'diffy' require 'pp' require 'fileutils' class App include Methadone::Main include Methadone::CLILogging # the main block main do @api = Vpnconfig::Api.new @verbose = !options['v'].nil? self.check_mandatory_inputs input_config = self.validate_yaml_if_present(options['w']) puts 'Logging in' if @verbose conn = Vpnconfig::Login.new.login(options['u']) puts "\nReading configuration...." dc_details = @api.get_dc_details(conn, options['d']) puts 'Found data centre: '+dc_details['name'] if @verbose current_config, edgegw_href = @api.read_edgegw_config(dc_details, conn) unless options['b'].nil? self.backup_current_config(current_config, options['b'], options['d']) end puts 'Current configuration is:' if @verbose puts current_config if @verbose puts if @verbose unless options['w'].nil? puts 'Reading in your yaml file...' if @verbose puts 'Generating XML...' if @verbose new_config = Vpnconfig::Generator.new.generate_xml(input_config) puts 'Generated XML is:' if @verbose puts new_config if @verbose puts if @verbose if configs_match(current_config, new_config) puts 'Old and new configuration are identical, no changes to make' else puts "Posting new configuration to skyscape" puts "href: #{edgegw_href}..." if @verbose task_href = @api.post_to_api(edgegw_href, conn, new_config) puts 'Task has been created to update config, tracking progress....' if @verbose report_task_status(task_href, conn) end end end # Supplemental methods def self.validate_yaml_if_present(yaml_path) if !yaml_path.nil? input_config = YAML.load_file(yaml_path) validation_errors = Vpnconfig::Validator.new.validate_yaml(input_config) if !validation_errors.empty? display_errors_and_abort(validation_errors) end end input_config end def self.backup_current_config(current_config, backup_path, datacentre) puts 'Creating backup of current configuration...' if @verbose filename = Time.now.strftime("%Y%m%d%H%M%S") + '_' + datacentre + '_VPN_Config' backup_path = backup_path + '/' if backup_path[-1] != '/' filepath = backup_path + filename unless File.directory?(filepath) FileUtils.mkdir_p(backup_path) puts 'Created directory for backup' if @verbose end File.write(filepath, current_config) puts "Created backup file at: #{filepath}" if @verbose end def self.report_task_status(task_href, conn) completed_task = @api.get_completed_task(task_href, conn) if completed_task['status'] == 'success' puts 'New config has been successfully written to Skyscape' else api_error_message = completed_task.at('Error')['message'] api_error_code= completed_task.at('Error')['majorErrorCode'] Kernel.abort("The task returned with status code #{api_error_code} and the following error: #{api_error_message}") end end def self.check_mandatory_inputs if options['d'].nil? Kernel.abort('You must define a datacentre') end if options['u'].nil? Kernel.abort('You must provide a username') end end def self.save_config(xml_obj, filename) file = File.open(filename, "w") xml_obj.write_xml_to(file, options={}) file.close end def self.display_errors_and_abort(errors) errors.each{|e| puts "#{e.message}"} puts 'The schema to match against is:' pp YAML.load_file('./lib/vpn-configuration-schema.yaml') Kernel.abort('ERROR: Invalid yaml input does not match the schema, see validation_errors above.') end def self.configs_match(current_config, new_config) new_config.delete(' ').lines.drop(1).join() == current_config.delete(' ') end # Command line interface details description "Updates VPN configuration for given datacentre based on a yaml input file" on("-w VAL", "--write", "Writes configuration to the VDC as per specified XML file") on("-d VAL", "--datacentre", "Name of the skyscape datacentre") on("-u VAL", "--user", "Username to connect to the Skyscape Datacenter(check API tab)") on("-b VAL", "--backup", "Optionally specify the location to store a backup of the current configuration") on("-v", "--verbose", "Verbose logging") version Vpnconfig::VERSION use_log_level_option :toggle_debug_on_signal => 'USR1' go! end