Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Code Block
require 'capistrano/ext/multistage'

default_run_options[:shell] = '/bin/bash'

set :application, "features.library.cornell.edu"  # TODO - name your application

default_run_options[:shell] = '/bin/bash'

# based on:
# http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html
# http://www.58bits.com/blog/2013/03/23/deploying-drupal-with-capistrano
# https://github.com/antistatique/capdrupal

#SSH and PTY Options
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
set :use_sudo, false
#set :port, 5144

#On Mac OS X
ssh_options[:compression] = "none"

#Application settings
set :user, ENV['USER']  # can also come from ~/.caprc
set :runner, ENV['USER']  # when sudo-ing use this user
set :runner_group, "lib_web_dev_role"
set :admin_runner, ENV['USER']  # when sudo-ing during :setup use this

set :php_user, "apache" # user php runs as

set :stages, ["local", "staging", "production"] # TODO - define different stages
set :default_stage, "local"

set :keep_releases, 5
set :drush_cmd, "drush"

set :scm, :git
set :repository,  "git@git.library.cornell.edu:features_test_library_cornell_edu.git" # TODO - your git repo here
set :branch, "master"

# prevent errors from missing javascripts,stylesheets,images directories
set :normalize_asset_timestamps, false

# now use the regular cap deploy instead of drupal
#before 'deploy', 'deploy:drush:site_offline', 'drupal:db:backup', 'git:push_deploy_tag'
before 'deploy' do
  git.push_deploy_tag
  drupal.drush.site_offline
  drupal.db.backup
  drupal.drush.site_online
end
#after 'deploy', 'drupal:link_filesystem', 'drupal:drush:set_files_paths', 'drupal:drush:updatedb', 'deploy:drush:site_online'
after 'deploy' do
  drupal.link_filesystem
  drupal.drush.site_offline
  drupal.drush.set_files_paths
  drupal.drush.updatedb
  drupal.drush.revert_features
  drupal.drush.site_online
end

after 'deploy:rollback' do
  drupal.link_filesystem
  drupal.drush.clear_all_caches
  drupal.drush.site_offline
  drupal.db.reload_previous# TODO: list of modules to enable
# drush pm-list | grep Enabled | grep -o '(.\+)' | grep -o '[^()]\+' | tr '\n' ' ' && echo ""

set :enabled_modules, File.open("drupal_config/enabled_modules.txt", "r") { |file| file.read.split(" ") }
# override these in production
set :disabled_modules, File.open("drupal_config/disabled_modules.txt", "r") { |file| file.read.split(" ") }
set :default_theme, File.open("drupal_config/default_theme.txt", "r") { |file| file.read.split(" ") }

#SSH and PTY Options
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
set :use_sudo, false
#set :port, 5144

#On Mac OS X
ssh_options[:compression] = "none"

#Application settings
set :user, ENV['USER']  # can also come from ~/.caprc
set :runner, ENV['USER']  # when sudo-ing use this user
set :runner_group, "lib_web_dev_role"
set :admin_runner, ENV['USER']  # when sudo-ing during :setup use this

set :php_user, "apache" # user php runs as

set :stages, ["local", "staging", "production"] # TODO - define different stages
set :default_stage, "staging"

set :keep_releases, 5
set :drush_cmd, "drush"

set :scm, :git
set :repository,  "git@git.library.cornell.edu:features_test_library_cornell_edu.git" # TODO - your git repo here
set :branch, "master"

# prevent errors from missing javascripts,stylesheets,images directories
set :normalize_asset_timestamps, false

# now use the regular cap deploy instead of drupal
#before 'deploy', 'deploy:drush:site_offline', 'drupal:db:backup', 'git:push_deploy_tag'
before 'deploy' do
  git.push_deploy_tag
  drupal.drush.site_offline
  drupal.db.backup
  drupal.drush.site_online
end

before#after 'drupal:db:grabdeploy', 'drupal:drush:sitelink_offlinefilesystem', 'drupal:drush:clearset_allfiles_cachespaths'
after, 'drupal:dbdrush:grabupdatedb', 'drupaldeploy:drush:site_online'

before 'drupal:db:install', 'drupal:drush:site_offline'
after 'drupal:db:install', 'drupal:drush:after 'deploy' do
  drupal.link_filesystem
  drupal.drush.site_offline
  drupal.drush.set_files_paths',
  'drupal:drush:clear_all_caches', 'drupal:drush:site_online'

before 'drupal:db:install_latest', 'drupal:drush:site_offline'
after 'drupal:db:install_latest', 'drupal:drush:set_files_paths', 'drupal:drush:clear_all_caches', 'drupal:drush:site_online'.drush.enabler(enabled_modules)
  drupal.drush.updatedb
  drupal.drush.disabler(disabled_modules)
  drupal.drush.revert_features
  drupal.drush.set_theme(default_theme)
  drupal.drush.clear_all_caches
  drupal.drush.site_online
end

after 'deploy:setup', 'drupal:site_setup', 'deploy:update', 'drupal:link_filesystem', 'drupal:site_setup_permissions'

after 'drupal:post_install_configurationrollback' do
  drupal.link_filesystem
  drupal.drush.clear_all_caches
  drupal.drush.site_offline
  drupal.db.reload_previous
  drupal.drush.site_online
end

before 'drupal:db:grab', 'drupal:drush:setsite_files_pathsoffline', 'drupal:drush:updatedbclear_all_caches'

after 'drupal:fix_undefined_index:db:grab', 'drupal:drush:site_online'

before 'drupal:db:install', 'drupal:drush:site_offline'
after 'drupal:db:install', 'drupal:drush:set_files_paths', 'drupal:drush:clear_all_caches', '

namespace :deploy do
  task :start do ; end
  task :stop do ; end
  task :restart, :roles => :app, :except => { :no_release => true } do
    #Place holder for app restart - in Ruby apps this would touch restart.txt.
  end
end

#Drupal application and project specific tasks.
namespace :drupal do

  #desc "Perform a Drupal application deploy."
  # see before/after deploy above
  task :defaultdrupal:drush:site_online'

before 'drupal:db:install_latest', 'drupal:drush:site_offline'
after 'drupal:db:install_latest', 'drupal:drush:set_files_paths', 'drupal:drush:clear_all_caches', 'drupal:drush:site_online'

after 'deploy:setup', 'drupal:site_setup', 'deploy:update', 'drupal:link_filesystem', 'drupal:site_setup_permissions'

after 'drupal:post_install_configuration' do
  drupal.drush.set_files_paths
  drupal.drush.enabler(enabled_modules)
  drupal.drush.updatedb
  drupal.drush.disabler(disabled_modules)
  drupal.drush.set_theme(default_theme)
end

after 'drupal:fix_undefined_index', 'drupal:drush:clear_all_caches'

namespace :deploy do
  task :start do ; end
  task :stop do ; end
  task :restart, :roles => :app, :except => { :no_release => true } do
    #Place holder for app restart - in Ruby apps this would touch restart.txt.
  end
end

#Drupal application and project specific tasks.
namespace :drupal do

  desc "Real list of modules to enable"
  task :read_enabled_modules do
    contents = File.open("config/enabled_modules.txt", "r") { |file| file.read }
    return contents
  end

  #desc "Perform a Drupal application deploy."
  # see before/after deploy above
  task :default, :roles => :app, :except => { :no_release => true } do
    site_offline
    clear_all_caches
    backupdb
    deploy.default
    link_filesystem
    set_files_paths
    updatedb
    site_online
  end

  desc "Initial remote setup for Drupal"
  task :site_setup, :roles => :app do
    commands = []
    commands << "mkdir -p #{deploy_to}/backup"
    commands << "mkdir -p #{deploy_to}/cache"
    commands << "mkdir -p #{deploy_to}/files"
    commands << "mkdir -p #{deploy_to}/log"
    commands << "mkdir -p #{deploy_to}/private_files"
    commands << "mkdir -p #{deploy_to}/subsites"
    commands << "mkdir -p #{deploy_to}/tmp"
    run commands.join(' && ') if commands.any?
  end

  #desc "Set permissions for php to write to some directories"
  task :site_setup_permissions, :roles => :app, :except => { :no_release => true } do
    site_offline
    clear_all_caches
    backupdbsudo "chown #{php_user} #{deploy_to}/backup"
    deploy.default
    link_filesystem
    set_files_pathssudo "chown #{php_user} #{deploy_to}/cache"
    updatedb
sudo "chown   site_online#{php_user} #{deploy_to}/files"
  end

  descsudo "Initial remote setup for Drupalchown #{php_user} #{deploy_to}/private_files"
  task :site_setup, :roles => :app do sudo "chown #{php_user} #{deploy_to}/tmp"
    commands = []
    commands << "mkdir -psudo "chown #{php_user} #{deploy_to}/backup"
    commands << "chmod g+w #{deploy_to}/backupsettings.php"
  end

  desc "Get the user to run the Drupal install, then do final configuration"
  task  commands << "mkdir -p #{deploy_to}/cache":post_install_configuration, :roles => :app do
    commandsservers << "mkdir -p #{deploy_to}/files"
    commands << "mkdir -p #{deploy_to}/log"
    commands << "mkdir -p #{deploy_to}/private_files"
    commands << "mkdir -p #{deploy_to}/subsites= find_servers_for_task(current_task)
    server = servers.first
    default_ans = 'yes'
    ans = Capistrano::CLI.ui.ask "Have you run http://#{server}/install.php? [#{default_ans}]"
    commandsans << "mkdir -p #{deploy_to}/tmp"
= default_ans if ans.empty?
    abort run commands.join(' && ') if commands.any?"Please install Drupal first" if ans != default_ans
  end

  #desc "SetThis permissionsshould fornot phpbe torun writeon to some directories"
  task :site_setup_permissions, :roles => :app do
    sudo "chown #{php_user} #{deploy_to}/backup"
    sudo "chown #{php_user} #{deploy_to}/cache"
    sudo "chown #{php_user} #{deploy_to}/files"
    sudo "chown #{php_user} #{deploy_to}/private_files"
    sudo "chown #{php_user}its own - so comment out the description.
  # "Recreate the required Drupal symlinks to static directories and clear all caches."
  task :link_filesystem, :roles => :app, :except => { :no_release => true } do
    commands = []
    commands << "if [ ! -f #{deploy_to}/tmp"
    sudo "chown #{php_user}settings.php ]; then cp #{app_path}/sites/default/default.settings.php #{deploy_to}/settings.php"
  end

  desc "Get the user to run the Drupal install, then do final configuration"
  task :post_install_configuration, :roles => :app do
    servers = find_servers_for_task(current_task); fi"
    commands << "cat /dev/null > #{app_path}/.htaccess"
    commands << "mkdir -p #{app_path}/sites/default"
    servercommands = servers.first
    default_ans = 'yes'<< "ln -nfs #{share_path}/settings.php #{app_path}/sites/default/settings.php"
    anscommands = Capistrano::CLI.ui.ask "Have you run http://#{server}/install.php? [#{default_ans}]<< "ln -nfs #{share_path}/files #{app_path}/sites/default/files"
    ans = default_ans if ans.empty?commands << "ln -nfs #{share_path}/tmp #{app_path}/sites/default/tmp"
    abortcommands "Please install Drupal first" if ans != default_ans
  end

  #desc "This should not be run on its own - so comment out the description.
  # "Recreate the required Drupal symlinks to static directories and clear all caches."
  task :link_filesystem, :roles => :app, :except => { :no_release => true } do
    commands = []
    commands << "if [ ! -f #{deploy_to}/settings.php ]; then cp #{app_path}/sites/default/default.settings.php #{deploy_to}/settings.php; fi"
    commands << "cat /dev/null > #{app_path}/.htaccess"
    commands << "mkdir -p #{app_path}/sites/default"
    commands << "ln -nfs #{share_path}/settings.php #{app_path}/sites/default/settings.php"
    commands << "ln -nfs #{share_path}/files #{app_path}/sites/default/files"
    commands << "ln -nfs #{share_path}/tmp #{app_path}/sites/default/tmp"
    commands << "ln -nfs #{share_path}/cache #{app_path}/cache"
    commands << "find #{app_path} -type d -print0 | xargs -0 chmod 755"
    commands << "find #{app_path} -type f -print0 | xargs -0 chmod 644"
    run commands.join(' && ') if commands.any?
  end

  namespace :db do

    desc "returns a stage and time stamped backup file name"
    def backup_file_name(stage)
      backup_time = release_name # use capistrano's variable %Y%m%d%H%M%S
      return make_backup_file_name(stage, backup_time)
    end

    def make_backup_file_name(stage, backup_time)
      filename = "backup/#{stage}-snapshot-#{backup_time}.sql"
      return filename<< "ln -nfs #{share_path}/cache #{app_path}/cache"
    commands << "find #{app_path} -type d -print0 | xargs -0 chmod 755"
    commands << "find #{app_path} -type f -print0 | xargs -0 chmod 644"
    run commands.join(' && ') if commands.any?
  end

  namespace :db do

    desc "returns a stage and time stamped backup file name"
    def backup_file_name(stage)
      backup_time = release_name # use capistrano's variable %Y%m%d%H%M%S
      return make_backup_file_name(stage, backup_time)
    end

    def make_backup_file_name(stage, backup_time)
      filename = "backup/#{stage}-snapshot-#{backup_time}.sql"
      return filename
    end

    desc "gets the most recent database backup file with a given prefix"
    def latest_backup(backup_prefix)
      tmax = Time.at 0
      latestfile = nil
      Dir.glob("backup/#{backup_prefix}-snapshot-*") do |filename|
        mt = File.mtime(filename)
        if mt > tmax
          tmax = mt
          latestfile = filename
        end
      end
      return latestfile
    end

    desc "upload and install database"
    def upload_install(filename)
      puts "uploading #{filename}"
      top.upload("#{filename}", "#{deploy_to}/#{filename}")
      puts "loading drupal with database"
      drush.load_drupal("#{deploy_to}/#{filename}")
    end

    desc "getsbackup the most recent database backup file with a given prefix"
    deftask latest_backup(backup_prefix)
      tmax = Time.at 0
      latestfile = nil
      Dir.glob("backup/#{backup_prefix}-snapshot-*") do |filename|:backup, :roles => :app, :except => { :no_release => true } do
        mtbackup_file = File.mtime(filenamebackup_file_name(stage)
        if mt > tmaxdrush.dump_drupal(backup_file)
      puts "#{backup_file}"
   tmax = mtend

    desc "Grab local copy of  latestfile = filenameremote database"
    # cap   endproduction drupal:db:grab
    task  end
      return latestfile
    end

:grab, :roles => :app, :except => { :no_release => true } do
    desc "upload andbackup_file install database"= backup_file_name(stage)
    def  uploaddrush.dump_installdrupal(filenamebackup_file)
      puts "uploading #{filenamebackup_file}"
      top.upload("#{filenamedownload "#{deploy_to}/#{backup_file}", "#{deploy_to}/#{filenamebackup_file}")
      puts "loading drupal with database"end

      drush.load_drupal("#{deploy_to}/#{filename}")
    end

    desc "backup the database"desc "Install latest local database snapshot"
    # cap staging drupal:db:install_latest -s from=production
    task :backupinstall_latest, :roles => :app, :except => { :no_release => true } do
      backup_file = backup_file_name(stage)
      drush.dump_drupal(backup_fileset :source_stage, fetch(:from, '')
      puts "#{backup_file}"if source_stage.empty?
    end

    descputs "Grabuseage:"
 local copy of remote database"
   abort # "cap productionstaging drupal:db:grab
    task :grab, :roles => :app, :except => { :no_release => true } do
install_latest -s from=production"
      else
         backup_filefilename = latest_backup(source_file_name(stage)
        if drush.dump_drupal(backup_file)
filename.nil?
       puts "#{backup_file}"
      download "#{deploy_to}/#{backup_file}", "#{backup_file}"
    end

    desc "Install latest local database snapshot"   abort "first grab a copy of the datatbase: cap #{source_stage} drupal:db:grab"
        else
    # cap staging drupal:db:install_latest -s from=production
 puts "Moving database task :install_latest, :roles => :app, :except => { :no_release => true } dofrom #{source_stage} to #{stage}"
          upload_install(filename)
      set :source_stage, fetch(:from, '') end
      if source_stage.empty?end
    end

    putsdesc "useage:"
    Install a specific local database snapshot"
    abort# "cap staging drupal:db:install_latest -s from=production"
      elsefile=backup/staging-snapshot-2013-10-25-13-17-23.sql
    task :install, :roles => :app, :except => { :no_release => true } do
      set   :filename, = latest_backup(source_stage)
 fetch(:file, '')
       if filename.nilempty?
        puts "useage:"
    abort "first grab a copyabort of"cap thestaging datatbasedrupal:db:install cap #{source_stage} drupal:db:grab"
  -s file=backup/production-snapshot-2013-10-25-13-17-23.sql"
      else
          puts "Moving database from #{source_stagefilename} to #{stage}"
          upload_install(filename)
        end
      end
    end

    desc "Install a specific local database snapshot"
    # cap staging drupal:db:install -s file=backup/staging-snapshot-2013-10-25-13-17-23.sqlreload database from previous release"
    task :installreload_previous, :roles => :app, :except => { :no_release => true } do
      set :filename, fetch(:file, '')
      if filename.empty?
        puts "useage:"
        abort "cap staging drupal:db:install -s file=backup/production-snapshot-2013-10-25-13-17-23.sql"previous_release_name = File.basename(previous_release)
      else
  filename = make_backup_file_name(stage, previous_release_name)
      puts "Movingreloading database from #{filename} to #{stage}"
        upload_install(filenamedrush.load_drupal("#{deploy_to}/#{filename}")
    end

  end

  namespace :drush enddo

    desc "reloadBackup the database from previous release."
    task :reload_previousbackupdb, :roleson_error => :app, :except => { :no_release => true } docontinue do
      run "#{drush_cmd} -r #{app_path} sql-dump --result-file=#{deploy_to}/backup/release-drupal-db.sql"
    end

    #desc  previous_release_name = File.basename(previous_release)
      filename = make_backup_file_name(stage, previous_release_name)"Backup the database"
    # we don't want to require backup_migrate
    task  puts "reloading database from #{filename}":backupdb_bam, :on_error => :continue do
      drush.load_drupal(run "#{deploydrush_to}/cmd} -r #{filename}")
    end

app_path} bam-backup"
    end

  namespace :drush do

    desc "BackupClear theall database.caches"
    task :backupdb, :on_errorclear_all_caches, :roles => :app, :except => { :no_release => :continuetrue } do
      run "#{drush_cmd} -r #{app_path} sql-dump --result-file-uri=#{deploydrush_to}/backup/release-drupal-db.sql"
    end

    #desc "Backup the database"
    # we don't want to require backup_migrate
    task :backupdb_bam, :on_error => :continue douri} cc all"
    end

    desc "error message fix - undefined index: <name, version>"
    # see https://drupal.org/node/1170362
    task :fix_undefined_index, :roles => :app, :except => { :no_release => true } do
      run "#{drush_cmd} -r #{app_path} vset --yes install_profile \"standard\""
      run "#{drush_cmd} -r #{app_path} bam-backupsql-query \"UPDATE system SET status=1 WHERE name='standard';\""
    end

    desc "ClearRevert all caches features to install the newest versions"
    task :clearrevert_all_cachesfeatures, :roles => :app, :except => { :no_releaseon_error => true }:continue do
      run "#{drush_cmd} -r #{app_path} features--uri=#{drush_uri} cc allrevert-all -y"
    end

    desc "errorset messagethe fixprivate_files -& undefinedtmp index:path <name, version>"
    # see https://drupal.org/node/1170362for the deploy environment"
    task :fixset_undefined_index, :roles => :app, :except => { :no_releasefiles_paths, :on_error => true:continue } do
      run "#{drush_cmd} -r #{app_path} vset --yes installfile_public_profile \"standard\""path sites/default/files"
      run "#{drush_cmd} -r #{app_path} vset sql-query \"UPDATE system SET status=1 WHERE name='standard';\""--yes file_private_path #{deploy_to}/private_files"
      run "#{drush_cmd} -r #{app_path} vset --yes file_temporary_path sites/default/tmp"
    end

    desc "Revert all features to install Set the newestsite versionsoffline"
    task :revertsite_featuresoffline, :on_error => :continue do do
      run "#{drush_cmd} -r #{app_path} vset site_offline 1 -y"
      run "#{drush_cmd} -r #{app_path} features-revert-all vset maintenance_mode 1 -y"
    end

    desc "setSet the private_files & tmp path for the deploy environment"
    task :set_files_paths, :on_error => :continue do
      run "#{drush_cmd} -r #{app_path} vset --yes file_public_path sites/default/files"site online"
    task :site_online, :on_error => :continue do
      run "#{drush_cmd} -r #{app_path} vset --yes file_private_path #{deploy_to}/private_filessite_offline 0 -y"
      run "#{drush_cmd} -r #{app_path} vset --yes file_temporary_path sites/default/tmpmaintenance_mode 0 -y"
    end

    desc "Set the site offline
    desc "Run Drupal database updates for new core/modules/themes if required."
    task :site_offlineupdatedb, :on_error => :continue do
      run "#{drush_cmd} -r #{app_path} vset site_offline 1 -y"
      run "#{drush_cmd} -r #{app_path} vset maintenance_mode 1 -updatedb -y"
    end

    desc "Setbackup the site online Drupal database to a timestamped file"
    taskdef :site_online, :on_error => :continue dodump_drupal(filename)
      run "#{drush_cmd} -r #{app_path} vset site_offline 0 -y"} sql-dump --result-file=#{deploy_to}/#{filename}"
    end

    desc "load the Drupal database from an sql dump"
    def load_drupal(filename)
      run "#`#{drush_cmd} -r #{app_path} vset maintenance_mode 0 -ysql-connect` < #{filename}"
    end

    desc "Runenable Drupalan databasearray updates for new core/modules/themes if required.of modules"
    task :updatedb, :on_error => :continue do
def enabler(modules)
       run "#{drush_cmd} -r #{app_path} updatedb pm-enable -y #{modules.join(' ')}"
    end

    desc "backupdisable thean Drupalarray database to a timestamped fileof modules"
    def dump_drupaldisabler(filenamemodules)
       run "#{drush_cmd} -r #{app_path} sqlpm-dumpdisable --result-file=#{deploy_to}/#{filename}y #{modules.join(' ')}"
    end

    desc "loadset the Drupal database from an sql dumpdefault theme"
    def loadset_drupaltheme(filenametheme)
      run "`##{drush_cmd} -r #{app_path} sql-connect` <vset theme_default #{filenametheme}"
    end


  end

end


namespace :git do

  desc "Place release tag into Git and push it to origin server."
  task :push_deploy_tag do
    user = `git config --get user.name`
    email = `git config --get user.email`
    tag = "release_#{release_name}"
    if exists?(:stage)
      tag = "#{stage}_#{tag}"
    end
    puts `git tag #{tag} #{revision} -m "Deployed by #{user} <#{email}>"`
    puts `git push origin tag #{tag}`
  end

end

namespace :explore do
  desc "Local variables"
  task :locals, :on_error => :continue do
    local_variables.each {|var| puts "#{var} fetch(:#{var})"}
    puts "shared_path #{shared_path}"
    puts "stage #{stage}"
    puts "args #{args}"
    puts "release_name #{release_name}"
    puts "previous_revision #{previous_revision}"
    puts "current_revision #{current_revision}"
    # deploy.instance_variables.map do |var|
    #   puts [var, deploy.instance_variable_get(var)].join(":")
    # end
  end

  desc "check paths for mysql and mysqldump"
  task :check_mysql, :on_error => :continue do
    puts "$PATH"
    run "echo $PATH"
    puts "Which mysql?"
    run "which mysql"
    puts "Which mysqldump?"
    run "which mysqldump"
    puts "connect statement:"
    run "#{drush_cmd} -r #{app_path} sql-connect"
  end

  desc "test du jour"
  task :testdujour, :on_error => :continue do
    mysqlcmd = %x[ echo `#{drush_cmd} -r #{app_path} sql-connect` ]
    puts "mysql command: #{mysqlcmd}"
    puts "current_path #{current_path}"
    puts "deploy_to #{deploy_to}"
  end

  desc "find code for a task"
  task :find, :on_error => :continue do
    # load all the tasks associated with the rails app
    Rails.application.load_tasks

    # get the source locations of actions called by a task
    task_name = 'deploy:cold' # fully scoped task name
    Rake.application[task_name].actions.map(&:source_location)
  end

  desc "try out enabler"
  task :tryout do
    modules = ['aaa', 'bbb', 'ccc', 'ploop']
    drupal.drush.enabler(modules)
  end

end