12.16.2013

Rails 4 Connect Existing Database

Once connect strings are specified in database.yml file, just add a model as follows:
class TestResult < ActiveRecord::Base
  self.table_name = "Test"
  self.primary_key = "testId"
end
Now, lets check from the console
$ rails c
Loading development environment (Rails 4.0.2)
2.0.0p353 :002 > TestResult.column_names
 => ["testId", "analysis", "archive", "baseline", "description", "engineer", "name", "project", "reference", "retention", "link", "errors"] 

12.11.2013

Deploying a Rails App Remotely With Capistrano

Modify Apache Config

1. Capistrano inserts a directory named "current" so change the DocumentRoot of the .conf file:
$ sudo vi /etc/httpd/sites-available/depot.conf
DocumentRoot /home/samdc/prod/depot/current/public
<Directory /home/samdc/prod/depot/current/public>

Setup Git Server

2. Create an empty repository on the git server
$ mkdir -p ~/git/depot.git
$ cd ~/git/depot.git
$ git --bare init
3. Generate a public key and use it to give ourselves permission to access our own server
$ test -e ~/.ssh/id_dsa.pub || ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/samdc/.ssh/id_dsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/samdc/.ssh/id_dsa.
Your public key has been saved in /home/samdc/.ssh/id_dsa.pub.

$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
4. Make sure that proper permissions are set for ssh. I got another post related to this..
$ chmod g-w /home/samdc
$ chmod 700 /home/samdc/.ssh
$ chmod 600 /home/samdc/.ssh/authorized_keys

Prepare Application

5. Update Gemfile to indicate that we are using capistrano
$ vi Gemfile
gem 'rvm-capistrano', group: :development
6. Install capistrano using bundle install
$ bundle install
7. If you havent done so, put project under git
$ cd app_directory
$ git init
$ git add .
Ignore files
$ vi .gitignore
.ruby-gemset
.ruby-version
$ git commit -m "initial commit"
8. Copy all the gems required by your application into the vendor/cache folder. This also includes dependencies required by the gems. This helps because at the time of deployment you can just run bundle install --local to avoid dependency on the gems repository (rubygems.org) and install all the gems from the cached folder
$ bundle package
$ git add Gemfile.lock vendor/cache
$ git commit -m "bundle gems"
9. Push our code to the Git server
$ git remote add origin ssh://samdc@host/~/git/depot.git
$ git push origin master

Remote Deployment

1. Add necessary capistrano files to the project
$ capify .
[add] writing './Capfile'
[add] writing './config/deploy.rb'
[done] capified!
2. Modify Capfile and uncomment one line
load 'deploy/assets'
3. Modify deploy.rb, this is the recipe that we will use for deployment
require 'bundler/capistrano'

# be sure to change these
set :user, 'samdc'
set :domain, 'depot.com'
set :application, 'depot'

# adjust if you are using RVM, remove if you are not
set :rvm_type, :user
set :rvm_ruby_string, 'ruby-2.0.0-p353'
require 'rvm/capistrano'

# file paths
set :repository,  "#{user}@#{domain}:git/#{application}.git" 

# stages
set :stages, ["staging", "production"]
set :default_stage, "staging"

# distribute your applications across servers (the instructions below put them
# all on the same server, defined above as 'domain', adjust as necessary)
role :app, domain
role :web, domain
role :db, domain, :primary => true

# you might need to set this if you aren't seeing password prompts
# default_run_options[:pty] = true

# As Capistrano executes in a non-interactive mode and therefore doesn't cause
# any of your shell profile scripts to be run, the following might be needed
# if (for example) you have locally installed gems or applications.  Note:
# this needs to contain the full values for the variables set, not simply
# the deltas.
# default_environment['PATH']=':/usr/local/bin:/usr/bin:/bin'
# default_environment['GEM_PATH']=':/usr/lib/ruby/gems/1.8'

# miscellaneous options
set :deploy_via, :remote_cache
set :scm, 'git'
set :branch, 'master'
set :scm_verbose, true
set :use_sudo, false
set :normalize_asset_timestamps, false

namespace :deploy do
  desc "cause Passenger to initiate a restart"
  task :restart do
    run "touch #{current_path}/tmp/restart.txt" 
  end

  desc "reload the database with seed data"
  task :seed do
    deploy.migrations
    run "cd #{current_path}; rake db:seed RAILS_ENV=#{rails_env}"
  end
end
4. Create staging and production deployment files
$ cd config
$ mkdir deploy
$ vi production.rb
require "rvm/capistrano"                  # Load RVM's capistrano plugin.
set :rvm_ruby_string, 'ruby-2.0.0-p353'   # Or whatever env you want it to run in.
set :rvm_bin_path, '/home/samdc/.rvm/bin'
server "deployment_server_name", :app, :web, :db, :primary => true
set :deploy_to, "/home/samdc/apps/depot"
$ vi staging.rb
require "rvm/capistrano"                  # Load RVM's capistrano plugin.
set :rvm_ruby_string, 'ruby-2.0.0-p353'   # Or whatever env you want it to run in.
set :rvm_bin_path, '/home/samdc/.rvm/bin'
server "deployment_server_name", :app, :web, :db, :primary => true
set :deploy_to, "/home/samdc/apps/depot_staging"
5. First time deployment, setup basic dir structure on deployment server
$ cap deploy:setup
Uncomment default_run_options line in deploy.rb if there is any failure.

6. Check the config.
$ cap deploy:check
7. We can load seed data.
$ cap deploy:seed
8. Deploy
$ git add .
$ git commit -m "add cap files"
$ git push
$ cap deploy
Remember this deploys to the default "staging" server. To deploy to production...
$ cap production deploy
9. Rollback deployment
$ cap deploy:rollback

Further reading:
http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html
https://github.com/capistrano/capistrano/wiki/2.x-From-The-Beginning

Install and Configure MariaDB on CentOS 6

1. Go to repository generator, select the desired repository. In my case, I got this:
# MariaDB 5.5 CentOS repository list - created 2013-12-07 02:35 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/5.5/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
2. Create a new repo, and put the generated text above.
$ sudo vi /etc/yum.repos.d/MariaDB.repo
3. Install
$ sudo yum install MariaDB-server MariaDB-client MariaDB-devel MariaDB-common
4. Start mysql
$ sudo /etc/init.d/mysql start
$ sudo /sbin/chkconfig mysql on
5. Autostart mysql
Find out the name of service’s script from /etc/init.d/ directory e.g. mysqld or httpd
Add it to chkconfig
$ sudo /sbin/chkconfig --add mysqld
Make sure it is in the chkconfig.
$ sudo /sbin/chkconfig --list mysqld
Set it to autostart
$ sudo /sbin/chkconfig mysqld on
6. Setup mysql Login as root:
[samdc@perfdb4 apps]$ mysql -u root
Set root password:
MariaDB [(none)]> set password for root@localhost=password('mypass');
MariaDB [(none)]> set password for root@'127.0.0.1'=password('mypass');
MariaDB [(none)]> set password for root@'machine.domain.com'=password('mypass');
Delete anonymous:
MariaDB [(none)]> delete from mysql.user where user='';
7. Create db and user: Create db:
MariaDB [(none)]> create database mydb;
Create user myuser with password mypass:
MariaDB [(none)]> grant all on mydb.* to 'mydb' identified by 'mypass';
MariaDB [(none)]> grant all on mydb.* to 'mydb'@'localhost' identified by 'mypass';
8. Show databases
MariaDB [(none)]> show databases;

SSH Issue While Deploying Rails App Via Capistrano

Learned some lessons today about SSH and how to troubleshoot. While setting up Capistrano to deploy for the first time, I was getting this error message:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)
As it turned out, SSH is very picky when it comes to permissions. The solution is to set proper permissions for ssh authorized_keys file. Symptom is this error message from /var/log/secure
Authentication refused: bad ownership or modes for file /home/samdc/.ssh/authorized_keys
Which means, its a file permission issue as noted in this post.

Following that...
$ chmod g-w /home/samdc
$ chmod 700 /home/samdc/.ssh
$ chmod 600 /home/samdc/.ssh/authorized_keys
One thing to note is that when accessing that location using a different account, we have to make sure to copy the public key of that different account to the same authorized_keys file.

12.04.2013

How to Deploy a Rails App to Apache with Passenger

This guide is for Fedora Core 19, but I think it should be fine for any Linux machines...

Prepare System

1. Create a local account that will be used for passenger config
$ sudo useradd samdc
$ sudo passwd samdc
$ su - samdc
2. Install RVM and Ruby using this post (How to Install RVM, Ruby and Rails), up to step 10.

Install Passenger

3. Start apache
$ sudo apachectl start
4. Install passenger
$ gem install passenger
$ passenger-install-apache2-module
This runs the installer...
Press enter. The installer will check for required software, if the dependencies are not met, it will tell you what to install...
5. Install all missing dependencies and re-run the install
$ sudo yum install httpd-devel
$ sudo yum install apr-devel
$ sudo yum install apr-util-devel
$ passenger-install-apache2-module
A number of sources will be compiled and after that it will ask to update our Apache config...
6. To find out where the Apache config file is, try these commands
$ apachectl -V | grep HTTPD_ROOT
 -D HTTPD_ROOT="/etc/httpd"
$ apachectl -V | grep SERVER_CONFIG_FILE
 -D SERVER_CONFIG_FILE="conf/httpd.conf"
From that, our config file is in /etc/httpd/conf/httpd.conf

7. Our Apache config has this at the end.
$ cat /etc/httpd/conf/httpd.conf
...
IncludeOptional conf.d/\*.conf
Which means we can maintain our extensions separately. In our case, what we want to do is to create a file called passenger.conf, then we can add the lines as indicated by the passenger installer from step 5 of this guide.
$ sudo vi /etc/httpd/conf.d/passenger.conf
$ cat /etc/httpd/conf.d/passenger.conf
LoadModule passenger_module /home/samdc/.rvm/gems/ruby-2.0.0-p353/gems/passenger-4.0.26/buildout/apache2/mod_passenger.so
PassengerRoot /home/samdc/.rvm/gems/ruby-2.0.0-p353/gems/passenger-4.0.26
PassengerDefaultRuby /home/samdc/.rvm/wrappers/ruby-2.0.0-p353/ruby

Configure Apache

8. Create directories that we will use later
$ sudo mkdir /etc/httpd/sites-available
$ sudo mkdir /etc/httpd/sites-enabled
9. Add a virtual host for our rails app
$ sudo vi /etc/httpd/sites-available/depot.conf
<VirtualHost *:80>
   ServerName www.depot.com
   ServerAlias depot.com
   DocumentRoot /home/samdc/prod/depot/public
   <Directory /home/samdc/prod/depot/public>
      AllowOverride all
      Options all 
      Require all granted
   </Directory>
</VirtualHost>
10. Tell Apache about our virtual hosts
$ vi /etc/httpd/conf/httpd.conf
Add this at the bottom:
Include sites-enabled/*.conf
11. Link the virtual host definition to sites-enabled
$ sudo ln -s /etc/httpd/sites-available/depot.conf /etc/httpd/sites-enabled/depot.conf
12. Add ServerName entry to /etc/hosts file
$ vi /etc/hosts
127.0.0.1 www.depot.com
127.0.0.1 depot.com

Configure SELinux

13. Suspend SELinux
$ sudo setenforce 0
14. Install checkpolicy
$ sudo yum install checkpolicy
15. Walk through SELinux log and generate new SELinux policy module
$ sudo grep httpd /var/log/audit/audit.log | /usr/bin/audit2allow -M passenger
16. Make policy active
$ sudo semodule -i passenger.pp
17. Switch SELinux back to enforcing mode
$ sudo setenforce 1
18. Restart Apache
$ sudo apachectl restart

Deploy Rails App

19. Copy all files to the deploy directory
$ cp -r /home/samdc/dev/depot/ /home/samdc/prod/
20. Install all gems required
$ cd /home/samdc/prod/depot/
If using a different db in production, e.g., mysql, change the Gemfile to add that for production
$ vi Gemfile
group :production do
  gem 'mysql2'
end
$ bundle install
21. Create the database
$ mysql -u root -p
> CREATE DATABASE depot_production DEFAULT CHARACTER SET utf8;
> GRANT ALL PRIVILEGES ON depot_production.* TO 'username'@'localhost' IDENTIFIED BY 'password';
> EXIT;
22. Configure rails production yml file
$ vi config/database.yml
production:
  adapter: mysql2
  encoding: utf8
  reconnect: false 
  database: depot_production
  pool: 5
  username: username
  password: password
  host: localhost
23. Lets load the database
$ rake db:setup RAILS_ENV="production"
$ rake db:seed
24. Change production environment settings
$ vi config/environments/production.rb
config.serve_static_assets = true
config.assets.compile = true
25. Precompile assets
$ rake assets:precompile
26. Now browse to http://depot.com

11.22.2013

Sqlite Cheat Sheet

This is from command line shell for sqlite.

1. Open sqlite database
$ sqlite3 db/development.sqlite3
2. List down tables
sqlite> .tables
3. Look at the schema
sqlite> .schema
4. Exit
sqlite> .exit

11.13.2013

Perforce Cheat Sheet

1. New client spec for workspace
$ p4 client
2. Populate workspace with files from server
$ p4 sync
$ p4 sync * - only files from current dir
$ p4 sync ... - current path, all folders and files underneath
$ p4 sync -f filename - force the sync, override no clobber (lose all local changes)
$ p4 sync @490807 - sync to changelist number
$ p4 sync @=490807 - sync only the files revised within that changelist
3. Check out a file for edit
$ p4 edit filename
4. See checked out files
$ p4 opened
$ p4 have filename - what version you have
$ p4 filelog filename - check history
5. View local changes
$ p4 diff
$ p4 diff filename | p4c.rb - colored diff
$ p4 diff -db filename - disregard whitespace
$ p4 diff -t filename - even though files aren't text
6. Create new changelist
$ p4 change
$ p4 change -u changelist_number - update submitted changelist
7. Add files for addition to the depot
$ p4 add
$ p4 add -c change_number -f filenames - add files to changelist
$ p4 add -f filenames - add files to default changelist
$ p4 add -c change_number * */* - add files in current dir and next dir to default changelist
$ "find . -type f | p4 -x - add" - cmd inside quotes would find all files in a directory structure and add them all in
8. Get info about a changelist, listing files that are included
$ p4 describe change_number
9. Get a list of your changes
$ p4 changes -u username
$ p4 changes -u username -s pending
10. Discard changes made to open files
$ p4 revert -c change_number - reverts only those files in the specified changelist
$ p4 revert filename - reverts only this file
11. Submit changes for code review
$ /auto/tools/bin/post-review change_number
12. Checkin your changes
$ p4 submit
$ p4 submit -c change_number
13. Delete pending changelist
$ p4 changes -u username -s pending
$ p4 revert -c 12345 //... - revert all files in my pending changelist 12345
$ p4 change -d 12345 - delete the now-empty changelist
14. Print detailed information about file revisions.
$ p4 filelog filename
15. Add opened files to a specific changelist
$ p4 reopen -c 431494 */*
16. Get specific change information
$ p4 changes //prod/main/...\@445029,445029
Change 445029 on 2014/08/10 by sdc@main:sdc 'Integrate change 444241 from 5.'
17. Move (or rename) a file from one location to another
$ p4 move deploy/deploy_change util/deploy_change
18. Move a directory
$ p4 edit 5.5/*/baseline.xml
$ p4 move 5.5/... 5.5_old/...
18. Take a peek at the branches available
$ p4 branches | grep "5\.6\.0"
19. Delete file
$ p4 delete filename
20. Change file type into executable
$ p4 edit -t +x watchdog

11.11.2013

Git Cheat Sheet

1. Initial git configuration
$ git config --global --add user.name "Sam Dela Cruz"
$ git config --global --add user.email "samdc@mail.com"
2. Verify configuration
$ git config --global --list
user.name=Sam Dela Cruz
user.email=samdc@mail.com
3. Tell git which files are not be be version controlled
$ vi .gitignore
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
4. Initialize repository
$ git init
5. Add all files
$ git add .
6. Commit
$ git commit -m "Project Scaffold"
============
Searching
============

1. History of code changes...
$ git log -L :start_perfcloud_run:./api/api/orchestrator/tasks/job_tasks.py

11.09.2013

Rails Cheat Sheet

1. Create rails application
$ rails new demo
2. Examine installation
$ cd demo
$ rake about
3. Start the application
$ rails server
4. Create a controller and actions
$ rails generate controller Say hello goodbye
$ rails generate controller Store index
5. Generate a scaffold
$ rails generate scaffold Product title:string description:text image_url:string price:decimal
$ rails generate scaffold_controller LdapUsers  # generate only controller and views, say if model had been predefined.
With relationships
$ rails generate scaffold LineItem product:references cart:belongs_to
Destroy just created scaffold
$ rails destroy scaffold LineItem
6. Apply the migration
$ rake db:migrate
7. Run the tests
$ rake test
$ rake test:models - only the models directory
8. Populate table with test data
$ rake db:seed
9. Rollback the migration
$ rake db:rollback
10. Open up rails console
$ rails console
$ rails c
11. Add a column to a table
$ rails generate migration add_quantity_to_line_items quantity:integer
12. Create a migration
$ rails generate migration combine_items_in_cart
13. Clear the logs
$ rake log:clear LOGS=test
14. Create a mailer
$ rails generate mailer OrderNotifier received shipped
15. Create an integration test
$ rails generate integration_test user_stories
16. Generate documentation in HTML format. First modify README.doc then...
$ rake doc:app
17. See how much code is written
$ rake stats
18. Loading production db
$ rake db:setup RAILS_ENV="production"
19. Generate rake task
$ rails g task perfdb get_baselines
      create  lib/tasks/perfdb.rake

How to Install RVM, Ruby and Rails

For my reference:
http://yakiloo.com/using-rvm/
http://ryanbigg.com/2010/12/ubuntu-ruby-rvm-rails-and-you/
http://rvm.io/rvm/best-practices

For this installation I followed what’s called single user installation, which is the recommended way of installation, this is an isolated install within a user's $HOME, not for root.

Install RVM

1. Install prerequisites
$ sudo yum install sqlite-devel nodejs openssl
2. Set rvm_path
$ echo 'rvm_path="$HOME/.rvm"' >> ~/.rvmrc
3. Install RVM as a single user ( background info: https://rvm.io/rvm/install)
$  \curl -L https://get.rvm.io | bash -s stable
4. At this point, RVM should have been installed, check if rvm was installed correctly by loading it then checking it’s type:
$ source ~/.rvm/scripts/rvm
$ type rvm | head -n 1
rvm is a function
5. Make sure that the latest version is installed
$ rvm get stable
6. Run the rvm requirements to get all the dependencies for RVM, this might prompt for your password when it needed to install missing packages:
$ rvm requirements
Checking requirements for fedora.
Installing requirements for fedora.
Updating system
Installing required packages: patch, gcc-c++, patch, readline-devel, zlib-devel, libyaml-devel, libffi-devel, openssl-devel, autoconf, automake, libtool, bisondelacs password required for '/usr/bin/env PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/bin/Aptana_Studio_3:/auto/home3/delacs/bin:/auto/home3/delacs/.rvm/bin:/sbin yum install -y patch gcc-c++ patch readline-devel zlib-devel libyaml-devel libffi-devel openssl-devel autoconf automake libtool bison': 
....................................................................................................................................................................................................................
Requirements installation successful.

Install Ruby

7. Now let’s install Ruby:
$ rvm install 2.0.0
8. The above command should install RubyGems with it, if in case there is an issue such that RubyGems was not able to install due to some checksum error, go to one version below the latest, e.g.,
$ rvm rubygems latest
9. Let’s tell RVM to use Ruby 2.0.0 as our default
$ rvm use ruby-2.0.0-p247 --default
Using /home/samdc/.rvm/gems/ruby-2.0.0-p247
10. Let’s check the version of Ruby in our environment
$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]

Install Rails

11. First, let’s set our gems environment, due to some contraints (I think it’s the corporate firewall preventing installation of certs) Add these lines to your ~/.gemrc:
:ssl_verify_mode: 0
:sources:
- http://rubygems.org/
- http://gems.github.com
gem: --no-rdoc --no-ri
The last line is to not install rdoc and ri

12. Let’s install Rails. We wan’t to make use of GemSets so we can easily manage versioning in our installs. Create a gemset:
$ rvm gemset create RailsDev
gemset created RailsDev => /auto/home3/delacs/.rvm/gems/ruby-2.0.0-p247@RailsDev
13. Let’s use that GemSet:
$ rvm gemset use RailsDev
Using ruby-2.0.0-p247 with gemset RailsDev
Let’s check if we are using that gemset
$ rvm gemset name
RailsDev
14. Now let’s install all gems that we need
$ gem install rails --version 4.0.1
15. Lets verify the installation
$ rails -v
Rails 4.0.1
16. To make use of this RVM environment, we can specify 2 files in the project’s root folder:
$ cat .ruby-gemset
RailsDev

$ cat .ruby-version
ruby-2.0.0-p247
To learn more about RVM and its environment, refer to these posts: http://yakiloo.com/using-rvm/ http://stackoverflow.com/questions/15708916/use-rvmrc-or-ruby-version-file-to-set-a-project-gemset-with-rvm

17. To make use of automatic install of rubies, you can specify a flag in ~/.rvmrc
rvm_install_on_use_flag=1
18. You also make bootstrapping a project happen via cd into the project directory, by adding this to ~/.rvmrc
export rvm_project_rvmrc=1
19. To access webrick from another system, firewall needs to be opened up for port 3000 as follows:
$ sudo firewall-cmd --permanent --zone=public --add-port=3000/tcp
$ sudo systemctl restart firewalld.service

10.15.2013

Open up Firewall of Fedora Core 19

Here's the whole write up on FirewallD.
How you would open up http and https, or specific ports for your box:
$ sudo firewall-cmd --permanent --zone=public --add-service=http
$ sudo firewall-cmd --permanent --zone=public --add-service=https
Restart the firewall:
$ sudo systemctl restart firewalld.service
Or on specific ports:
$ sudo firewall-cmd --permanent --zone=public --add-port=9393/tcp
Restart the firewall:
$ sudo systemctl restart firewalld.service

10.09.2013

How to Install RVM, Ruby and Sinatra

For my reference:
http://yakiloo.com/using-rvm/
http://ryanbigg.com/2010/12/ubuntu-ruby-rvm-rails-and-you/
http://rvm.io/rvm/best-practices

For this installation I followed what’s called single user installation, which is the recommended way of installation, this is an isolated install within a user's $HOME, not for root.

Install RVM

1. Set rvm_path
$ echo 'rvm_path="$HOME/.rvm"' >> ~/.rvmrc
2. Install RVM as a single user ( background info: https://rvm.io/rvm/install)
$  \curl -L https://get.rvm.io | bash -s stable
3. At this point, RVM should have been installed, check if rvm was installed correctly by loading it then checking it’s type:
$ source ~/.rvm/scripts/rvm
$ type rvm | head -n 1
rvm is a function
4. Make sure that the latest version is installed
$ rvm get stable
5. Run the rvm requirements to get all the dependencies for RVM, this might prompt for your password when it needed to install missing packages:
$ rvm requirements
Checking requirements for fedora.
Installing requirements for fedora.
Updating system
Installing required packages: patch, gcc-c++, patch, readline-devel, zlib-devel, libyaml-devel, libffi-devel, openssl-devel, autoconf, automake, libtool, bisondelacs password required for '/usr/bin/env PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/bin/Aptana_Studio_3:/auto/home3/delacs/bin:/auto/home3/delacs/.rvm/bin:/sbin yum install -y patch gcc-c++ patch readline-devel zlib-devel libyaml-devel libffi-devel openssl-devel autoconf automake libtool bison': 
....................................................................................................................................................................................................................
Requirements installation successful.

Install Ruby

6. Now let’s install Ruby:
$ rvm install 1.9.3
7. The above command should install RubyGems with it, if in case there is an issue such that RubyGems was not able to install due to some checksum error, go to one version below the latest, e.g.,
$ rvm rubygems 2.1.8
8. Let’s tell RVM to use Ruby 1.9.3 as our default
$ rvm use ruby-1.9.3-p448 --default
Using /auto/home3/delacs/.rvm/gems/ruby-1.9.3-p448
9. Let’s check the version of Ruby in our environment
$ ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-linux]

Install Sinatra

10. First, let’s first set our gem environment, due to some contraints (I think it’s our firewall preventing installation of certs) Add these lines to your ~/.gemrc:
:sources:
- http://rubygems.org/
- http://gems.github.com
gem: --no-rdoc --no-ri
The last line is to not install rdoc and ri

11. Let’s install Sinatra. We wan’t to make use of GemSets so we can easily manage versioning in our installs. Create a gemset:
$ rvm gemset create SinatraDev
gemset created SinatraDev => /auto/home3/delacs/.rvm/gems/ruby-1.9.3-p448@SinatraDev
12. Let’s use that GemSet:
$ rvm gemset use SinatraDev
Using ruby-1.9.3-p448 with gemset SinatraDev
Let’s check if we are using that gemset
$ rvm gemset name
SinatraDev
13. Now let’s install all gems that we need
$ gem install sinatra -v 1.4.3
$ gem install shotgun -v 0.9
14. To make use of this RVM environment, we can specify 2 files in the project’s root folder:
$ cat .ruby-gemset
SinatraDev
 
$ cat .ruby-version
ruby-1.9.3-p448
To learn more about RVM and its environment, refer to these posts: http://yakiloo.com/using-rvm/ http://stackoverflow.com/questions/15708916/use-rvmrc-or-ruby-version-file-to-set-a-project-gemset-with-rvm 15. To make use of automatic install of rubies, you can specify a flag in ~/.rvmrc
rvm_install_on_use_flag=1
16. You also make bootstrapping a project happen via cd into the project directory, by adding this to ~/.rvmrc
export rvm_project_rvmrc=1
17. To access webrick from another system, firewall needs to be opened up for port 9393 as follows:
$ sudo firewall-cmd --permanent --zone=public --add-port=9393/tcp
$ sudo systemctl restart firewalld.service
18. Start WEBrick using shotgun:
$ shotgun main.rb --host mymachine.domain.com

How to add Launcher in Gnome for Fedora 19

Create a .desktop file:
$ sudo vi /usr/share/applications/aptana-studio-3.desktop
Add this content:
[Desktop Entry]
Name=Aptana Studio 3
Exec=/usr/local/bin/Aptana_Studio_3/aptana
Icon=/usr/local/bin/Aptana_Studio_3/icon.xpm
Type=Application
Categories=Development

10.03.2013

VNC Server Setup on Fedora 19

I followed this post to setup my VNC Server. Specific to my setup I had to update my /etc/systemd/system/vncserver@:1.service so that it will wait for autofs for my home directory:
After=syslog.target network.target autofs.service
Then I had to open up the ports for VNC as follows:
$ sudo firewall-cmd --permanent --zone=public --add-service=vnc-server

9.24.2013

Bash Keyboard Shortcuts

Ctrl + A        Go to the beginning of the line you are currently typing on
Ctrl + E        Go to the end of the line you are currently typing on
Ctrl + L        Clears the Screen, similar to the clear command
Ctrl + U        Clears the line before the cursor position. If you are at the end of the line, clears the entire line.
Ctrl + H        Same as backspace
Ctrl + R        Let’s you search through previously used commands
Ctrl + C        Kill whatever you are running
Ctrl + D        Exit the current shell
Ctrl + Z        Puts whatever you are running into a suspended background process. fg restores it.
Ctrl + W        Delete the word before the cursor
Ctrl + K        Clear the line after the cursor
Ctrl + T        Swap the last two characters before the cursor
Esc + T         Swap the last two words before the cursor
Alt + F         Move cursor forward one word on the current line
Alt + B         Move cursor backward one word on the current line
Tab             Auto-complete files and folder names

9.19.2013

Vi Text Editor My Frequently Used Commands

h              move cursor one character to left
j              move cursor one line down
k              move cursor one line up
l              move cursor one character to right
w              move cursor one word to right
b              move cursor one word to left
0              move cursor to beginning of line
$              move cursor to end of line
nG             move cursor to line n
1G             move cursor to 1st line
G              move cursor to last line
control-f      scroll forward one screen
control-b      scroll backward one screen

gx             jump to method definition

zi             switch folding on or off
za             toggle current fold open/closed
zc             close current fold
zR             open all folds
zM             close all folds
zv             expand folds to reveal cursor

i              insert to left of current cursor position (end with ESC)
a              append to right of current cursor position (end with ESC)
dw             delete current word (end with ESC)
cw             change current word (end with ESC)
r              change current character
~              change case (upper-, lower-) of current character

dd             delete current line
D              delete portion of current line to right of the cursor
x              delete current character
dgg            delete current line to the top of the file
jdG            delete all lines below current line
ma             mark currrent position
d`a            delete everything from the marked position to here
`a             go back to the marked position
p              dump out at current place your last deletion (``paste'')

u              undo the last command 
.              repeat the last command 

J              combine (``join'') next line with this one

:w             write file to disk, stay in vi
:q!            quit VI, do not write file to disk,
ZZ             write file to disk, quit vi

:r filename    read in a copy of the specified file to the current
               buffer

/string        search forward for string (end with Enter)
?string        search backward for string (end with Enter)
n              repeat the last search (``next search'')
N              repeat the last search backward
/\cstring      case insensitive prepend with \c

:s/s1/s2       replace (``substitute'') (the first) s1 in this line by s2
:lr/s/s1/s2/g  replace all instances of s1 in the line range lr by s2
               (lr is of form 'a,b', where a and b are either explicit
               line numbers, or . (current line) or $ (last line)
:map k s       map the key k to a string of vi commands s (see below)
:abb s1 s2     expand the string s1 in append/insert mode to a string 
               s2 (see below)
%              go to the "mate," if one exists, of this parenthesis
               or brace or bracket (very useful for programmers!)

:%s/foo/bar/g  replace every 'foo' with a 'bar'
:!command      execute a command from vi
:%!perltidy    format perl code using perltidy from within vi
:%!perltidy -l=0    ignore line length 
:noh           remove search highlighting
:sp            to split window horizontally
:vsp           to split window vertically
<ctrl-w>h|j|k|l to navigate between split windows
<ctrl-w>q      to quit split window 

Comment/Uncomment:
Press Ctrl+V and go down until the last commented line and press x, that will delete all the # characters vertically.

For commenting a block of text is almost the same: First, go to the first line you want to comment, press Ctrl+V, and select until the last line. Second, press Shift+I, then #, then Esc.

Indent several lines at once:
Press Ctrl+V and go down until the last line to be indented, press Shift+>

Cut/Copy and Paste:
Position the cursor where you want to begin cutting.
Press v (or upper case V if you want to cut whole lines).
Move the cursor to the end of what you want to cut.
Press d to cut or y to copy.
Move to where you would like to paste.
Press P to paste before the cursor, or p to paste after.
Copy and paste can be performed with the same steps, only pressing y instead of d in step 4.
The name of the mark used is related to the operation (d:delete or y:yank).

9.17.2013

Linux Cheat Sheet

1. Find Out Linux Distribution Name and Version:
$ cat /etc/∗-release
Red Hat Enterprise Linux Server release 5 (Tikanga)
2. Use scp (Cygwin) to transfer files:
>scp -r [user_name]@[host_name or host_ip]:[Path to your directory] [target_path_dir]
>scp -r root@server.domain.com:/tmp/example.zip .
>scp -r user@your.server.example.com:/path/to/foo /home/user/Desktop/
from local to remote server:
>scp file* root@server.domain.com:/tmp
3. Copy files from a linux server to another linux server
rsync -auv -e ssh --progress source_folder/ useraccount@machine.whatever.com:/destination_folder/
4. Find files using 'find'
#find files from current directory and subdirectories that matches mon*
$ find . -name mon\*

#find files from current directory and subdirectories displaying the full path
$ find `pwd` -name koala\*
#or
$ find `pwd` | grep koala

#find files older than 90 days and move to another directory
$ find /home/perf-builder/deploy -maxdepth 1 -mtime +90 -type f -exec mv "{}" /perflogs/deploy_package_archive/ \;

#find files that are writable by anyone
$ find -maxdepth 1 -type f -perm /222

#find files that are writable by their owners
$ find -maxdepth 1 -type f -perm /200
5. Delete environment variable
$ env | grep rvm
OLDPWD=/home/samdc/.rvm
$ unset OLDPWD
6. Set environment variable
$ export PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
7. Monitor log file as the file grows using tail
$ tail -f /home/sammydc/logs/request.log
8. Search a directory for files containing certain string
$ grep -r "192.168.1.5" /etc/
$ grep -E "whatever" -r .   - recursive on current dir and subdirs
# multi-line grep
$ grep -Ezl "FC_count\s+2.*autoselect\s+yes.*client_os_version_linux\s+CentOS 6.5.*fc_switch\s+ls-dur3-mds2.*motherboard_product_name\s+.*C240.*use_for_group\s+Perf" *.cfg
# grep from different directories from July 21 – July 28
grep 'caught exception: ERROR' /mnt/perfresults/*/logs/2016072[1-8]_*/controller_log
9. This will show process id, user, command and arguments:
$ ps -e -o "pid,user,comm,args"
10. Cat a bunch of files at once
$ for f in /var/log/*.log; do cat $f; done
11. Iterate thru a list and apply operation
Copy a file to multiple destination
$ for FILE in {544..579}; do cp perf-c440 perf-c$FILE; done

Ping several clients
$ for CLIENT in client1 client2 client3; do ping $CLIENT -c2; done
12. Filter using grep with regex
$ ps -efw | grep -E '5\.5.*dd670'
13. List directories up to 3 levels down, then filter
$ ls -d ./*/*/* | grep 416041
14. Get number of cpus
$ cat /proc/cpuinfo | grep processor | wc -l
15. Get memory info
$ cat /proc/meminfo
16. Get disks info
$ cat /proc/partitions
$ df -H
17. How to determine biggest directories/files occupying disk
$ df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda5             26011288  24703036         0 100% /
/dev/sda1               202219     63562    128217  34% /boot
$ df -BG  (in GigaBytes)
Filesystem           1G-blocks      Used Available Use% Mounted on
/dev/dd_dg0_0p15            2G        2G        1G  68% /
/dev/dd_dg0_0p14            5G        4G        2G  72% /ddr
/dev/dd_dg0_0p13           30G       30G        0G 100% /ddr/var

$ du -a /home | sort -n -r | head -n 10
14259824        /home
14259052        /home/delacs
14259048        /home/delacs/scheduler
14256188        /home/delacs/scheduler/ctl
9382796 /home/delacs/scheduler/ctl/run_request.log
3238172 /home/delacs/scheduler/ctl/resourcedb.log
1036148 /home/delacs/scheduler/ctl/requestdb.log
569516  /home/delacs/scheduler/ctl/update_resource_status.log
29492   /home/delacs/scheduler/ctl/www_index.log
2056    /home/delacs/scheduler/resources

$ du -h /home | sort -h -r | head -n 10 (human readable form)
$ du -ahx / | sort -h -r | head -n 50 (exclude mounted directories)
18. Which processes take so much... Memory
$ ps -e -o pid,vsz,command | sort -n -r -k 2 | head -n 20
22796 345320 /usr/sbin/httpd
22799 344772 /usr/sbin/httpd
22907 344392 /usr/sbin/httpd
27749 242936 run_request_id_20140614_0800_mweb_dur
26515 217668 run_request_id_20140725_1738_mweb_dur
20061 217476 run_request_id_20140724_1600_mweb_dur
27748 215428 run_request_id_20140614_0800_mweb_dur
...
CPU
$ ps -eo pcpu,pid,user,args | sort -k1 -r -n | head -20
 8.8  9341 ioperf   /usr/bin/python /home/ioperf/maestro-production/cloudapi/pcrun.py --noTty --logLevel DEBUG -s /tmp/tmpsap5Fn/cfg.json -w /tmp/tmpsap5Fn/cfg.json -r /tmp/tmpsap5Fn/cfg.json --scriptDir /home/ioperf/maestro-production --resultDirBase /data/maestro_prod/vsan-fio
 7.0 29457 ioperf   /usr/bin/python /home/ioperf/maestro-production/cloudapi/pcrun.py --noTty --logLevel DEBUG -s /tmp/tmpUvSJTh/cfg.json -w /tmp/tmpUvSJTh/cfg.json -r /tmp/tmpUvSJTh/cfg.json --scriptDir /home/ioperf/maestro-production --resultDirBase /data/maestro_prod/vsan-fio
 0.4  8817 root     /usr/bin/etserver --daemon --cfgfile=/etc/et.cfg
...
19. Find files and delete them
The basic find command syntax is:
find dir-name criteria action
dir-name : - Defines the working directory such as look into /tmp/
criteria : Use to select files such as "*.sh"
action : The find action (what-to-do on file) such as delete the file.

$ find . -name ".nfs000000000006a8b200000062" -exec rm -rf {} \;

Options:
-name "FILE-TO-FIND" : File pattern.
-exec rm -rf {} \; : Delete all files matched by file pattern.
20. Echo string with a tab and append to end of a file
$ echo -e "autoselect\tyes" >> perf-c576
21. Count number of directories
$ echo 201404*/ | wc
22. Prepend contents of a file to another file
echo -e "`cat list.idx.forcopy`\n$(cat list.idx)" > list.idx
23. Script execution time
$ time ./monitor_regression.pl
...
Output
...
real    0m57.766s
user    0m0.444s
sys     0m0.805s
24. NFS mount
# mount -t nfs -o rw,nosuid,nodev,tcp,intr,nolock perfresultsSC:/backup /mnt/perfresultsSC/
25. Time sync
# ntpdate time-server-name-or-ip
26. Start process in background
$ ./my_process >std.txt 2>err.txt &
$ ./my_process >std.txt 2>&1 & (both stdout and stderr goes to the same file)
$ ./my_process >/dev/null 2>err.txt & (don't care about output, but stderr is recorded)
27. Monitor CPU & Memory utilization
Get CPU utilization every 2 minutes and run forever
$ mpstat -P ALL 120 > mpstat.log &
Get memory utilization every 2 minutes in 2 weeks
$ sar -r 120 10080 > sar.log &
27. Put currently running process in the background
$ Ctrl+Z
$ bg
# be able to exit out of ssh connection without affecting the running process
$ disown -h
27. Memory usage of a process, units in MB
$ smem -P server.rb
  PID User     Command         Swap      USS      PSS      RSS 
 2176 samdc    ruby server.rb     0   240052   241281   246296 
28. Create a tarball
$ tar -cvf openssh.deploy.tar file1 file2
$ tar -zcvf archive-name.tar.gz directory-name
$ tar -zcvf archive-name.tar.gz directory-name --remove-files (to remove original directory and files)
29. View tarball contents
$ tar -tvf openssh.deploy.tar
30. Extract tarball
$ tar -xvf openssh.deploy.tar
31. Kill processes at once
$ ps -efw | grep rvc | grep '1  ' | awk '{print $2}' | xargs -I{} kill -9 {}
Safer...
$ ps -ewf | grep rvc | grep 10.92.81.163 | awk '{print $2}' | xargs -I{} kill -9 {}
30. Rename files in directory at once
$ for file in *.log; do mv "$file" "$file.old"; done
31. How to remove all empty directories in a subtree
$ find ROOTDIR -type d -empty -delete
e.g.
$ find /mnt/maestro/maestro_prod/vsan-fio/15278 -type d -empty -delete
32. Find out how much space files occupy in a directory
$ du -bch

9.13.2013

Ruby Gems Issues

Just a list of issues that I want to take note of while using ruby gems.

Encountered this problem when I tried to install Sinatra:
>gem install sinatra
ERROR:Could not find a valid gem 'sinatra' (>= 0), here is why: Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://s3.amazonaws.com/production.s3.rubygems.org/latest_specs.4.8.gz)
Solution is to specify the source explicitly and use http instead of https:
>gem install sinatra --source http://rubygems.org/

9.12.2013

MySQL Cheat Sheet

1. Connect to MySQL server in localhost
>mysql -u username -p password [databasename]
2. Executing SQL Statements from a Text File
mysql> source c:\filename.sql
3. Migrate database
# everything
$ mysqldump -u [user] -p --opt mydb > mydb.sql

# To export to file (data only)
mysqldump -u [user] -p --no-create-info mydb > mydb.sql

# To export to file (structure only)
mysqldump -u [user] -p --no-data mydb > mydb.sql

# To import to database
mysql -u [user] -p mydb < mydb.sql

3.18.2013

PowerShell Script that removes VSS bindings and files from a Visual Studio Project

Below is a powershell script I found from the web that I have been using for a while to remove the bindings from SourceSafe.

First, unbind the project from VSS within Visual Studio, then run this script.
# This script removes VSS bindings and files from a VS Project
# Taken from http://blog.magenic.com/blogs/daniels/archive/2008/11/18/Removing-VSS-Bindings-to-Migrate-SSRS-2005-Solutions-to-TFS-Using-Powershell.aspx

# First thing to do before running this script is to specify where the project is located
$Folder = "C:\dev\vs\2008\SalesSync"
#first clear the read-only flag from all files
get-childitem "$folder" -Recurse | % {         
        # Test for ReadOnly flag and remove if present 
     if ($_.attributes -band [system.IO.FileAttributes]::ReadOnly) {  
            $_.attributes = $_.attributes -bxor [system.IO.FileAttributes]::ReadOnly 
   }
}

#next delete all files that are *.suo, *.user, and *.*scc - we don't want them in TFS
Get-ChildItem  $folder *.suo -Recurse -Force | Remove-Item -Force
Get-ChildItem  $folder *.*scc -Recurse -Force | Remove-Item -Force
Get-ChildItem  $folder *.user -Recurse -Force | Remove-Item -Force

#next get all the .sln file - and remove the VSS binding information
$files = Get-ChildItem $folder *.sln -Recurse 
foreach ($file in $files) {
 $fileout = $file.FullName + ".new"
 Set-Content $fileout $null
 $switch=0
 Get-Content $file.FullName | % {
  if ($switch -eq 0) {
   if ($_  -eq " GlobalSection(SourceCodeControl) = preSolution") {
    #we found the section to skip - so set the flag and don't copy the content
    $switch=1}
   else {
    #we haven't found it yet - so copy the content
    Add-Content $fileout $_
   }        
   }
  elseif ($switch -eq 1) {
   if ($_ -eq " EndGlobalSection") {
    #last line to skip - after it we start writing the content again
    $switch=2}
   }
  else 
   { #write remaining lines
    Add-Content $fileout $_}
 }
 #remove the original .sln and rename the new one
 $newname = $file.Name
 Remove-Item $file.FullName
 Rename-Item $fileout -NewName $newname
}

3.15.2013

Client-Side Validation for a Custom DataAnnonation in MVC 4

This is a continuation of my previous post. This is based from this excellent tutorial.

First step is to implement IClientValidatable interface in the FileTypesAttribute class:
public class FileTypesAttribute : ValidationAttribute, IClientValidatable {
        private readonly List _types;
        private readonly string specifiedTypes;

        public FileTypesAttribute(string types) {
            _types = types.Split(',').ToList();
            specifiedTypes = types;
        }

        public override bool IsValid(object value) {
            if (value == null) return true;
            var postedFile = value as HttpPostedFileBase;
            var fileExt = System.IO.Path.GetExtension(postedFile.FileName).Substring(1);
            return _types.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
        }

        public override string FormatErrorMessage(string name) {
            return string.Format("Invalid file type. Only {0} are supported.", String.Join(", ", _types));
        }

        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "filetypes";
            rule.ValidationParameters.Add("types", specifiedTypes);
            yield return rule;
        }
    }
Things to note here are the validationtype="filetypes" and the added parameter="types", which can be observed in the emitted html below:
<input data-val="true" data-val-filetypes="Invalid file type. Only xls, xlsx are supported."
data-val-filetypes-types="xls,xlsx" data-val-required="The AttachmentTrace field is required."
id="AttachmentTrace" name="AttachmentTrace" type="file" value="" />
The added parameter called types has a value of "xls,xlsx". This parameter and validationtype are significant because it will be used for the jquery validator and adapter as follows:
$(function () {
    // custom validation method
    $.validator.addMethod("filetypes",
        function (value, element, params) {
            if (value == null) return true;
            var fileExtension = value.split('.').pop().toLowerCase();
            var types = params.toLowerCase();
            return types.indexOf(fileExtension) !== -1;
        }
    );
    // add to unobtrusive adapters
    $.validator.unobtrusive.adapters.addSingleVal("filetypes", "types");
} (jQuery));
The value has the contents of the input element, while params has the parameter value of "xls,xlsx" from the data annotation.

3.13.2013

ModelState.IsValid always returning False for RegularExpression ValidationAttribute for a File Upload in MVC 4

I posted a question in stackoverflow and ended up answering it on my own. Some people gave me clues along the way so I'm thankful. I just want to do a recap of the solution that way I have it in my notes...

I was having issues with model validation using RegularExpression as indicated in my class below, the property AttachmentTrace is a file attachment that is uploaded during form post.
public class Certificate {
    [Required]
    // TODO:  Wow looks like there's a problem with using regex in MVC 4, this does not work!
    [RegularExpression(@"^.*\.(xlsx|xls|XLSX|XLS)$", ErrorMessage = "Only Excel files (*.xls, *.xlsx) files are accepted")]
    public string AttachmentTrace { get; set; }
}
All the while I thought there's something wrong with my Regex. But after looking closely on this issue, I found out that what is being validated on the server side is the string "System.Web.HttpPostedFileWrapper", and not the actual filename. That's the reason why ModelState.IsValid returns a false everytime, no matter how right the regex is. But I cannot simply switch the property type of string to HttpPostedFileBase in my model, because I'm using EF code-first migration, which will result into an unpleasant error message when adding a migration.

So the solution to this is to employ a ViewModel, instead of the Entity directly:
public class CertificateViewModel {
    // .. other properties
    [Required]
    [FileTypes("xls,xlsx")]
    public HttpPostedFileBase AttachmentTrace { get; set; }
}
The next step is to create a custom ValidationAttribute for the FileTypes:
public class FileTypesAttribute : ValidationAttribute {
    private readonly List _types;

    public FileTypesAttribute(string types) {
        _types = types.Split(',').ToList();
    }

    public override bool IsValid(object value) {
        if (value == null) return true;
        var postedFile = value as HttpPostedFileBase;
        var fileExt = System.IO.Path.GetExtension(postedFile.FileName).Substring(1);
        return _types.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    public override string FormatErrorMessage(string name) {
        return string.Format("Invalid file type. Only {0} are supported.", String.Join(", ", _types));
    }
}
In the controller Action, use the ViewModel instead of the Entity, then map the ViewModel back to the Entity via AutoMapper:
public ActionResult Create(CertificateViewModel certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail) {
        if (ModelState.IsValid) {
            // Let's use AutoMapper to map the ViewModel back to our Certificate Entity
            // We also need to create a converter for type HttpPostedFileBase -> string
            Mapper.CreateMap().ConvertUsing(new HttpPostedFileBaseTypeConverter());
            Mapper.CreateMap();
            Certificate myCert = Mapper.Map(certificate);
            // other code ...
        }
        return View(myCert);
    }
For the AutoMapper, create a TypeConverter for HttpPostedFileBase:
public class HttpPostedFileBaseTypeConverter : ITypeConverter {

    public string Convert(ResolutionContext context) {
        var fileBase = context.SourceValue as HttpPostedFileBase;
        if (fileBase != null) {
            return fileBase.FileName;
        }
        return null;
    }
}
I know, it's a lot of work, but this will ensure the file extension validation will be done correctly. But wait, this is not yet complete, I need to also make sure that the client side validation will work for this and that will be the topic of my next post.

3.11.2013

Download Any File Type in ASP.NET MVC 4 FileResult

Just simply specify a generic Octet stream as the contentType:
        public FileResult Download(string filename) {
            filename = Server.HtmlEncode(filename);
            string filePath = ConfigurationManager.AppSettings["SignatureFilesPath"];
            string contentType = System.Net.Mime.MediaTypeNames.Application.Octet;
            return File(Path.Combine(filePath, filename), contentType, filename);
        }

Configure MachineKey When Deploying App In A Web Farm

One thing to keep in mind when deploying in a web farm is that if you are using form authentication, or ViewState, and you want to keep your session alive across the web farm, you need to specify an machineKey in the web.config file. This is how it looks like:
<system.web>
     <machineKey validationKey="C82FF1CB5C0B723C0C6682274C87AE0A32E957D05846F505A1968D30EB41B7C34175741FFC45C20D89915C05D133EDE69154E9EDC6B82F7B76B24009B09DF299" decryptionKey="A941AD982309BBC34B1D17C2E5C3A27298CB32EBB29C7AD94F513ACCE09B1F06" validation="SHA1" decryption="AES"></machineKey>
</system.web>
You should generate your own machineKey, here's a machineKey generator.
Reference from msdn.

Setting Up Folder Permissions For Uploading Files in IIS 6

There are so many solutions to this problem. But it all boils down to the permissions given to the account to be used in accessing a particular resource. Assuming the website is saving a document to a Windows Share on another server. You will have to give Read/Write access to your account of choice (a system account maybe that password never expires) to that particular Share. Then in the web.config file, configure impersonation to use that same account like so ...
<system.web>
     <identity impersonate="true" userName="dom1\sys-account" password="mypass"></identity />
Here's a post from msdn regarding IIS Authentication with impersonation. In particular about intranet scenarios.

3.08.2013

EF Code First Migrations - How To Sync To Production DB

It's very simple to push out the changes in the database across any db that would need the changes, be it your test, staging or production servers. All you have to do is to create a SQL script via Update-Database with a -Script flag:
PM>Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: AddPostAbstract
Because of the -Script switch, Code First Migrations will run the migration pipeline but instead of actually applying the changes it will write them out to a .sql file for you. Neat.

Complete write up from Microsoft is here.

If you are doing this for the first time, and you need all the changes so far, you just need to do this:
PM>Update-Database -Script -SourceMigration: $InitialDatabase
Here's a sample PM console session:
PM> Update-Database -Script -SourceMigration: $InitialDatabase
Applying code-based migrations: [201301240307501_Initial, 201302020143144_ModifiedEmailTableAndAddedSignatureTable, 201302020149599_AddedCreatorToSignatureRelation, 201302020158207_ChangeSignatureIdToNullable, 201302050122407_AddResultingImageFileToSignatureTable, 201302050154113_AddLabelToSignatureTable, 201302052134222_ChangedAddressToHave3LineItems, 201302090226121_ChangedSignatureFileToRequired, 201302121909589_AddedSalesItemClass, 201302192149411_AddedCustomerClass, 201302210141465_AddedLocationInIamProfileClass, 201302260305398_UpdatedCertificateClass].
Applying code-based migration: 201301240307501_Initial.
Applying code-based migration: 201302020143144_ModifiedEmailTableAndAddedSignatureTable.
Applying code-based migration: 201302020149599_AddedCreatorToSignatureRelation.
Applying code-based migration: 201302020158207_ChangeSignatureIdToNullable.
Applying code-based migration: 201302050122407_AddResultingImageFileToSignatureTable.
Applying code-based migration: 201302050154113_AddLabelToSignatureTable.
Applying code-based migration: 201302052134222_ChangedAddressToHave3LineItems.
Applying code-based migration: 201302090226121_ChangedSignatureFileToRequired.
Applying code-based migration: 201302121909589_AddedSalesItemClass.
Applying code-based migration: 201302192149411_AddedCustomerClass.
Applying code-based migration: 201302210141465_AddedLocationInIamProfileClass.
Applying code-based migration: 201302260305398_UpdatedCertificateClass.
Once the script is generated, Visual Studio opens the script for you to save. What I do is just simply copy and paste the resulting sql script to SQL Server Management Studio, then execute it there against the database. Done!

There's a little hickup:
I got this error message, which means that the script generator is unable to remove duplicate variable declarations in the sql. The solution is to simply delete such duplicate declarations.

Msg 134, Level 15, State 1, Line 101 The variable name '@var0' has already been declared. Variable names must be unique within a query batch or stored procedure.

How To Setup SecurityGuard.MVC4 And MvcInstaller.MVC4 For ASP.NET MVC 4 Application

I love this open source project called SecurityGuard.  It is a complete ASP.NET Membership management system plugin for ASP.NET MVC 4 application.

To install via NuGet:
PM> Install-Package SecurityGuard.MVC4
To make it easier to create and setup the Membership database tables and roles, I recommend to use another Nuget package called MvcInstaller.MVC4:
PM> Install-Package MvcInstaller.MVC4
Follow these steps to setup SecurityGuard.
Follow these steps to setup MvcInstaller.

For the MvcInstaller, the following requirements should be met prior to running the installer for the first time:

1. Create the database, and make sure to create the db login account to be used in accessing this database.
2. Modify the installer.config file, example is as follows:
<installerconfig>
  <applicationname>ProductCoC</applicationname>
  <path>
    <relativesqlpath>App_Data</relativesqlpath>
  </path>
  <membership create="true" providername="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
  <profile providername="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
  <rolemanager providername="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
    <roles>
      <role name="Administrator">
        <users>
          <user email="sammydc@mail.com" password="ProductCoC" secretanswer="Green" secretquestion="Favorite Color" username="WBI\sammydc">
        </user></users>
      </role>    
      <role name="SecurityGuard">
        <users>
          <user email="sammydc@mail.com" password="ProductCoC" secretanswer="Green" secretquestion="Favorite Color" username="WBI\sammydc">
        </user></users>
      </role>
    </roles>
  </rolemanager>
  <sessionstate providername="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
  <database usetrustedconnection="false">
    <connectionstringname>MembershipConnection</connectionstringname>
    <datasource>MSSQ4\Instance1</datasource>
    <initialcatalog>ProductCoC</initialcatalog>
    <username>ProductCoC</username>
    <password>ProductCoC</password>
  </database>
</sessionstate></profile></membership></installerconfig>
3. Make sure that the AppInstalled setting in web.config is set to false
<appsettings>
 <add key="AppInstalled" value="false" />
</appsettings>
4. Now deploy the MVC 4 application. After deployment, from the browser, navigate to the install path, you should see this on the browser:



5. Make sure to select Use SecurityGuard, then click Install.

6. After a few seconds, it should display a message that the installer completed successfully.

7. Check the database to make sure that the tables and users have been created, in SQL Server Management Studio, it should look like this:



8. Finally, go to /SecurityGuard/Membership/Index, this is what you should see:



Success! Now we have an instant membership management for our app.

Issues encountered during implementation and deployment:

1. When I deployed this to the production server, I got an error like below because the installer.config and web.config are inaccessible:



To overcome this issue, I needed to temporarily add, the Everyone group in windows to have modify access to these files. Make sure to change back the permissions right after the setup.

2. Another issue that I encountered is that because the application is intended for the intranet and I'm using windows integrated security, there is a problem when using an account preceded by a domain name such as DOM1\sammydc, the backslash causes some issues with the UI and routing logic. I will write up the solution to this problem on my next post.

3.07.2013

Syntax Highlighter for Blogger using Prettyfy

Adding Prettify Syntax Highlighter to any CMS or webpage is very easy. For Blogger you just need to go to your blog’s Template tab, click “Edit HTML” button and add the below script before </head> tag.
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js">
As you can see that the project is hosted on Google Code. This is an auto-loader which will automatically load the required JavaScript API and the CSS file from the subfolders of SVN. So the last thing that you are left is to mention where it should highlight the codes by adding class="prettyprint" to pre and/or code tags within Blogger Post Editor, HTML view. Here is an example:
<pre class="prettyprint">
$(function() {
 alert('I am using Prettify as Syntax Highlighter');
});
</pre>
There are also some styles available that you can call and load the stylesheet in one URL, here is an example:
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>

2.27.2013

AraNight - My Color Scheme for Visual Studio

I have been changing my color scheme for Visual Studio.  I have decided to share it at...

http://studiostyl.es/schemes/aranight

2.20.2013

Alternating Colors Table Rows Css

Pure CSS Solution for alternating color rows for a table:

table.MyGrid tr:nth-child(even) {
    background:#ECF4FE;
}