Скрипт для создания хостов

Когда разрабатываешь локально или на одном дев сервере, то приходится часто вписывать одни и такие же настройки для хостов в Apache, nginx и в случае с localhost сделать запись в файл hosts.

Нам как разработчикам всегда хочется все автоматизировать, из-за этого я решил написать скрипт для такой автоматизации.

В одной из прошлых статей «Установка и настройка web-сервера» я писал про настройку web-сервера. По этому примеру я и буду писать скрипт автоматизации.

Основные настройки

Писать все это дело я решил на python. При запуске скрипта план действий такой: берем аргументы с командной строки, берем настройки с конфигурационного файла, соединяем их, создаем конфигурационные фалы для web-сервера. У меня получился вот такой конфигурационный файл:

[DEFAULT]
site_name = test.site.com #название сайта по умолчанию
site_path = /Users/nil/Sites/ #путь где будет храниться сайт
add_hosts = True # Делать ли запись в /etc/hots
create_test_folder = True #Если флаг установлен то будет создана папка с сайтом в site_path и тестовый файл index.html
create_nginx = False #Если установлен то создать запись для nginx

[HTTPD] #настройка для apache
port = 80
email = username@admin.com
log_path = logs/
host = *


[NGINX]
port = 81
proxy_pass = http://127.0.0.1:81


[SYSTEM]
httpd_config_path = data/httpd.conf.data #путь к template для конфигурационного файла apache
httpd_path = /etc/apache2/other/ #путь куда будут сохранятся наши конфигурационные файл для apache
nginx_config_path = data/nginx.conf.data #путь к template для конфигурационного файла nginx
nginx_path = data/ #путь куда будут сохранятся наши конфигурационные файл для nginx
file_hosts_path = /etc/hosts #путь к hosts 
hosts_ip = 127.0.0.1 #ip для hosts
template_page_path = data/index.html.data 

По своей сути мы будем просто брать готовый шаблон для конфигураций и подставлять туда наши настройки.

Вот мой пример такого шаблона для apache который лежит по пути httpd_config_path. Назовем файл httpd.conf.data


    ServerAdmin {$.EMAIL}
    DocumentRoot {$.SITE_PATH}{$.SITE_NAME}
    ServerName  {$.SITE_NAME}
    ServerAlias www.{$.SITE_NAME}
    #ErrorLog {$.LOG_PATH}{$.SITE_NAME}-error_log
    #CustomLog {$.LOG_PATH}{$.SITE_NAME}-access_log common
    
        AllowOverride All
        Options All
    

Следующий template будет для nginx.

server {
        listen {$.PORT};
        server_name {$.SITE_NAME};

        location / {
                ssi on;
                default_type    text/html;
                charset utf-8;
                proxy_pass {$.PROXY_PASS};
                proxy_set_header   Host             $host;
                proxy_set_header        X-Real-IP   $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                limit_except GET POST {
                        deny all;
                }
        }
}

Как вы догадались все заменяемые параметры мы обрамляем в специальные фигурные скобки. Все переменные будут браться из наших конфигурационных файлов.

Основной файл

Приступим к программированию. Вот что получилось

#!/usr/bin/python

import os
import sys
import argparse
import configparser
import utils

def do_create_httpd(options):
	config_path = options['system']['httpd_config_path']
	content = utils.get_config_content(config_path)
	content = get_prepared_content(content, options, 'httpd')
	
	httpd_path = options['system']['httpd_path']
	file_name = options['httpd']['site_name'] + '.conf'
	full_file_path = httpd_path + file_name
	
	utils.create_file(full_file_path, content)
	
	utils.success_msg("Httpd File was Created.")

def do_create_nginx(options):
	if not utils.is_true('create_nginx', options['nginx']):
		return False;
	
	config_path = options['system']['nginx_config_path']
	content = utils.get_config_content(config_path)
	content = get_prepared_content(content, options, 'nginx')
	
	httpd_path = options['system']['nginx_path']
	file_name = options['nginx']['site_name'] + '.conf'
	full_file_path = httpd_path + file_name
	
	utils.create_file(full_file_path, content)
	utils.success_msg("Nginx File was Created.")

def do_create_site(options):
	if not utils.is_true('create_test_folder', options['default']):
		return False
	
	if not os.path.isdir(options['default']['site_path']):
		utils.error_msg('Path to Folder Site Not Found')
		return False
	
	site_folder_path = options['default']['site_path'] + options['default']['site_name']
	
	if os.path.isdir(site_folder_path):
		utils.error_msg('Site Folder is Exist')
		return False
		
	os.makedirs(site_folder_path)
	
	template_path = options['system']['template_page_path']
	content = utils.get_config_content(template_path)
	
	site_folder_path = site_folder_path + "/index.html"
	utils.create_file(site_folder_path, content)
	
	utils.success_msg("Site Folder was Created.")
	

def do_create_hosts(options):
	if not utils.is_true('add_hosts', options['default']):
		return False
		
	file_hosts_path = options['system']['file_hosts_path']
	if not os.path.isfile(file_hosts_path):
		raise Exception('File Hosts Not Found')
	
	host_ip = options['system']['hosts_ip']
	string = "\n" + host_ip + " " + options['default']['site_name']
	#add conditions if record exists
	file = open(file_hosts_path, 'a')
	file.write(string)
	file.close()
	
	utils.success_msg("Record in Hosts was Added.")

def get_config():
	config = configparser.ConfigParser()
	config.read('config.ini')
	
	return config;

def get_prepared_content(content, options, key_opt):

	for key in options[key_opt]:
		reserve_key = '{$.' + key.upper() + '}'
		if options[key_opt][key]:
			content = content.replace(reserve_key, options[key_opt][key])
	
	return content
	
def get_prepared_arguments(arguments):
	arguments = vars(arguments)
	for key in arguments:
		if arguments[key] is None:
			arguments = utils.remove_dict(arguments, key)
	return arguments

def get_options(arguments, config):
	default_configs  = dict(config.items('DEFAULT'))
	configs_https    = dict(config.items('HTTPD'))
	configs_nginx    = dict(config.items('NGINX'))
	configs_system   = dict(config.items('SYSTEM'))
	
	arguments = arguments.items()
	
	options = {
		'default': dict(default_configs.items() + arguments),
		'httpd'  : dict(default_configs.items() + configs_https.items() + arguments),
		'nginx'  : dict(default_configs.items() + configs_nginx.items() + arguments),
		'system' : dict(default_configs.items() + configs_system.items() + arguments)
	} 
	
	return options;

def do_create_virtual_host(arguments):
	arguments = get_prepared_arguments(arguments)
	config = get_config()
	
	options = get_options(arguments, config)

	do_create_httpd(options)
	do_create_nginx(options)
	do_create_hosts(options)
	do_create_site(options)

def create_parser():
	parser = argparse.ArgumentParser()
	parser.add_argument("site_name")
	parser.add_argument('-i', '--info')
	parser.add_argument('-a', '--add_hosts')
	return parser

def __init():
	parser = create_parser()
	arguments = parser.parse_args(sys.argv[1:])
	do_create_virtual_host(arguments)

if __name__ == "__main__":
	try:
		__init()
	except Exception as e:
		utils.error_msg(str(e))

Utils

Добавим еще файл utils в который я вынес стилизацию сообщений.

#!/usr/bin/python

TEXT_COLOR_RED = '\033[91m'
TEXT_COLOR_GREEN = '\033[92m'
TEXT_COLOR_YELLOW = '\033[93m'
TEXT_COLOR_BLUE = '\033[94m'
TEXT_COLOR_MAGENTA = '\033[95m'
TEXT_COLOR_CYAN = '\033[96m'
TEXT_COLOT_WHITE = '\033[97m'
TEXT_COLOR_GREY = '\033[90m'
TEXT_COLOR_BLACK = '\033[30m'
TEXT_STYLE_BOLD = '\033[1m'
TEXT_STYLE_ITALIC = '\033[3m'
TEXT_STYLE_UNDERLINE = '\033[4m'
TEXT_END = '\033[0m'

def success_msg(msg):
	print(color_text(msg, TEXT_COLOR_GREEN))

def error_msg(msg):
	print(color_text(msg, TEXT_COLOR_RED))

def color_text(text, color):
    return color + text + TEXT_END

def get_config_content(path):	
	data_file = open(path)
	content = data_file.read()
	data_file.close()
	
	return content

def create_file(path, content):
	file = open(path, 'w')
	file.write(content)
	file.close()

def remove_dict(dct, key):
   copy = dct.copy()
   del copy[key]
   return copy

def str2bool(value):
	return value.lower() in ("yes", "true", "t", "1")

def is_true(key, options):
	return key in options.keys() and str2bool(options[key])
	

По коду в принципе я не оставлял комментариев, все можно понять из названия функций. Единственное что я не успел сделать это добавить больше входные параметров для скрипта. Потому что сейчас все данные будут браться из файла конфигураций. Но по желанию можно добавить больше параметров.

def create_parser():
	parser = argparse.ArgumentParser()
	parser.add_argument("site_name")
	parser.add_argument('-i', '--info')
	parser.add_argument('-a', '--add_hosts') #можно указывать добавлять ли запись в /etc/hosts 
	return parser

Это можно модифицировать под свои нужды. Мне пока что достаточно настроек которые есть в фале. Я выложу исходники на GitHub, может к тому времени когда вы будете читать статью я модифицирую данный код.

Вот пример того что получилось. Скрипт конечно не идеальный но со своими задачами справляется. Главное подать идею для размышления.

Post Created 8

Related Posts

Begin typing your search above and press enter to search. Press ESC to cancel.

Back To Top