Issues with kitchen converge using windows boxs

Hi people,

i ‘m working with test kitchen. I created successfully my machine using kitchen create but i can’ converge my node though

   Installing Chef Omnibus package C:\Users\vagrant\AppData\Local\Temp\chef-

true.msi

   Transferring files to <default-mwrock-Windows2012R2>

$$$$$$ & : The term ‘C:\opscode\chef\bin\chef-client.bat’ is not recognized
as the
$$$$$$ name of a cmdlet, function, script file, or operable program. Check the
$$$$$$ spelling of the name, or if a path was included, verify that the path is
$$$$$$ correct and try again.
$$$$$$ At line:4 char:3
$$$$$$ + & $env:systemdrive\opscode\chef\bin\chef-client.bat --local-mode –
config
$$$$$$ $env:T …
$$$$$$ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$$$$$$ + CategoryInfo : ObjectNotFound: (C:\opscode\chef\bin\chef-c
lient
$$$$$$ .bat:String) [], CommandNotFoundException
$$$$$$ + FullyQualifiedErrorId : CommandNotFoundException

This error is indicative that the chef client download failed. The error from the client download can get “hidden” and is more visibly noticable when you run the kitchen command with -l debug. Can you do that and respond with a gist to the output?

i ru kitchen converge -l debug and here is the message

    Installing Chef Omnibus package C:\Users\vagrant\AppData\Local\Temp\chef-

true.msi

$$$$$$ Exception calling "DownloadString" with "1" argument(s): "Unable to conne
ct to
$$$$$$ the remote server"
$$$$$$ At C:\Users\vagrant\AppData\Local\Temp\default-mwrock-Windows2012R2-long_
script
$$$$$$ .ps1:23 char:22
$$$$$$ + Try { $response = ($c = Make-WebClient).DownloadString($url) }
$$$$$$ + ~~~~~~~~~~~~~~~~~~~
$$$$$$ + CategoryInfo : NotSpecified: (:slight_smile: , MethodInvocationExcep
tion
$$$$$$ + FullyQualifiedErrorId : WebException
$$$$$$
$$$$$$ You cannot call a method on a null-valued expression.
$$$$$$ At C:\Users\vagrant\AppData\Local\Temp\default-mwrock-Windows2012R2-long_
script
$$$$$$ .ps1:26 char:3
$$$$$$ + $md = ConvertFrom-StringData $response.Replace("`t", "=")
$$$$$$ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$$$$$$ + CategoryInfo : InvalidOperation: (:slight_smile: , RuntimeException
$$$$$$ + FullyQualifiedErrorId : InvokeMethodOnNull
$$$$$$
$$$$$$ Exception calling "DownloadFile" with "2" argument(s): "The path is not o
f a
$$$$$$ legal form."
$$$$$$ At C:\Users\vagrant\AppData\Local\Temp\default-mwrock-Windows2012R2-long_
script
$$$$$$ .ps1:41 char:6
$$$$$$ + ($c = Make-WebClient).DownloadFile($url, $dst)
$$$$$$ + ~~~~~~~~~~~~~~~~~~~
$$$$$$ + CategoryInfo : NotSpecified: (:slight_smile: , MethodInvocationExcep
tion
$$$$$$ + FullyQualifiedErrorId : ArgumentException
$$$$$$
$$$$$$ msiexec was not successful. Received exit code 1619
$$$$$$ At C:\Users\vagrant\AppData\Local\Temp\default-mwrock-Windows2012R2-long_
script
$$$$$$ .ps1:55 char:28
$$$$$$ + if ($p.ExitCode -ne 0) { throw "msiexec was not successful. Received
exit
$$$$$$ code ...
$$$$$$ +
$$$$$$ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$$$$$$ + CategoryInfo : OperationStopped: (msiexec was not... exit
code
$$$$$$ 1619:String) , RuntimeException
$$$$$$ + FullyQualifiedErrorId : msiexec was not successful. Received exit c
ode 1
$$$$$$ 619
$$$$$$
D [WinRM] negotiate::http://127.0.0.1:55985/wsman<{:user=>"vagrant", :pass=

"vagrant", :elevated_username=>"vagrant", :elevated_password=>"vagrant", :no_ss
l_peer_verification=>true, :disable_sspi=>false, :basic_auth_only=>false}> (
$dirs = @("$env:TEMP\kitchen\clients", "$env:TEMP\kitchen\cookbooks", "$env:TEMP
\kitchen\data", "$env:TEMP\kitchen\data_bags", "$env:TEMP\kitchen\encrypted_data
_bag_secret", "$env:TEMP\kitchen\environments", "$env:TEMP\kitchen\roles")
$root_path = "$env:TEMP\kitchen"

Function Delete-AllDirs($dirs) {
$dirs | ForEach-Object {
if (Test-Path ($path = Unresolve-Path $_)) { Remove-Item $path -Recurse -For
ce }
}
}

Function Unresolve-Path($p) {
if ($p -eq $null) { return $null }
else { return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFro
mPSPath($p) }
}

Function Make-RootPath($p) {
$p = Unresolve-Path $p
if (-Not (Test-Path $p)) { New-Item $p -ItemType directory | Out-Null }
}

Delete-AllDirs $dirs
Make-RootPath $root_path
)
Transferring files to
D creating hash for directory $env:TEMP\kitchen
D Populating files
D === All files added.
D creating hash for file $env:TEMP\kitchen
D creating hash for directory $env:TEMP\kitchen
D Populating files
D +++ Adding exemple/README.md
D +++ Adding exemple/metadata.json
D +++ Adding exemple/recipes/default.rb
D +++ Adding exemple/templates/default/server-info.txt.erb
D === All files added.
D creating hash for file $env:TEMP\kitchen
D creating hash for file $env:TEMP\kitchen
D Running check_files.ps1
D @{
D "76cdb2bad9582d23c1f6f4d868218d6c" = @{
D "target" = "$env:TEMP\winrm-upload\tmpzip-76cdb2bad9582d23c1f6f4d8682
18d6c.zip";
D "src_basename" = "cache";
D "dst" = "$env:TEMP\kitchen\cache"
D };
D "4a97fd2422bbd08087c45f41850d7c57" = @{
D "target" = "$env:TEMP\kitchen";
D "src_basename" = "client.rb";
D "dst" = "$env:TEMP\kitchen"
D };
D "f3533ee7ad43299663e75dd2711d5a22" = @{
D "target" = "$env:TEMP\winrm-upload\tmpzip-f3533ee7ad43299663e75dd2711
d5a22.zip";
D "src_basename" = "cookbooks";
D "dst" = "$env:TEMP\kitchen\cookbooks"
D };
D "949b7075bf9490aa8b7f325dee915562" = @{
D "target" = "$env:TEMP\kitchen";
D "src_basename" = "dna.json";
D "dst" = "$env:TEMP\kitchen"
D };
D "49abb94825cb80b9a9cd59e5f76daf4a" = @{
D "target" = "$env:TEMP\kitchen";
D "src_basename" = "validation.pem";
D "dst" = "$env:TEMP\kitchen"
D }
D }
D Parsing CSV Response
D "chk_exists","src_md5","dst_md5","chk_dirty","verifies","target_is_folder
"
"False","f3533ee7ad43299663e75dd2711d5a22",,"True","False","False"
"False","76cdb2bad9582d23c1f6f4d868218d6c",,"True","False","False"
"False","949b7075bf9490aa8b7f325dee915562",,"True","False","True"
"False","49abb94825cb80b9a9cd59e5f76daf4a",,"True","False","True"
"False","4a97fd2422bbd08087c45f41850d7c57",,"True","False","True"

D Uploading C:/Users/A625564/AppData/Local/Temp/tmpzip-20160602-6956-zx4f1l
.zip to encoded tmpfile $env:TEMP\b64-76cdb2bad9582d23c1f6f4d868218d6c.txt
D Finished uploading C:/Users/A625564/AppData/Local/Temp/tmpzip-20160602-69
56-zx4f1l.zip to encoded tmpfile $env:TEMP\b64-76cdb2bad9582d23c1f6f4d868218d6c.
txt (0.028 KB over 1 chunks) in (0m0.04s)
D Uploading C:/Users/A625564/AppData/Local/Temp/default-mwrock-Windows2012R
2-sandbox-20160602-6956-1us5jrn/client.rb to encoded tmpfile $env:TEMP\b64-4a97f
d2422bbd08087c45f41850d7c57.txt
D Finished uploading C:/Users/A625564/AppData/Local/Temp/default-mwrock-Win
dows2012R2-sandbox-20160602-6956-1us5jrn/client.rb to encoded tmpfile $env:TEMP
b64-4a97fd2422bbd08087c45f41850d7c57.txt (1.084 KB over 1 chunks) in (0m0.04s)
D Uploading C:/Users/A625564/AppData/Local/Temp/tmpzip-20160602-6956-spm94d
.zip to encoded tmpfile $env:TEMP\b64-f3533ee7ad43299663e75dd2711d5a22.txt
D Finished uploading C:/Users/A625564/AppData/Local/Temp/tmpzip-20160602-69
56-spm94d.zip to encoded tmpfile $env:TEMP\b64-f3533ee7ad43299663e75dd2711d5a22.
txt (1.492 KB over 1 chunks) in (0m0.04s)
D Uploading C:/Users/A625564/AppData/Local/Temp/default-mwrock-Windows2012R
2-sandbox-20160602-6956-1us5jrn/dna.json to encoded tmpfile $env:TEMP\b64-949b70
75bf9490aa8b7f325dee915562.txt
D Finished uploading C:/Users/A625564/AppData/Local/Temp/default-mwrock-Win
dows2012R2-sandbox-20160602-6956-1us5jrn/dna.json to encoded tmpfile $env:TEMP\b
64-949b7075bf9490aa8b7f325dee915562.txt (0.052 KB over 1 chunks) in (0m0.06s)
D Uploading C:/Users/A625564/AppData/Local/Temp/default-mwrock-Windows2012R
2-sandbox-20160602-6956-1us5jrn/validation.pem to encoded tmpfile $env:TEMP\b64-
49abb94825cb80b9a9cd59e5f76daf4a.txt
D Finished uploading C:/Users/A625564/AppData/Local/Temp/default-mwrock-Win
dows2012R2-sandbox-20160602-6956-1us5jrn/validation.pem to encoded tmpfile $env:
TEMP\b64-49abb94825cb80b9a9cd59e5f76daf4a.txt (2.236 KB over 1 chunks) in (0m0.0
4s)
D Running decode_files.ps1
D @{
D "$env:TEMP\b64-76cdb2bad9582d23c1f6f4d868218d6c.txt" = @{
D "dst" = "$env:TEMP\kitchen\cache";
D "tmpzip" = "$env:TEMP\winrm-upload\tmpzip-76cdb2bad9582d23c1f6f4d8682
18d6c.zip"
D };
D "$env:TEMP\b64-4a97fd2422bbd08087c45f41850d7c57.txt" = @{
D "dst" = "$env:TEMP\kitchen/client.rb"
D };
D "$env:TEMP\b64-f3533ee7ad43299663e75dd2711d5a22.txt" = @{
D "dst" = "$env:TEMP\kitchen\cookbooks";
D "tmpzip" = "$env:TEMP\winrm-upload\tmpzip-f3533ee7ad43299663e75dd2711
d5a22.zip"
D };
D "$env:TEMP\b64-949b7075bf9490aa8b7f325dee915562.txt" = @{
D "dst" = "$env:TEMP\kitchen/dna.json"
D };
D "$env:TEMP\b64-49abb94825cb80b9a9cd59e5f76daf4a.txt" = @{
D "dst" = "$env:TEMP\kitchen/validation.pem"
D }
D }
D Parsing CSV Response
D "src_md5","tmpzip","verifies","tmpfile","dst_md5","dst"
"f3533ee7ad43299663e75dd2711d5a22","C:\Users\vagrant\AppData\Local\Temp\winrm-up
load\tmpzip-f3533ee7ad43299663e75dd2711d5a22.zip","True","C:\Users\vagrant\AppDa
ta\Local\Temp\b64-f3533ee7ad43299663e75dd2711d5a22.txt","f3533ee7ad43299663e75dd
2711d5a22","C:\Users\vagrant\AppData\Local\Temp\kitchen\cookbooks"
"76cdb2bad9582d23c1f6f4d868218d6c","C:\Users\vagrant\AppData\Local\Temp\winrm-up
load\tmpzip-76cdb2bad9582d23c1f6f4d868218d6c.zip","True","C:\Users\vagrant\AppDa
ta\Local\Temp\b64-76cdb2bad9582d23c1f6f4d868218d6c.txt","76cdb2bad9582d23c1f6f4d
868218d6c","C:\Users\vagrant\AppData\Local\Temp\kitchen\cache"
"49abb94825cb80b9a9cd59e5f76daf4a",,"True","C:\Users\vagrant\AppData\Local\Temp
b64-49abb94825cb80b9a9cd59e5f76daf4a.txt","49abb94825cb80b9a9cd59e5f76daf4a","C:
\Users\vagrant\AppData\Local\Temp\kitchen/validation.pem"
"4a97fd2422bbd08087c45f41850d7c57",,"True","C:\Users\vagrant\AppData\Local\Temp
b64-4a97fd2422bbd08087c45f41850d7c57.txt","4a97fd2422bbd08087c45f41850d7c57","C:
\Users\vagrant\AppData\Local\Temp\kitchen/client.rb"
"949b7075bf9490aa8b7f325dee915562",,"True","C:\Users\vagrant\AppData\Local\Temp
b64-949b7075bf9490aa8b7f325dee915562.txt","949b7075bf9490aa8b7f325dee915562","C:
\Users\vagrant\AppData\Local\Temp\kitchen/dna.json"

D Cleaned up src_zip C:/Users/A625564/AppData/Local/Temp/tmpzip-20160602-69
56-zx4f1l.zip
D Cleaned up src_zip C:/Users/A625564/AppData/Local/Temp/tmpzip-20160602-69
56-spm94d.zip
D Uploaded 5 items dirty_check: (0m0.79s) stream_files: (0m0.24s) decode: (
0m1.22s)
D Transfer complete
D [WinRM] negotiate::http://127.0.0.1:55985/wsman<{:user=>"vagrant", :pass=

"vagrant", :elevated_username=>"vagrant", :elevated_password=>"vagrant", :no_ss
l_peer_verification=>true, :disable_sspi=>false, :basic_auth_only=>false}> (
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine")

& $env:systemdrive\opscode\chef\bin\chef-client.bat --local-mode --config $env:T
EMP\kitchen\client.rb --log_level auto --force-formatter --no-color --json-attri
butes $env:TEMP\kitchen\dna.json --chef-zero-port 8889)
$$$$$$ & : The term 'C:\opscode\chef\bin\chef-client.bat' is not recognized
as the
$$$$$$ name of a cmdlet, function, script file, or operable program. Check the
$$$$$$ spelling of the name, or if a path was included, verify that the path is
$$$$$$ correct and try again.
$$$$$$ At line:4 char:3
$$$$$$ + & $env:systemdrive\opscode\chef\bin\chef-client.bat --local-mode --
config
$$$$$$ $env:T ...
$$$$$$ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$$$$$$ + CategoryInfo : ObjectNotFound: (C:\opscode\chef\bin\chef-c
lient
$$$$$$ .bat:String) , CommandNotFoundException
$$$$$$ + FullyQualifiedErrorId : CommandNotFoundException
D Cleaning up local sandbox in C:/Users/A625564/AppData/Local/Temp/default-
mwrock-Windows2012R2-sandbox-20160602-6956-1us5jrn

Converge failed on instance .
Please see .kitchen/logs/default-mwrock-Windows2012R2.log for more detail
s
------Exception-------
Class: Kitchen::ActionFailed
Message: WinRM exited (1) for command: [
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine")

& $env:systemdrive\opscode\chef\bin\chef-client.bat --local-mode --config $env:T
EMP\kitchen\client.rb --log_level auto --force-formatter --no-color --json-attri
butes $env:TEMP\kitchen\dna.json --chef-zero-port 8889]


D Converge failed on instance .
D ------Exception-------
D Class: Kitchen::InstanceFailure
D Message: Converge failed on instance . Ple
ase see .kitchen/logs/default-mwrock-Windows2012R2.log for more details
D ---Nested Exception---
D Class: Kitchen::ActionFailed
D Message: WinRM exited (1) for command: [
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine")

& $env:systemdrive\opscode\chef\bin\chef-client.bat --local-mode --config $env:T
EMP\kitchen\client.rb --log_level auto --force-formatter --no-color --json-attri
butes $env:TEMP\kitchen\dna.json --chef-zero-port 8889]
D ------Backtrace-------
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/provisioner/base.rb:76:in rescue in call' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/provisioner/base.rb:79:in call'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/instance.rb:373:in block in converge_action' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/instance.rb:513:in call'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/instance.rb:513:in synchronize_or_call' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/instance.rb:478:in block in action'
D C:/opscode/chefdk/embedded/lib/ruby/2.1.0/benchmark.rb:279:in measure' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/instance.rb:477:in action'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/instance.rb:369:in converge_action' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/instance.rb:348:in block in transition_to'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/instance.rb:347:in each' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/instance.rb:347:in transition_to'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/instance.rb:138:in converge' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li b/kitchen/command.rb:176:in public_send'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/test-kitchen-1.8.0/li
b/kitchen/command.rb:176:in block (2 levels) in run_action' D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/logging-2.1.0/lib/log ging/diagnostic_context.rb:450:in call'
D C:/opscode/chefdk/embedded/lib/ruby/gems/2.1.0/gems/logging-2.1.0/lib/log
ging/diagnostic_context.rb:450:in `block in create_with_logging_context'
D ----------------------
D [WinRM] closing remote shell 9DB3C3A8-2E1E-4477-AE21-49019088614D on http
://127.0.0.1:55985/wsman
D [WinRM] remote shell 9DB3C3A8-2E1E-4477-AE21-49019088614D closed
PS C:\coookboooks\exemple>

does your box have access to the external internet?

Well i don’t think so because i’m behind a proxy on my host machine and i’m using your box matt (mwrock/windows2012R2) there are two sessions vagrant and administrator, the default password for vagrant is vagrant i used it and it failed to connect.
So, i think that i need to connect to my box first of all and then and then configure the guest machine to connect behind a proxy but what’s the password?

The vagrant account is an admin user and should be the only username/password needed. Sounds like Test-Kitchen is connecting to the box successfully. You just need to configure the kitchen provisioner with your proxy settings. I often refer to https://docs.chef.io/config_yml_kitchen.html for the various config settings in my kitchen.yml. You will notice there the http_proxy and https_proxy settings of the provisioner. Thats what you need to set in your kitchen.yml.

I’ve already configured the proxy in kitchen.yml. It doen’t work though! It doen’t get the chef-client.bat …

If you are setting the proxy config settings, the vagrant box will use those settings when it creates the web client that downloads the chef client. You can validate that the proxy settings are being set on the machine by looking in its $env:temp directory and looking for a file that ends in -long-script.ps1. This is the script that is run and downloads and installs the chef-client. At the top of the script you should see your proxy server settings.

I’d first have a look at that and ensure the settings are correct. Maybe also plug them into the internet settings on the box and see if you can browse the web.

Hello, I’m having similar issues with converge on a Windows system, Looking at the -long-script.ps1 file, the $chef_metadata_url variable is pointing to “https://chef.io…” (I’ve destroyed the machine, working from memory).

We’ve added the chef_metadata_url to the .kitchen.yml file as part of the provisioner: section, pointing to our internal metadata file, which is referring to the client MSI file, and the SHA/MD5 values. This is not pulling over to the -long-script.ps1 file.

If we manually change the value on the VM and execute the script, the client installs and future passes with converge execute as expected.

The function of the converge was working with chefdk 0.9.0, but changed when we upgraded to 0.12.0.

Please advise.

If you want to point to a specific msi url, use the :install_msi_url provisioner setting.

I’ve tried to Google your suggestion, where (which file and where in the file) should I add that setting, can you please provide more details, possibly an example.

Thank you,
CJ

Sure thing. Here is how you would craft your provisioner config to pull the chef-client MSI from a ustom URL:

provisioner:
  name: chef_zero
  install_msi_url: http://my/special/client.msi

Hi matt,

I’m sorry but i couldn’t connect to the box, i entered the password vagrant but it says the password is incorrect.
I can’t check $env:temp in that case to see if the proxy was configured.

What can i do to connect to the box?
Thanks

Hmm thats very strange. The vagrant user password should indeed be vagrant. In fact your kitchen run would not have been able to get as far as it has if those credentials were different since the kitchen-vagrant default credentials are vagrant/vagrant. All I can think of is that here is a casing issue or maybe an issue with your character set.

Tried your suggestion, but still no luck. Is this option supported in 0.12.x or does it require a more recent version, the -long-script.ps1 is still pointing to a chef.io location (http://www.chef.io/chef/metadata?p=windows&m=x86_64&pv=2008r2&v=)

Thank you
CJ

If I recall the 0.12 release of chefdk was the last version of Test-Kitchen that did not use the mixlib-install gem to handle the download and install of the chef client. I believe that predates the introduction of the install_msi_url setting explaining why its not working for you. You might consider trying a later release if thats an option for you.

Indeed that’s strange, it still doesn’t work so i returned to packer and tried to launch it. It builds a vm but i waits for winrm to be available and when i do ls windows2012r2min-virtualbox.box and stop Waiting for WinRM to become available…It tells me that the box was not created.
I’m on windows 7 and i’m using windows 2012-r2 box as in the tutorial.
thanks!

Thank you, really appreciate the time and effort !!

I had to upgrade to 0.13.x to get it to work. Quick question, is there a property that supports the omnibus_metadata_url and is all this documented somewhere ?

Thank you once again !
CJ

There really is no omnibus_metadata_url for windows packages. I think this docs page provides the best documentation on the .kitchen.yml configuration settings, but it has grown somewhat out of date and does not include the reference to the install_msi_url setting. I just submitted a PR to that page here.

Hi matt,
Can you tell me please what’s wrong with packer. It builds a vm but i waits for winrm to be available and when i do ls windows2012r2min-virtualbox.box and stop Waiting for WinRM to become available…It tells me that the box was not created.
I’m on windows 7 and i’m using windows 2012-r2 box as in the tutorial.
thanks!