It’s now or never

IT系の技術ブログです。気になったこと、勉強したことを備忘録的にまとめて行きます。

さくらVPSにOSをインストールしてroot以外のUserを作成する

  • さくらVPSで新規に環境をインストールしたときにroot以外の作業ユーザーを構築する方法をメモ
  • 環境構築には、Chef zero(Knife zero)を使用する

1.さくらVPSにOSをインストール

スクリーンショット 2017-03-19 10.34.38.png

今回は、CentOS7を選択

rootで接続できるか確認

ssh -p 22 root@<IPアドレス>

※さくらVPS上のコンソールからrootでログインできるかを確認してもOK

2.Chefの環境を構築

  • Chef自体のもろもろの設定についての説明は割愛する
    • Chefの設定は色々難しいので間違っているかもしれない…

Chefのツールのインストール

chef gem install knife-zero

Chefのリポジトリ作成

chef generate repo <chef-repo_name>

knifeの設定ファイル作成

knife configure
  • ~/.chef配下にknife.rbができる
vim .chef/knife.rb
  • ローカルプロジェクトの設定
local_mode true
log_level                :info
log_location             STDOUT
chef_repo_dir = File.absolute_path( File.dirname(__FILE__) + "/.." )
cookbook_path ["#{chef_repo_dir}/cookbooks", "#{chef_repo_dir}/site-cookbooks"]
node_path     "#{chef_repo_dir}/nodes"
role_path     "#{chef_repo_dir}/roles"

リモートサーバーのknife zeroを初期化

knife zero bootstrap <IPアドレス> --ssh-user root --node-name reter-product

※ 途中rootのパスワードを聞かれるため、手順1で設定したパスワードを入力

  • 作成が成功するとプロジェクト配下のclients/nodes/配下にリモートnodeの設定ファイルが作成される

3.ユーザーを作成する

  • ユーザーの作成は、サードパーティのcookbookを使用する
  • cookbookの管理にはBerkshelfを使用する

外部cookbookのインストール

vim Berksfile

site :opscode
cookbook 'user'
chef exec berks vendor ./cookbooks
  • userというcookbookはLWRPという方法でuserの作成を提供しており準じた形式で記述するだけでユーザーを簡単に作成できる

ログインユーザー用のssh-keyを作成

ssh-keygen -t rsa -b 4096 -f <ファイル名>
  • 作業ユーザーのssh用のキーを作成

user作成用のcookbookの作成

cd site-cookbooks
chef generate cookbook site-user
vim site-cookbooks/site-user/recipes/default.rb
user_account '<作成するユーザー名>' do
  action :create
  ssh_keys  ['
ssh-rsa ... 
'] # 作成したsshの公開鍵を指定する
end

本番用のロールを作成

vim roles/initial_setting.json
{
    "name": "initial_settings",
    "description": "This is initial recipes.",
    "chef_type": "role",
    "json_class": "Chef::Role",
    "default_attributes": {
    },
    "override_attributes": {
    },
    "run_list": [
        "recipe[user]",
        "recipe[site-user]"
    ]
}
  • 実行するレシピをnodeファイルごとに制御するのは、大変なのでロールに分けておく
  • roleのrun_listには、インストールした外部cookbookであるuserと自作したsite-userを追加する
    • 実行順序はuserが先

ロールをnodeに追加

knife node run_list add <bootstrapのときに作成されたnode名> 'role[initial_settings]'

リモートサーバーに反映

knife zero converge "name:reter-production" --ssh-user root

sshでログインできるか確認

ssh <ユーザー名>@<サーバーIP> -i <sshの秘密鍵>
  • ログインできていれば正しくユーザーが作成されている

作成したユーザーのSudo権限を許可

レシピをダウンロード

vim Berksfile
site :opscode
cookbook 'user'
cookbook 'sudo' # 追加
chef exec berks vendor ./cookbooks

環境設定のファイルを作成

chef exec knife environment create production -e vim
  • ユーザー個別の設定は、環境依存のため設定ファイルを作成

sudo設定を記載

vim environments/production.json
{
    "name": "production",
    "description":"Production User and Parmission",
    "chef_type": "environment",
    "json_class": "Chef::Environment",
    "default_attributes": {},
    "override_attributes": {
        "authorization": {
            "sudo": {
                "users": ["<sudo権限を与えるユーザー>"],
                "passwordless": "true"
            }
        }
    }
}

nodeファイルを編集して環境をproductionに変更する

chef exec knife node edit reter-production -e vim

設定を反映

knife zero converge "name:<ロール名>" --ssh-user root

sudoを実行できるか確認

ssh <ユーザー名>@<サーバーIP> -i <sshの秘密鍵>
sudo vim /etc/sudoers
  • 設定したuserにsudo設定がされていればOK

【iOS, swift】swiftコーディング規約

※ Swift 2.3をベースに記載

自分がswiftを書くときのコーディング規約を記載します。

クラス

  • Pascal記法 (大文字で始まる) で記述する
// ◯
class ViewController: UIViewController {

}

// ☓ snake case
class view_controller: UIViewController {
・・・
}
  • 継承する時にクラス名の後ろにつける:は:の後ろにスペースを入れる
// ◯
class ViewController: UIViewController {
}

// ☓
class view_controller:UIViewController {
}

メソッド

  • Camel記法(小文字始まり)で記述する(hogeFuga)
  • メソッド名は動詞を使う
  • ;は付けない
  • {の行は改行しない。前にスペースを入れる。
  • ->の前後はスペースを入れる
// ◯
func getName() -> Strig {
    return "name"
}

// ☓ name snake
func getName() -> Strig {
    return "name"
}

// ☓ break
func getName() -> Strig 
{
    return "name"
}

// ☓ space
func getName()->Strig {
    return "name"
}

変数・プロパティ(保持型・計算型)

  • Camel記法(小文字始まり)で記述する(hogeFuga)
  • 行末に;は付けない
  • privateな保持型プロパティは_から始める(_hogeFuga
  • interlな保持型プロパティはinternalを省略する
    • 理由: 基本的にスコープは厳格にすべきである。
    • しかしprivateスコープはテストファイルから参照できない。
    • テストを書くことの方が重要のため基本的にinternalであることを許可する。
    • internalがデフォルトであるため、冗長を削除するため省略して良しとする。
  • 基本的にpublicは使用しない
    • 理由: 同じモジュール内であれば参照可能なためPublicは必要ない
    • APIを定義する場合は必要
  • 計算型プロパティのgetがある場合はprivateでOK
class Sample {
    // ◯
    var userName: Int;
    private var _userMessage: String;

    func hoge() -> Int {
        let age = 10
        return age
    }

    private var _inSpeed: Double = 0
    var speed: Double {
        get {
            return self._inSpeed + 10;
        }

        set(speed) {
            self._inSpeed = speed
        }
    }

    // ☓ Pascal
    var UserName: String;
    // ☓ not `_`
    private var userLevel: Int;
}
  • storybord(or xib)上で強参照する変数(ViewController.viewが保持するなど)は@IBOutlet weak varで宣言する
// ◯
@IBOutlet weak var clickHogeButton: UIBarButtonItem!

// ☓
@IBOutlet var clickHogeButton: UIBarButtonItem!
  • 読み取り専用のプロパティと添字付けのgetterは暗黙的にする
  • 可能な限り、読み取り専用のプロパティと添字付けではgetキーワードを省略する
  • 理由: 意図と意味が明確だから。コードも少なくて済む。
// ◯
var myGreatProperty: Int {
    return 4
}

subscript(index: Int) -> T {
    return objects[index]
}

// ☓
var myGreatProperty: Int {
    get {
        return 4
    }
}

subscript(index: Int) -> T {
    get {
        return objects[index]
    }
}

enum

  • enum名はPascal記法 (大文字で始まる) で記述する
  • 値もPascal記法で記述する
  • caseは省略せず、caseごとに改行を入れる
    • 理由: 統一性
// ◯
enum CustomResult {
    case Success, 
    case Error
}

// ☓ upper case
enum CustomResult {
    case SUCCESS, ERROR
}

// ☓ Case is not omitted
enum CustomResult {
    case Success, Error
}

if

  • 判定式に()は付けない
  • {の前には改行は入れない
// ◯
let x = 1
if x == 1 {
    print("")
}

// ☓
let x = 1
if (x == 1) {
    print("")
}

for

  • for-inを使用する
  • {の前には改行は入れない
  • cの構文for(let i; i < 10; i++)は使わない(非推奨になっている)
// ◯
var sum: Int = 0
for i in 1...10 {
    sum += i
}

// ☓
var sum: Int = 0
for (var i = 1; i <= 10; i += 1) {
    sum += i
}

switch

  • {の前には改行は入れない
  • switchcaseの左は揃える
// ◯
let c: Int = 1
switch c {
case 1:
    print("")
}

// ☓
let c: Int = 1
switch c 
{
    case 1:
        print("")
}

可能な限りvar宣言よりもlet宣言を使う

  • 理由: letは値が変わらないことを保証するためより安全で明確なコードになる

1行の文字数

  • 努力目標:80文字
  • 最大:100文字

識別子に型を指定する時は、常に識別子のすぐ後ろにコロンを置き、空白を一つあけて型名を書く

// ◯
class MyClass: SuperClass { ... }
let myConst: Int = 2
func myFunc(type: Int) -> String { ... }

// ☓
class MyClass:SuperClass { ... }
let myConst:Int = 2
func myFunc(type:Int) -> String { ... }

明示的なself参照は必要な時だけ

  • selfの持つプロパティやメソッドへアクセスする時、デフォルトではselfへの参照は省く
  • 理由: クロージャにおけるselfのキャプチャリングが目立つようになる。その他の場所における冗長さが無くなるため。
class MyClass {
    var hoge: Int

    // ◯
    func myFunc() {
        hoge = 1234
    }

    var myClosure: () -> () {
        return {
            self.hoge
        }
    }

    // ☓
    func myFunc() {
        self.hoge = 1234
    }
}

【Swift 2.0】クラスのプロパティ名を取得する

swiftでクラスからプロパティ名のリストを取得する方法です。

static func propertyNames() -> Array<String> {
    var names: Array<String> = []
    var count: UInt32 = 0
    self.classForCoder()
    let properties:UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(self.classForCoder(), &count)
    for var i: UInt32 = 0; i < count; i++ {
        let property = properties[Int(i)];
        let cname = property_getName(property)
        let name = String.fromCString(cname)
        names.append(name!)
    }
    free(properties)
    return names
}

【Rails4】GrapeをつかってAPIを作成する

Grapeとは

REST-likeなAPIを作成する為のフレームワークです。 詳しくは、Grape githubを参照してください。

今回は、サンプルアプリケーションを作成し、jsonを返すAPIを動かしてみます。

サンプルプロジェクトにGrapeをインストール

任意のRailsアプリケーションを作成します。

rails new grape_api --skip-bundle -T

Gemのインストール

作成したアプリケーションのGemfileを編集し、grapeのGemをインストールします。

■ Gemfile

gem 'grape'
bundle install
// ※ローカルにインストールする場合は、--path vendor/bundleをつける

ディレクトリを作成する

API経由でデータを参照するために任意のモデルを作成します。

# userテーブルを作成しDBへ反映
rails g scaffold user name:string
rake db:migrate

ディレクトリは、下記のような構成にします。

- app
  - apis
    - api
      -v1
       - users
      -vXX
# とりあえず、v1のディレクトリのみ作成
mkdir -p app/apis/api/v1

今回は、上記のファイル構成を元に、

  • http://[ホスト]/api/v1/users
  • http://[ホスト]/api/v1/users/[user_id]

という2つのAPIを作成します。

ファイルの自動インポートの設定を行なう

apisディレクトリ配下に置かれたファイルが自動的にRailsのファイルパスに追加されるようにapplication.rbを以下のように編集します。

■ config/application.rb

module GrapeApi
  class Application < Rails::Application
    # app/api配下の.rbファイルを読み込み対象にする
    config.paths.add File.join('app', 'apis'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'apis', '*')]
  end
end

APIのパスをルーティングする

APIのルートパスを定義します。

■ config/routes.rb

Rails.application.routes.draw do
・・・
  # APIモジュールのBaseクラスを'/'Pathとして定義する
  mount API::Base => '/'
・・・
end

Baseクラスを作成

ルーティングしたAPI::Baseクラスを定義します。
prefixにapiを定義することでhttp://[host]/apiのpathを構成することができます。

■ /app/apis/api/base.rb

module API
  class Base < Grape::API
    # Baseクラスのpathを定義する
    prefix 'api'

  end
end

上記のBaseクラスと同じようにv1ディレクトリ配下にもbase.rbを作成します。
versionを定義することでhttp://[host]/api/v1のpathを構成することができます。
formatAPIのレスポンスデータのフォーマットをjsonに指定しています。

■ /app/apis/api/v1/base.rb

module API
  module V1
    class Base < Grape::API
      version 'v1'
      format :json
    end
  end
end

先ほど作成したAPI::BaseAPI::V1::Baseをマウントします。

■ /app/apis/api/base.rb

module API
  class Base < Grape::API
    # Baseクラスのpathを定義する
    prefix 'api'

    # v1のBaseクラスをマウントする
    mount API::V1::Base
  end
end

apiクラスを作成

v1ディレクトリ配下にusersクラスを作成します。

resourceapiのpathを定義しています。

■ /app/apis/api/v1/users.rb

module API
  module V1
    class Users < Grape::API
      # `users`resource配下にすることで
      # /api/v1/usersのapiとしてアクセスできる
      resource :users do
        # GET http://[host]/api/v1/users
        get do
          User.all
        end

        # パラメタバリデーション
        params do
          requires :id, {type: Integer, desc: 'user id.'}
         end
         # GET http://[host]/api/v1/users/[user_id]
         get ':id' do
          User.find(params[:id])
         end
      end
    end
  end
end

API::V1::UsersAPI::V1::Baseにマウントします。

■ /app/apis/api/v1/base.rb

module API
  module V1
    class Base < Grape::API
      version 'v1'
      format :json
    end
    mount API::V1::Users
  end
end

サンプルデータを作成してAPIにアクセス

ローカル環境でRailsサーバを起動します。

rails server

http://localhost:3000/usersにアクセスして、画面上から適当にデータを作成します。

f:id:inon29:20150907082655p:plain

  • http://localhost:3000/api/v1/usersにアクセスするとUsersテーブルのデータの全件が取得できます。

f:id:inon29:20150907082705p:plain

  • http://localhost:3000/api/v1/users/1にアクセスするとUsersテーブルのデータの1件目が取得できます。

f:id:inon29:20150907082714p:plain

参考サイト

http://kzy52.com/entry/2014/11/07/084023 http://qiita.com/hkusu/items/2ca0323cc276ab31e926

【cocos2d-x】【CocoStudio】CocoStudioを使って画面のレイアウトを読み込む

環境

cocos2d-x 3.2
CocoStudio for Mac 1.0.0 Bata

CocoStudioでレイアウトを作成する

まずは、CocoStudioにて任意の画面を作成します。
以下では、画面に一つボタンを置いています。

cocos.png

上記、赤枠の名前は、各UIパーツのをソースコード上から取得する時に必要になるので、
わかりやすい名前にしておきます。

レイアウトファイルの読み込み

CocoStudioにて、cmd + Eでエクスポート。
[CocoStudioのプロジェクト]/Export配下のに作成したキャンバスのディレクトリが出力されているので、それをそのままXCodeへimportします。

インポートしたレイアウトを以下のようにソースコード上で読み込みます。

#include "cocostudio/CocoStudio.h"
// UIパーツを使用するためにimportしておく
#include "CocosGUI.h"

auto node = cocostudio::timeline::NodeReader::getInstance()->createNode("[jconファイル名]");

// 画面に配置
addChild(node);

子ノードを取得する

レイアウト上に配置した、子ノードを取得するにはgetChildByName()を使います。
ここで指定するオブジェクト名は、CocoStudio上で名前に指定した文字列です。

auto button = (Button *)scene->getChildByName("[オブジェクト名]");


階層が深い位置のオブジェクトを取得するには、以下のヘルパーメソッドを使います。

utils::findChildren([探索対象ノード], [オブジェクト名])

Buttonイベントを取得するとき

参考までに、ui::Buttonクラスのタッチイベントを取得するには以下のようにします。

button->addTouchEventListener([&](Ref *ref, Widget::TouchEventType type) {
    if (type == Widget::TouchEventType::ENDED) { // タッチアップを取得する
    }
});

参考

http://qiita.com/kyokomi/items/9e3dea9325047940f3e0
http://iphone-labo.blogspot.jp/2014/08/cocos2dx-v32node.html
http://giginet.hateblo.jp/entry/2014/08/29/185519
http://raharu0425.hatenablog.com/entry/2014/06/20/154718

【cocos2d-x】cocos2d-x 3.X系を使ってみる① (セットアップ)

最近、ゲーム開発に携わる機会があり、
ゲーム開発の大手プラットホームであるcocos2d-xについて触れてみました。

cocos2d-xは、2Dゲームをつくることに優れたプラットホームで、
開発の方法はわかり易いのです。 ただ、2.X系と3.X系で大きな違いがあったり、ビルド関連でハマったり色々つまずいたのでメモしておきます。

cocos2d-xのセットアップ

1.ダウンロード

cocos2d-xを以下のページからダウンロードします。

公式ページ

ダウンロードしたcocos2d-xのディレクトリを任意の場所に配置します。

2.setup.pyを実行

手順1でダウンロードしたディレクトリへ移動し、直下にあるsetup.pyファイルを実行する。

python setup.py

色々と足りないパスを聞かれるので、設定されていないパスがあれば設定を行います。
これで、開発する為の準備が完了しました。

3.新規プロジェクトを作成する

作成するゲームのプロジェクトを作成します。
cocos2d-x 3.X系で新規プロジェクトを作成するには、cocosコマンドを使用します。

cocos new [プロジェクト名] -p [パッケージ名] -l [開発言語(cpp)] -d [プロジェクトを置くディレクトリ名]

■ 各引数の簡単な解説

-p Androidプロジェクトのパッケージ名。iOSBundle identifierも共通かなと思ってましたが、ここは変わりませんでした。

-l 開発言語を指定します。対応する言語は次のとおりです。 c++ => "cpp", lua => "lua", javascript => "js"

-d プロジェクトを配置するRootディレクトを指定します

作成されたディレクトリを確認すると、以下のようなディレクトリが作成されているかと思います。
これが各開発環境のプロジェクトディレクトリになります。

proj.android
proj.ios_mac
proj.linux
proj.win32
proj.wp8-xaml

プロジェクトをビルド

プロジェクトが正しく作成できたら、試しにプロジェクトをビルドします。
ここでは、iOS用のプロジェクトをビルドしてみます。

cocos run -s [プロジェクトディレクトリ] -p ios

ビルドが成功すると、iPhoneシュミレータが起動して以下のような画面が表示されているかと思います。

f:id:inon29:20140916001114p:plain


これで、開発のための準備ができました。
今回は、iOSAndroidのアプリをターゲットにしているので、 今後は、各OSでのハマりどころなどを押さえていきたいと思います。

Apache用のVirtualHostの設定メモ(for Mac)

■ 環境

Mac OSX 10.9.3 (Mavericks)

Apacheの関連ファイルパス

httpd.conf

/private/etc/apache2/httpd.conf

アクセスログ

/private/var/log/apache2/access_log

エラーログ

/private/var/log/apache2/error_log

各ユーザー設定ファイル

/private/etc/apache2/extra/httpd-userdir.conf
/private/etc/apache2/users/[ユーザー名].conf

1.httpd.confの設定

ユーザーの設定ファイルは、以下のファイルに記述します。

/private/etc/apache2/users/[ユーザー名].conf

設定内容は、以下の通りです。

<VirtualHost *:80>
    ServerName [ホスト名]
    DocumentRoot [ドキュメントルートPath]
    <Directory [ディレクトリパス ※ドキュメントルートと同じ]>
        Options Indexes FollowSymLinks Includes ExecCGI
        AllowOverride all
        Options -MultiViews
        Order allow,deny
        Allow from all 
    </Directory>
</VirtualHost>

2.hostsの編集

以下のファイルにhostの設定を記載します。

/etc/hosts


127.0.0.1  [ホスト名]