CloudOps CloudStack Budapest, 2014

50
#CCCEU14 | #CloudStackWorks #CCCEU14 | #CloudStackWorks Test your cloud as code Pierre-Luc Dion ([email protected])

Transcript of CloudOps CloudStack Budapest, 2014

Page 1: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Test your cloud as code

Pierre-Luc Dion ([email protected])

Page 2: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Overview

• introduction

• Why?

• cloudstack_spec: how it work

Page 3: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

About Me

• Cloud Architect @ CloudOps

• Work full time with Apache CloudStack– As user

– As contributor

• Apache CloudStack PMC member

• Ruby and Chef Enthusiast

Page 4: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

About CloudOps

• CloudOps builds and operates CloudStack based clouds of all shapes and sizes

• Develops cloud infrastructure solutions and operational models

• 24x7x365 managed service for CloudStack based cloud infrastructures

• Customers are global

• Based in Montreal, Canada

Page 5: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Current state of the project

• Proof of concept

• Support– VPC

– Port Forwarding

– Create snapshot

– Create template from snapshot

– Various zone features validation.

Page 6: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Why ?

Page 7: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

What I’m trying to solve

• We have multiple LAB CloudStack installations running multiple versions and configurations. Need to validate their usability.

• CloudStack Release Upgrade tests on real hardware.

Page 8: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Monitoring is not enough

• Monitoring can tell if there is enough Secondary storage. But cannot tell if it’s usable in CloudStack.

• Monitoring cannot tell if Featured templates are usable.

Page 9: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

But what about Marvin?

Page 10: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

I did not tried Marvin

1. Look like it provision CloudStack configs and tests, right?

2. Defining tests require coding (from user perspective)

3. Could hardly benefit from ServerSpec, specinfra or test-kitchen

https://cwiki.apache.org/confluence/display/CLOUDSTACK/Marvin+-+Testing+with+Python

Page 11: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

cloudstack_spec

Page 12: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

The purposes

• Test existing CloudStack installation

• Validate functionality of a Cloud

• Advanced tests:– Port-forwarding rules into VPC

– Create Instance from Snapshot

– Create Template from Snapshot

Page 13: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

About cloudstack_spec

• Ruby Rspec based

• Based on ServerSpec

• Test case easy to define

• Use: – cloudstack_ruby_client

– serverspec

– specinfra

• Code maturity: under heavy dev

Page 14: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

It is not

• Deployment tool

• Replacement to Marvin

• Monitoring plugin/tool

• Reporting tool

Page 15: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

In Action

Page 16: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Define tests

Page 17: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Zone

require 'spec_helper'

describe zone do

it { should exist }

it { should be_allocated }

its(:local_storage) { should be_set }

its(:security_group) { should_not be_set }

its(:network_type) { should match("Advanced") }

end

Page 18: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Zone

require 'spec_helper'

describe zone do

it { should exist }

it { should be_allocated }

its(:local_storage) { should be_set }

its(:security_group) { should_not be_set }

its(:network_type) { should match("Advanced") }

end

Do I have a zone?

Page 19: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Zone

require 'spec_helper'

describe zone do

it { should exist }

it { should be_allocated }

its(:local_storage) { should be_set }

its(:security_group) { should_not be_set }

its(:network_type) { should match("Advanced") }

end

The zone is enabled

(allocated)?

Page 20: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Zone

require 'spec_helper'

describe zone do

it { should exist }

it { should be_allocated }

its(:local_storage) { should be_set }

its(:security_group) { should_not be_set }

its(:network_type) { should match("Advanced") }

end

rspec_its: eval method attributes

Page 21: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Zone

require 'spec_helper'

describe zone do

it { should exist }

it { should be_allocated }

its(:local_storage) { should be_set }

its(:security_group) { should_not be_set }

its(:network_type) { should match("Advanced") }

end

Easy valid on false

Page 22: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Zone

require 'spec_helper'

describe zone do

it { should exist }

it { should be_allocated }

its(:local_storage) { should be_set }

its(:security_group) { should_not be_set }

its(:network_type) { should match("Advanced") }

end

Rspec string validation

Page 23: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Output results

Page 24: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Output results

Page 25: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Output results

Page 26: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Output results

Page 27: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Does my zone have system VMs?

Page 28: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

System vm tests

%w(consoleproxy secondarystoragevm).each do |svm|

describe system_vm(svm) do

it { should exist }

it { should be_running }

it { should be_reachable }

end

end

Page 29: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

SVMs output

Page 30: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Create VM inside VPC and test the network

Page 31: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

VPC test Scope

• Create VPC

• Create VPC network Tier

• Create Instance

• Enable Port-Forwarding for SSH

Page 32: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

vpc_spec.rb

describe vpc('spec-vpc1') do

it { should be_created }

it { should exist }

it { should be_ready }

it { should be_reachable }

describe vpc_tier('tier11') do

it { should be_created }

it { should exist }

describe virtual_machine('vm-test1') do

it { should be_created }

it { should_not be_reachable }

it { should exist }

it { should be_running }

its(:open_pf_ssh) { should be_set }

context 'With port forwarding' do

it { should be_reachable.with( :port => 22, :proto => 'tcp' ) }

end

end

end

end

Page 33: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

vpc_spec.rb

describe vpc('spec-vpc1') do

it { should be_created }

it { should exist }

it { should be_ready }

it { should be_reachable }

describe vpc_tier('tier11') do

it { should be_created }

it { should exist }

describe virtual_machine('vm-test1') do

it { should be_created }

it { should_not be_reachable }

it { should exist }

it { should be_running }

its(:open_pf_ssh) { should be_set }

context 'With port forwarding' do

it { should be_reachable.with( :port => 22, :proto => 'tcp' ) }

end

end

end

end

be_createdCreate the object

Page 34: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

vpc_spec.rb

describe vpc('spec-vpc1') do

it { should be_created }

it { should exist }

it { should be_ready }

it { should be_reachable }

describe vpc_tier('tier11') do

it { should be_created }

it { should exist }

describe virtual_machine('vm-test1') do

it { should be_created }

it { should_not be_reachable }

it { should exist }

it { should be_running }

its(:open_pf_ssh) { should be_set }

context 'With port forwarding' do

it { should be_reachable.with( :port => 22, :proto => 'tcp' ) }

end

end

end

end

be_reachablePing test

Page 35: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

vpc_spec.rb

describe vpc('spec-vpc1') do

it { should be_created }

it { should exist }

it { should be_ready }

it { should be_reachable }

describe vpc_tier('tier11') do

it { should be_created }

it { should exist }

describe virtual_machine('vm-test1') do

it { should be_created }

it { should_not be_reachable }

it { should exist }

it { should be_running }

its(:open_pf_ssh) { should be_set }

context 'With port forwarding' do

it { should be_reachable.with( :port => 22, :proto => 'tcp' ) }

end

end

end

end

be_reachableTcp connection test

Using Public IP

Page 36: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Results of VPC tests…

Page 37: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

test execution (1/4)

Page 38: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

test execution (2/4)

Page 39: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

test execution (3/4)

Page 40: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

test execution (4/4)

Page 41: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Working with Rspec

Page 42: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Custom Rspec matcher

# If the zone is allocated (Enabled)

RSpec::Matchers.define :be_allocated do |expected|

match do |actual|

actual.allocated? == true

end

failure_message do |actual|

"status: #{actual.allocated?}"

end

description do

"be allocated (Enabled)"

end

failure_message_when_negated do |actual|

"Status: #{actual}"

end

end

Page 43: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

resources (Test cases)

• Test cases are:– Objects to test are Ruby Class:

CloudstackSpec::Resource::Snapshot

– Unit tests are Ruby Methods inside Class:

self.exist?

Page 44: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

What’s next?

Page 45: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Future improvements

• Provide as Gem

• Auto config, same as Serverspec

• More tests

• Better error message

• Add compatibility with ServerSpec

• test-kitchen compatibility?

Page 46: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Help needed

• ServerSpec integration– Test from within an instance

• More test scenarios

Page 47: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Future usage

• Validate new CloudStack release

• Cloud heath check

• Post automation tests

• Continuous Integration Tests (CI)

Page 48: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

Conclusion

• Test phase in the automated DevOps world

• Tests definition made easy.

• More tests case in progress.

Page 49: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

More Information

• Pierre-Luc Dion– [email protected]

– www.cloudops.com

–@CloudOps_

• Github– https://github.com/pdion891/

cloudstack_spec

Page 50: CloudOps CloudStack Budapest, 2014

#CCCEU14 | #CloudStackWorks

#CCCEU14 | #CloudStackWorks

Thank you!