diff --git a/site-cookbooks/liquor_cabinet/.gitignore b/site-cookbooks/liquor_cabinet/.gitignore new file mode 100644 index 0000000..f1e57b8 --- /dev/null +++ b/site-cookbooks/liquor_cabinet/.gitignore @@ -0,0 +1,25 @@ +.vagrant +*~ +*# +.#* +\#*# +.*.sw[a-z] +*.un~ + +# Bundler +Gemfile.lock +gems.locked +bin/* +.bundle/* + +# test kitchen +.kitchen/ +kitchen.local.yml + +# Chef Infra +Berksfile.lock +.zero-knife.rb +Policyfile.lock.json + +.idea/ + diff --git a/site-cookbooks/liquor_cabinet/CHANGELOG.md b/site-cookbooks/liquor_cabinet/CHANGELOG.md new file mode 100644 index 0000000..feaf621 --- /dev/null +++ b/site-cookbooks/liquor_cabinet/CHANGELOG.md @@ -0,0 +1,7 @@ +# liquor_cabinet CHANGELOG + +This file is used to list changes made in each version of the liquor_cabinet cookbook. + +## 0.1.0 + +Initial release. diff --git a/site-cookbooks/liquor_cabinet/LICENSE b/site-cookbooks/liquor_cabinet/LICENSE new file mode 100644 index 0000000..a00749b --- /dev/null +++ b/site-cookbooks/liquor_cabinet/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Kosmos Developers + +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. diff --git a/site-cookbooks/liquor_cabinet/README.md b/site-cookbooks/liquor_cabinet/README.md new file mode 100644 index 0000000..1f7bc27 --- /dev/null +++ b/site-cookbooks/liquor_cabinet/README.md @@ -0,0 +1,6 @@ +# liquor_cabinet + +Installs/configures the [Liquor Cabinet][1] [remoteStorage][2] API server. + +[1]: https://gitea.kosmos.org/5apps/liquor-cabinet +[2]: https://remotestorage.io diff --git a/site-cookbooks/liquor_cabinet/attributes/default.rb b/site-cookbooks/liquor_cabinet/attributes/default.rb new file mode 100644 index 0000000..6e88013 --- /dev/null +++ b/site-cookbooks/liquor_cabinet/attributes/default.rb @@ -0,0 +1,24 @@ +node.default['liquor-cabinet']['ruby']['version'] = "3.1.4" +node.default['liquor-cabinet']['repo'] = 'https://gitea.kosmos.org/5apps/liquor-cabinet.git' +node.default['liquor-cabinet']['revision'] = 'master' +node.default['liquor-cabinet']['redis_server_role'] = 'redis_server' +node.default['liquor-cabinet']['redis_port'] = 6379 +node.default['liquor-cabinet']['redis_db'] = 1 +node.default['liquor-cabinet']['s3_endpoint'] = nil +node.default['liquor-cabinet']['s3_region'] = nil +node.default['liquor-cabinet']['s3_bucket'] = nil +node.default['liquor-cabinet']['ufw_source_allowed'] = nil +node.default['liquor-cabinet']['maintenance_mode_enabled'] = false +node.default['liquor-cabinet']['rainbows'] = { + 'port' => 3000, + 'preload_app' => true, + 'timeout' => 60, + 'worker_processes' => node['cpu']['total'], + 'worker_connections' => 100, + 'client_header_buffer_size' => 1024, + 'client_max_body_size' => 104857600, + 'client_max_header_size' => 114688, + 'copy_stream' => 'IO', + 'keepalive_requests' => 100, + 'keepalive_timeout' => 5 +} diff --git a/site-cookbooks/liquor_cabinet/chefignore b/site-cookbooks/liquor_cabinet/chefignore new file mode 100644 index 0000000..cc170ea --- /dev/null +++ b/site-cookbooks/liquor_cabinet/chefignore @@ -0,0 +1,115 @@ +# Put files/directories that should be ignored in this file when uploading +# to a Chef Infra Server or Supermarket. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +ehthumbs.db +Icon? +nohup.out +Thumbs.db +.envrc + +# EDITORS # +########### +.#* +.project +.settings +*_flymake +*_flymake.* +*.bak +*.sw[a-z] +*.tmproj +*~ +\#* +REVISION +TAGS* +tmtags +.vscode +.editorconfig + +## COMPILED ## +############## +*.class +*.com +*.dll +*.exe +*.o +*.pyc +*.so +*/rdoc/ +a.out +mkmf.log + +# Testing # +########### +.circleci/* +.codeclimate.yml +.delivery/* +.foodcritic +.kitchen* +.mdlrc +.overcommit.yml +.rspec +.rubocop.yml +.travis.yml +.watchr +.yamllint +azure-pipelines.yml +Dangerfile +examples/* +features/* +Guardfile +kitchen.yml* +mlc_config.json +Procfile +Rakefile +spec/* +test/* + +# SCM # +####### +.git +.gitattributes +.gitconfig +.github/* +.gitignore +.gitkeep +.gitmodules +.svn +*/.bzr/* +*/.git +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Bundler # +########### +vendor/* +Gemfile +Gemfile.lock + +# Policyfile # +############## +Policyfile.rb +Policyfile.lock.json + +# Documentation # +############# +CODE_OF_CONDUCT* +CONTRIBUTING* +documentation/* +TESTING* +UPGRADING* + +# Vagrant # +########### +.vagrant +Vagrantfile diff --git a/site-cookbooks/liquor_cabinet/kitchen.yml b/site-cookbooks/liquor_cabinet/kitchen.yml new file mode 100644 index 0000000..e309743 --- /dev/null +++ b/site-cookbooks/liquor_cabinet/kitchen.yml @@ -0,0 +1,37 @@ +--- +driver: + name: dokken + privileged: true # allows systemd services to start + +provisioner: + name: dokken + +transport: + name: dokken + +verifier: + name: inspec + +platforms: + # @see https://github.com/chef-cookbooks/testing_examples/blob/main/kitchen.dokken.yml + # @see https://hub.docker.com/u/dokken + - name: ubuntu-20.04 + driver: + image: dokken/ubuntu-20.04 + pid_one_command: /bin/systemd + intermediate_instructions: + - RUN /usr/bin/apt-get update + + - name: centos-8 + driver: + image: dokken/centos-8 + pid_one_command: /usr/lib/systemd/systemd + +suites: + - name: default + run_list: + - recipe[liquor_cabinet::default] + verifier: + inspec_tests: + - test/integration/default + attributes: diff --git a/site-cookbooks/liquor_cabinet/metadata.rb b/site-cookbooks/liquor_cabinet/metadata.rb new file mode 100644 index 0000000..bd24a4c --- /dev/null +++ b/site-cookbooks/liquor_cabinet/metadata.rb @@ -0,0 +1,12 @@ +name 'liquor_cabinet' +maintainer 'Kosmos Developers' +maintainer_email 'ops@kosmos.org' +license 'MIT' +description 'Installs/configures the Liquor Cabinet remoteStorage API server' +version '0.1.0' +chef_version '>= 18.2' +issues_url 'https://gitea.kosmos.org/kosmos/chef/issues' +# source_url 'https://gitea.kosmos.org/kosmos/chef' + +depends 'firewall' +depends "ruby_build" diff --git a/site-cookbooks/liquor_cabinet/recipes/default.rb b/site-cookbooks/liquor_cabinet/recipes/default.rb new file mode 100644 index 0000000..ebf6b0e --- /dev/null +++ b/site-cookbooks/liquor_cabinet/recipes/default.rb @@ -0,0 +1,139 @@ +# +# Cookbook:: liquor_cabinet +# Recipe:: default +# + +app_name = "liquor-cabinet" +deploy_user = "deploy" +deploy_group = "deploy" +deploy_path = "/opt/#{app_name}" +credentials = Chef::EncryptedDataBagItem.load('credentials', app_name) + +ruby_version = node[app_name]['ruby']['version'] +ruby_path = "/opt/ruby_build/builds/#{ruby_version}" +bundle_path = "#{ruby_path}/bin/bundle" +rack_env = node.chef_environment == "production" ? "production" : "development" + +ruby_build_install 'v20231225' +ruby_build_definition ruby_version do + prefix_path ruby_path +end + +group deploy_group + +user deploy_user do + group deploy_group + manage_home true + shell "/bin/bash" +end + +directory deploy_path do + owner deploy_user + group deploy_group + mode '0750' +end + +redis_server_role = node[app_name]['redis_server_role'] +redis_host = search(:node, "role:#{redis_server_role}").first['knife_zero']['host'] rescue nil +if redis_host.nil? + Chef::Log.warn("No node found with '#{redis_server_role}' role. Stopping here.") + return +end + +git deploy_path do + repository node[app_name]['repo'] + revision node[app_name]['revision'] + user deploy_user + group deploy_group + notifies :restart, "service[#{app_name}]", :delayed +end + +directory "#{deploy_path}/tmp" do + owner deploy_user + group deploy_group + mode 0750 +end + +execute "bundle install" do + user deploy_user + cwd deploy_path + command "#{bundle_path} install --without development,test --deployment" +end + +template "#{deploy_path}/config.yml.erb" do + source 'config.yml.erb' + owner deploy_user + group deploy_group + mode '0600' + sensitive true + variables environment: rack_env, + redis_host: redis_host, + redis_port: node[app_name]['redis_port'], + redis_db: node[app_name]['redis_db'], + s3_endpoint: node[app_name]['s3_endpoint'], + s3_region: node[app_name]['s3_region'], + s3_bucket: node[app_name]['s3_bucket'], + s3_access_key: credentials['s3_access_key'], + s3_secret_key: credentials['s3_secret_key'], + maintenance_mode_enabled: node[app_name]['maintenance_mode_enabled'] + # TODO sentry_dsn: credentials['sentry_dsn'] + notifies :restart, "service[#{app_name}]", :delayed +end + +directory '/etc/rainbows' do + owner deploy_user + group deploy_group + mode '0750' +end + +template "/etc/rainbows/#{app_name}.rb" do + source 'rainbows.rb.erb' + owner deploy_user + group deploy_group + mode '0640' + variables user: deploy_user, + group: deploy_group, + app_name: app_name, + working_directory: deploy_path, + config: node[app_name]['rainbows'] + notifies :restart, "service[#{app_name}]", :delayed +end + +systemd_unit "#{app_name}.service" do + content({ + Unit: { + Description: "Liquor Cabinet remoteStorage HTTP API", + Documentation: ["https://gitea.kosmos.org/5apps/liquor-cabinet"], + After: "syslog.target network.target" + }, + Service: { + Type: "simple", + User: deploy_user, + WorkingDirectory: deploy_path, + Environment: "RACK_ENV=#{rack_env}", + ExecStart: "#{bundle_path} exec rainbows -c /etc/rainbows/#{app_name}.rb -E #{rack_env}", + PIDFile: "#{deploy_path}/tmp/rainbows.pid", + TimeoutSec: "10", + Restart: "on-failure", + }, + Install: { + WantedBy: "multi-user.target" + } + }) + verify false + triggers_reload true + action [:create, :enable] +end + +service app_name do + action [:enable, :start] +end + +if node[app_name]['ufw_source_allowed'] + firewall_rule app_name do + command :allow + protocol :tcp + port node[app_name]['rainbows']['port'] + source node[app_name]['ufw_source_allowed'] + end +end diff --git a/site-cookbooks/liquor_cabinet/templates/config.yml.erb b/site-cookbooks/liquor_cabinet/templates/config.yml.erb new file mode 100644 index 0000000..615d28d --- /dev/null +++ b/site-cookbooks/liquor_cabinet/templates/config.yml.erb @@ -0,0 +1,12 @@ +<%= @environment %>: + maintenance: <%= @maintenance_mode_enabled %> + redis: + host: <%= @redis_host %> + port: <%= @redis_port %> + db: <%= @redis_db %> + s3: + endpoint: <%= @s3_endpoint %> + region: <%= @s3_region %> + bucket: <%= @s3_bucket %> + access_key_id: <%= @s3_access_key %> + secret_key_id: <%= @s3_secret_key %> diff --git a/site-cookbooks/liquor_cabinet/templates/rainbows.rb.erb b/site-cookbooks/liquor_cabinet/templates/rainbows.rb.erb new file mode 100644 index 0000000..4cf5125 --- /dev/null +++ b/site-cookbooks/liquor_cabinet/templates/rainbows.rb.erb @@ -0,0 +1,32 @@ +## +# Rainbows config at /etc/rainbows/<%= @app_name %>.rb +# Managed by Chef - Local changes will be overwritten by Chef runs +## + +# What ports/sockets to listen on, and what options for them. +listen "<%= @config['port'] %>", { tcp_nodelay: true, backlog: 100 } + +# What the timeout for killing busy workers is, in seconds +timeout <%= @config['timeout'] %> + +# Whether the app should be pre-loaded +preload_app <%= @config['preload_app'] %> + +# How many worker processes +worker_processes <%= @config['worker_processes'] %> + +# Run forked children as specified user/group +user "<%= @user %>", "<%= @group %>" + +pid "<%= @working_directory %>/tmp/rainbows.pid" + +Rainbows! do + use :ThreadSpawn + client_header_buffer_size <%= @config['client_header_buffer_size'] %> + client_max_body_size <%= @config['client_max_body_size'] %> + client_max_header_size <%= @config['client_max_header_size'] %> + copy_stream <%= @config['copy_stream'] %> + keepalive_requests <%= @config['keepalive_requests'] %> + keepalive_timeout <%= @config['keepalive_timeout'] %> + worker_connections <%= @config['worker_connections'] %> +end