togatttiのエンジニアメモ

過度な期待はしないでください.

Designate の413エラーの対処

OpenStack Designate で、ゾーン登録時に、エラーが出たので対応方法を残しておく。

下記の作業は、designateが置いてあるホストで、行う。

事象

ゾーン登録時に、下記のエラーが出た。

413 Request Entity Too Large

ソースコードを調べると、どうやら、Designateで持っているゾーン登録の閾値に達しているらしい。

github.com

ゾーンの上限値は、10。

$ curl http://localhost:9001/v1/quotas/noauth-project
{
  "api_export_size": 1000,
  "recordset_records": 20,
  "zone_records": 500,
  "zone_recordsets": 500,
  "zones": 10
}
対応

ゾーン登録の上限値を更新する。

designate.confのapiのquotasを有効にしていることを確認する。

$ grep 'quotas' /var/lib/designate/etc/designate/designate.conf
enabled_extensions_v1 = diagnostics, quotas, reports, sync, touch
enabled_extensions_v2 = quotas, reports

API経由で、上限値を更新する。

$ curl -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"zones": 100}' http://localhost:9001/v1/quotas/noauth-project
{
  "api_export_size": 1000,
  "recordset_records": 20,
  "zone_records": 500,
  "zone_recordsets": 500,
  "zones": 100
}
参考

Quotas — designate 2.0.0.0b3.dev57 documentation

OpenStack Keystoneで、Designateを認証する

Designateは、既にインストールされていることを前提とする。

OpenStack Designate を試す : あかぎメモ

ちなみに、これで、Designate の仮装環境を用意した。

ここで紹介すること

  • KeyStone セットアップ
  • テナント登録
  • DesignateへのKeystone設定
  • Keystoneを使った認証デモ

OSは、Ubuntu14.04を使う。

Keystone セットアップ

インストール
# apt-get -y update 
# apt-get -y install keystone
データベース、ユーザ作成

データベースは、MariaDBを使う。

# mysql -uroot -e "CREATE DATABASE keystone;"
# mysql -uroot -e "GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';"
# mysql -uroot -e "GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';"
管理トークン発行
# openssl rand -hex 10
b5fca4a6d7e3ba1d69ac
設定ファイル変更

管理トークン、データベース、ログディレクトリ情報を追記する。

# diff -u /etc/keystone.conf.sample /etc/keystone/keystone.conf
--- /etc/keystone.conf.sample    2016-01-14 16:59:04.665864893 +0900
+++ /etc/keystone.conf  2016-01-15 10:58:45.350297815 +0900
@@ -10,6 +10,7 @@
 # paste application pipelines (for example, in keystone-paste.ini). (string
 # value)
 #admin_token = ADMIN
+admin_token = b5fca4a6d7e3ba1d69ac

 # The base public endpoint URL for Keystone that is advertised to clients
 # (NOTE: this does NOT affect how Keystone listens for connections). Defaults
@@ -141,6 +142,7 @@
 # is ignored if log_config_append is set. (string value)
 # Deprecated group/name - [DEFAULT]/logdir
 #log_dir = <None>
+log_dir = /var/log/keystone

 # (Optional) Uses logging handler designed to watch file system. When log file
 # is moved or removed this handler will open a new log file with specified path
@@ -560,6 +562,7 @@
 # Deprecated group/name - [DATABASE]/sql_connection
 # Deprecated group/name - [sql]/connection
 #connection = <None>
+connection = mysql://keystone:keystone@127.0.0.1/keystone

 # The SQLAlchemy connection string to use to connect to the slave database.
 # (string value)
ログディレクトリ作成
# mkdir /var/log/keystone
# chown keystone:keystone /var/log/keystone
テーブル作成
# keystone-manage db_sync
起動
# service keystone restart
keystone stop/waiting
keystone start/running, process 7461

エンドポイントにアクセスできていれば、正しく起動している。

$ curl -s http://127.0.0.1:5000/v2.0
{"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://127.0.0.1:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}}

Keystone へテナント、ユーザ、ロール作成

python-keyclientを使用する。

python-keyclient インストール
# git clone https://github.com/openstack/python-keystoneclient.git
# cd ~/python-keystoneclient
# python install -r requirements.txt
Keystoneにテナントやユーザ、ロールを作成するPython スクリプト

Designateのエンドポイント http://10.200.19.40:9001/v1 に対して、

DNSaasというテナントを作成する。

adminUserというユーザに対して、パスワードは、secretwordでユーザ作成する。

#!/usr/bin/python
# ./keystone_create.py

from keystoneclient.v2_0 import client

component_url = 'http://10.200.19.40:9001/v1'
token = 'b5fca4a6d7e3ba1d69ac'
endpoint = 'http://10.200.19.40:35357/v2.0'
tenant_name = 'DNSaas'
description = 'test'
username = 'adminUser'
password = 'secretword'
role = 'admin'
service_name='designate'
service_type='dnsaas'

keystone = client.Client(token=token, endpoint=endpoint)
print keystone

print keystone.tenants.create(
        tenant_name=tenant_name, 
        description=description, 
        enabled=True)

tenants = keystone.tenants.list()
my_tenant = [x for x in tenants if x.name == tenant_name][0]
my_user = keystone.users.create(
        name=username, 
        password=password, 
        tenant_id=my_tenant.id)

role = keystone.roles.create(role)

keystone.roles.add_user_role(my_user, role, my_tenant)
service = keystone.services.create(
        name=service_name, 
        service_type=service_type, 
        description=description)
keystone.endpoints.create(
        region='RegionOne', 
        service_id = service.id,
        publicurl=component_url,
        adminurl=component_url,
        internalurl=component_url)

管理用トークンをヘッダーに追加して、登録されたテナントを確認する。

$ curl -H 'X-Auth-Token: b5fca4a6d7e3ba1d69ac' http://10.200.19.40:35357/v2.0/tenants
{"tenants_links": [], "tenants": [{"description": "hoge", "enabled": true, "id": "beac3004ba344ddc8d4e9be13e77ce0e", "name": "DNSaas"}]}

Designateで、Keystone認証

designate.confに、以下を追加、変更する。

認証方法に関して、

auth_strategy = keystone

認証トークンに関して、

[keystone_authtoken]
auth_host = 127.0.0.1
auth_port = 35357
auth_protocol = http
admin_tenant_name = DNSaas
admin_user = adminUser
admin_password = secretword

Designateを再起動する。

# cd /etc/init.d
# ls designate-* | xargs -I@ service @ restart

通常アクセスした時に、認証エラーになることを確認する。

# curl http://127.0.0.1:9001/v1
Authentication required
Keystone 認証
  1. Keystoneに、ユーザとパスワード情報を渡す。テナントへのアクセストークンを発行する。
  2. テナントへのアクセストークンとテナント名をKeystoneに渡して、Designateへのアクセストークンを発行する。
  3. アクセストークンを用いて、Designateのエンドポイントへアクセスする。
# アクセストークンを取得するPython スクリプト
#!/usr/bin/python

import json
from httplib import HTTPConnection

keystone_unscoped = '127.0.0.1:5000'
username='adminUser'
password='secretword'

conn = HTTPConnection(keystone_unscoped)
header = {'Content-Type':'application/json'}
req = {'auth': {'passwordCredentials': {'username': username, 'password': password }}}
json_req = json.dumps(req)
conn.request('POST','/v2.0/tokens', json_req, header)
json_res = json.loads(conn.getresponse().read())
access_token_id = json_res["access"]["token"]["id"]
conn.close()

conn = HTTPConnection(keystone_unscoped)
header = {'X-Auth-Token': access_token_id, 'Content-Type':'application/json'}
conn.request('GET', '/v2.0/tenants', None, header)
print json.dumps(json.load(conn.getresponse()), indent=2)
conn.close()

tenant = raw_input("\ntenant name: ")
conn = HTTPConnection(keystone_unscoped)
header = {'Content-Type':'application/json'}
req = {'auth': {'tenantName': tenant, 'token': {'id':access_token_id}}}
json_req = json.dumps(req)
conn.request('POST', '/v2.0/tokens', json_req, header)
json_res = json.loads(conn.getresponse().read())
print "===== below is access_token ====="
print json_res["access"]["token"]["id"]
conn.close()

使い方

$ chmod 755 ./get_auth_token.py
$ ./get_auth_token.py
{
  "tenants": [
    {
      "enabled": true,
      "description": "test",
      "name": "DNSaas",
      "id": "5a30147f9c184fc6b618fc16e06c2b66"
    }
  ],
  "tenants_links": []
}

tenant name: DNSaas
===== below is access_token =====
MIIE-QYJKoZIhvcNAQcCoIIE7jCCBOoCAQExDTALBglghkgBZQMEAgEwggNLBgkqhkiG9w0BBwGgggM8BIIDOHsiYWNjZXNzIjogeyJ0b2tlbiI6IHsiaXNzdWVkX2F0IjogIjIwMTYtMDItMDlUMDM6MjE6NTYuMjM5MTU4IiwgImV4cGlyZXMiOiAiMjAxNi0wMi0wOVQwNDoyMTo1MloiLCAiaWQiOiAicGxhY2Vob2xkZXIiLCAidGVuYW50IjogeyJkZXNjcmlwdGlvbiI6ICJ0ZXN0IiwgImVuYWJsZWQiOiB0cnVlLCAiaWQiOiAiNWEzMDE0N2Y5YzE4NGZjNmI2MThmYzE2ZTA2YzJiNjYiLCAibmFtZSI6ICJEZXNpZ25hdGUgRE5TYWFzIn19LCAic2VydmljZUNhdGFsb2ciOiBbeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTAuMjAwLjE5LjQwOjkwMDEvdjEiLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTAuMjAwLjE5LjQwOjUwMDAvdjIuMCIsICJpZCI6ICIwYTdkZGNkZDZmODA0NjllYjMzZDJiZGQ5MmI2YzNkNyIsICJwdWJsaWNVUkwiOiAiaHR0cDovL2xvY2FsaG9zdDo5MDAxL3YxLyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJkbnNhYXMiLCAibmFtZSI6ICJkZXNpZ25hdGUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pblVzZXIiLCAicm9sZXNfbGlua3MiOiBbXSwgImlkIjogImNkYTlmYmFhNjZhZTQzNTViZGViOWIwMjJjOTUzMzEzIiwgInJvbGVzIjogW3sibmFtZSI6ICJfbWVtYmVyXyJ9LCB7Im5hbWUiOiAiYWRtaW4ifV0sICJuYW1lIjogImFkbWluVXNlciJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyI5ZmUyZmY5ZWU0Mzg0YjE4OTRhOTA4NzhkM2U5MmJhYiIsICJkNjY2MGVkMzU0NDE0OWU0Yjc4YWQ1NzUxNzI5ZjIzMCJdfX19MYIBhTCCAYECAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQBWYPlk24npFFVrciVovHYLIUueg5pgV0zRa2cWT8RoWUxXNTcbIbSDCyRh+rbDXx3eCZaafcnddjlYJhGzXp9PD5qgpUhj0tynNN0pZPNklDKAFZvZqtzf8pCGj3RPjmTg-lo2ff5hBpRwsl0TZWnF8S0q-Mx7IemVI48Sairehk0UJ8GkU12cLqeS2K4rRVEYdY81GAuErodlRHvkaRsm5WgjKFjE3TpMNT0xdS+IvKnsE5TRt-6O9pbX+sAp+SGg1fb+XHPIW6L5o6TrFbQtruuoSB7aHLKlY75kYXYaicNyVdsa-gMRuya-93CKdMdwcvDQ0s2IGGVcximTRi+Y

アクセストークンを使って、Designateのエンドポイントにアクセスする。

# ACCESS_TOKEN_ID="<上で出した文字列>"
# curl -H "X-Auth-Token: $ACCESS_TOKEN_ID" http://127.0.0.1:9001/v1/servers
{
  "servers": [
    {
      "created_at": "2016-02-08T06:51:46.000000",
      "id": "06b696c2-b2e0-47ef-b348-de8e221e1b0b",
      "name": "ns1.example.com.",
      "updated_at": "2016-02-08T07:30:26.000000"
    },
    {
      "created_at": "2016-02-08T07:30:26.000000",
      "id": "2c593756-a82c-4372-9587-c4a4489b6724",
      "name": "ns2.example.com.",
      "updated_at": null
    }
  ]
}
参考

KeystoneのUnscoped TokenとScoped Tokenの違い - めもめも Software Defined Boden: OpenStack Keystone Workflow & Token Scoping

Designateの仮想環境作成は、ここを参考にした。

OpenStack Designate を試す : あかぎメモ

Jenkinsのジョブをコマンドラインから生成する

Jenkinsのジョブをコマンドラインから、生成する方法を調べてみた。

OSは、Ubuntu14.04。

結論から言うと、XMLファイルをjenkins-cli.jarの create-jobコマンドに与えればよい。

Jenkins CLI - Jenkins - Jenkins Wiki

以下の実行パスや、URLは各自の環境に読み替えること。

jenkins.example.comとなっている箇所は、自身のJenkinsが動作しているURLを指す。

テンプレート用のXMLファイル作成

生成するジョブのテンプレートとなるXMLファイルを作成する。 通常通り、UIからジョブを作成する。

ここでは、echo 'this is 01_job' をする簡単な01_jobを作成する。

そうすると、サーバ内に、以下のようなファイルが作成される。

jenkins@ubuntu:~$ cat /var/lib/jenkins/jobs/01_job/config.xml
<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description>this is 01_job</description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.scm.NullSCM"/>
  <canRoam>true</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers/>
  <concurrentBuild>false</concurrentBuild>
  <builders>
    <hudson.tasks.Shell>
      <command>echo &apos;this is 01_job&apos;</command>
    </hudson.tasks.Shell>
  </builders>
  <publishers/>
  <buildWrappers/>

Jenkins CLI

今回は、Jenkins CLIのcreate-jobコマンドを使い、ジョブを生成する。

Jenkins CLI は、コマンドラインから、Jenkinsを操作するためのjarファイルで、Jenkinsにパッケージされている。

まずは、自身のURL/jnlpJars/jenkins-cli.jar から、jenkins-cli.jarをダウンロードする。

$ wget http://jenkins.example.com/jnlpJars/jenkins-cli.jar

また、http://jenkins.example.com/cli のようなURLで、使えるコマンド一覧、 ヘルプが参照できる。

ダウンロードしたら、実際に使ってみる。

$ java -jar jenkins-cli.jar -s jenkins.example.com/ -i ~/.ssh/id_rsa version
1.627

$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa who-am-i
Authenticated as: togashik
Authorities:
  authenticated

-s には、jenkins のURL、-i には、秘密鍵を指定する。 秘密鍵は、ログインユーザに登録した公開鍵とペアになっているものを指定する。

早速、create-jobを使い、ジョブを生成してみる。

最後に与えた02_jobは、新規生成するジョブ名を指す。

$ cat /var/lib/jenkins/jobs/01_job/config.xml | java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa create-job 02_job

これで、ジョブが生成できたはずなので、get-jobで確認してみる。

$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa get-job 02_job
<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description>this is 01_job</description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.scm.NullSCM"/>
  <canRoam>true</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers/>
  <concurrentBuild>false</concurrentBuild>
  <builders>
    <hudson.tasks.Shell>
      <command>echo &apos;this is 01_job&apos;</command>
    </hudson.tasks.Shell>
  </builders>
  <publishers/>
  <buildWrappers/>

ただし、これでは、02_jobは01_jobの単なるコピーなので、設定に含めたシェルスクリプトecho 'this is 01_job' のままである。

これを、echo 'this is 02_job' としたいとき等、読み込むxmlファイルを変更する必要がある。

delete-jobで先ほどのジョブを削除する。

$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa delete-job 02_job

create-jobで、再生成する。

$ sed 's/01_job/02_job/' /var/lib/jenkins/jobs/01_job/config.xml | java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa create-job 02_job

おまけ

コマンドラインから、生成したジョブを既存のビューに追加する

Jenkins CLIを使う方法を試そうとしたけど、うまくいかなかったので、力づくでやる。

つまり、ビュー構造が定義されているconfig.ymlを手動で変更して、読み込ませる。

02_jobをblogというビューに追加する。

$ sed -n '/^\s*<name>blog/,/^\s*<\/jobNames>/p' /var/lib/jenkins/config.xml
      <name>blog</name>
      <filterExecutors>false</filterExecutors>
      <filterQueue>false</filterQueue>
      <properties class="hudson.model.View$PropertyList"/>
      <jobNames>
        <comparator class="hudson.util.CaseInsensitiveComparator"/>
        <string>01_job</string>
      </jobNames>

$ sed -i.bak -e '/<string>01_job<\/string>/a\ \ \ \ \ \ \ \ <string>02_job<\/string>' /var/lib/jenkins/config.xml

$ sed -n '/^\s*<name>blog/,/^\s*<\/jobNames>/p' /var/lib/jenkins/config.xml
      <name>blog</name>
      <filterExecutors>false</filterExecutors>
      <filterQueue>false</filterQueue>
      <properties class="hudson.model.View$PropertyList"/>
      <jobNames>
        <comparator class="hudson.util.CaseInsensitiveComparator"/>
        <string>01_job</string>
        <string>02_job</string>
      </jobNames>

Jenkinsを安全に再起動する。

$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa safe-restart

参考

Jenkinsはじめました - こしごぇ

Firefoxの証明書警告を自動でスキップする

自動テストで、Seleniumを使っているが、自己割当証明書のドメインをテストする たびに、例外証明書として、登録するのが手間だと思ったので、自動化でできないか調べてみた。

f:id:togattti1990:20150828172155p:plain

証明書警告とは、このような表示。。

自動で、証明書警告をスキップするためには、FirefoxアドオンのSkip Cert Errorを使う。

addons.mozilla.org

インストールしたら、設定を開き次のように設定を済ませる。

f:id:togattti1990:20150828173024p:plain

Domain whitelist には、ドメインもしくはIPの一部にマッチした場合、証明書の検証をスキップしてくれる。 複数サブドメインを利用することがある場合は、楽に設定を済ますことが出来る。

もっとおすすめの方法があれば、ぜひ教えてください。

ちなみに、Firefoxプロファイルの設定は、ここらへんが参考になると思います。

togattti.hateblo.jp

Slackでアニメ放送時間の通知Botを作ってみた

最近、Slackを使ったアプリネタを見る機会が増えてきた気がします。

なので、自分でもやってみようと思いました。

今回は、アニメ放送時間の一時間前になったら、定期通知するBotを作ってみます。

具体的には、

  1. Web UIにアニメの放送時間を登録
  2. Cronファイルを更新
  3. 放送時間の一時間前になったら、Slack APIを叩いてPost

という仕組みのものを作ります。

手順

Web UIはRailsで簡単なものを用意します。

必要なモジュールの準備、Scaffold作成

$ rails new animelovers --skip-bundle
$ cd animelovers

Gemfileには、以下を追記します。

slack-apiは、文字通りSlackの操作に使い、wheneverは、crontabの設定内容を管理するモジュールです。

# for slack
gem 'slack-api'

# for crontab
gem 'whenever', require: false

bundle installします。

bundle install --path vendor/bundle

次に、scaffoldでひな形を作ります。

$ bundle exec rails g scaffold Anime title:string days_of_the_week:string start_time:time
$ bundle exec rake db:migrate

Slackの設定

SlackのAPIトークンを、config/initializers/slack.rb に下記のように書きます。

APIは、Slack Web API | Slack から発行します。

#config/initializers/slack.rb
require 'slack'

Slack.configure do |config|
  config.token = 'xoxp-9469336594-9469676821-9469781495-******'
end

これで、Rails内の各所から、Slackにポストできます。

Postは、次の一行で行うことができます。text, username, channelは、適宜変更します。

Slack.chat_postMessage(text: 'テスト', username: 'kenta', channel: '#random')

Wheneverの設定

UIから、新規登録、更新、削除が行われたときに、config/schedule.rbが更新され、crontabファイルも更新されるようにします。

下記のような、ヘルパーを書きます。

何点か補足しておくと、crontabに書く、* * * * * のような、実行時間はcrontimeで、適当に整形しています。

Slackのusernameや、channelは適宜変更します。

config/schedule.rbを書き換えた後は、whenever --update-crontabを実行しています。

# app/helpers/whenever_helper.rb
module WheneverHelper
  def update_schedule 
    schedule_path = File.join(Rails.root, 'config/schedule.rb')

    File.open(schedule_path, 'w') do |f| 
      f.flock File::LOCK_EX
      header = "set :output, 'log/output.log'\n"
      header << "set :environment, :development\n"
      f.write(header)
    end

    animes = Anime.all
    animes.each do |anime|
      content = <<-FILE
# minute, hour, day_of_month, month, day_of_week
every '#{crontime(anime)}' do
    runner "Slack.chat_postMessage(text: '#{anime.title} が あと一時間で始まるよ!!', username: 'kenta', channel: '#random')"
end

      FILE
      File.open(schedule_path, 'a') do |f|
        f.flock File::LOCK_EX
        f.write(content)
      end
    end
    system("bundle exec whenever --update-crontab")

  end 

  private
  def crontime anime
     if anime.start_time.to_s.match(/\s(\d{2}):(\d{2}):/)
       hour = "%01d" % $1
       hour = hour.to_i
       minute = "%01d" % $2
     end

     wday = week_list[anime.days_of_the_week]

     if hour == 0
       hour = 23
       if wday == 0
         wday = 6
       else
         wday = wday - 1
       end
     else
       hour = hour - 1
     end

    "%s %s * * %s" % [minute, hour, wday]
  end

  def week_list
    {'Sun' => 0, 'Mon' => 1, 'Tue' => 2, 'Wen' => 3, 'Thr' => 4, 'Fri' => 5, 'Sat' => 6}
  end

end

次に、コントローラーに、反映させます。

WheneverHelperはこのあたりに、

# app/controllers/animes_controller.rb
class AnimesController < ApplicationController
  include WheneverHelper

update_scheduleはcreateと

  # POST /animes
  # POST /animes.json
  def create
    @anime = Anime.new(anime_params)

    respond_to do |format|
      if @anime.save
        update_schedule

updateと

  # PATCH/PUT /animes/1
  # PATCH/PUT /animes/1.json
  def update
    respond_to do |format|
      if @anime.update(anime_params)
        update_schedule

destroyに

  # DELETE /animes/1
  # DELETE /animes/1.json
  def destroy
    @anime.destroy
    update_schedule

それぞれ、追記します。

ソースコードGitHubに挙げました。

github.com

実演

このように登録しておくと、

f:id:togattti1990:20150823215345p:plain

こうやって通知してくれます。

f:id:togattti1990:20150823215324p:plain

ちなみに、config/schedule.rbには、次の行が追記されます。

# minute, hour, day_of_month, month, day_of_week
every '52 21 * * 0' do
    runner "Slack.chat_postMessage(text: 'テストアニメ が あと一時間で始まるよ!!', username: 'kenta', channel: '#random')"
end

これで、アニメを見逃すことが無くなる、やったー\(^o^)/

参考にしたリンク

10分コーディング! Rubyでつくる Slack時報 | マネーフォワード エンジニアブログ