Skip to content

Commit

Permalink
Merge pull request #4 from mhedgpeth/feature/inspec-added
Browse files Browse the repository at this point in the history
Added inspec as a product cafe manages
  • Loading branch information
mhedgpeth authored Jan 22, 2017
2 parents b859a01 + 146c83f commit d355cd5
Show file tree
Hide file tree
Showing 59 changed files with 799 additions and 475 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,27 @@ Cafe is lightweight. To run the service it takes 17.8MB of memory and no CPU. Th

# Walkthrough

After installation, let's work on getting chef bootstrapped on the machine. The first step is to download the [Chef Client](https://docs.chef.io/ctl_chef_client.html):
After installation, let's work on getting chef bootstrapped on the machine.

The first step is to download and install [inspec](http://inspec.io/):

```
cafe inspec download 1.7.1
```

Once the inspec installer is downloaded, let's install it:

```
cafe inspec install 1.7.1
```

Next we will do the same with the [Chef Client](https://docs.chef.io/ctl_chef_client.html):

```
cafe chef download 12.16.42
```

Once the Chef Client is downloaded, let's install it:
And then install it:

```
cafe chef install 12.16.42
Expand Down
92 changes: 62 additions & 30 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var target = Argument("target", "FullBuild");
var configuration = Argument("configuration", "Debug");
var buildNumber = Argument("buildNumber", "0");

var version = "0.3.1." + buildNumber;
var version = "0.4.0." + buildNumber;

var cafeDirectory = Directory("./src/cafe");
var cafeProject = cafeDirectory + File("project.json");
Expand Down Expand Up @@ -135,27 +135,19 @@ Task("ShowChefRunHelp")
RunCafe("chef run -h");
});


Task("ShowChefVersion")
Task("ShowChefStatus")
.Does(() => {
RunCafe("chef version");
RunCafe("chef status");
});


Task("ShowStatus")
Task("ShowJobStatus")
.Does(() => {
var processSettings = new ProcessSettings() { Arguments = "status" }.UseWorkingDirectory(cafeWindowsPublishDirectory);
Information("Running cafe.exe from {0}", cafeWindowsPublishDirectory);
var exitCode = StartProcess(cafeWindowsPublishDirectory + File("cafe.exe"), processSettings);
Information("Exit code: {0}", exitCode);
});
RunCafe("job status");
});

Task("RunChef")
.Does(() => {
var processSettings = new ProcessSettings() { Arguments = "chef run" }.UseWorkingDirectory(cafeWindowsPublishDirectory);
Information("Running cafe.exe from {0}", cafeWindowsPublishDirectory);
var exitCode = StartProcess(cafeWindowsPublishDirectory + File("cafe.exe"), processSettings);
Information("Exit code: {0}", exitCode);
RunCafe("chef run");
});


Expand All @@ -164,32 +156,62 @@ Task("RunServer")
RunCafe("server");
});

var oldInspecVersion = "1.6.0";
var newInspecVersion = "1.7.1";
var oldChefVersion = "12.16.42";
var newChefVersion = "12.17.44";

Task("InspecDownloadOldVersion")
.Does(() =>
{
RunCafe("inspec download {0}", oldInspecVersion);
});

Task("InspecInstallOldVersion")
.Does(() =>
{
RunCafe("inspec install {0}", oldInspecVersion);
});


Task("InspecDownloadNewVersion")
.Does(() =>
{
RunCafe("inspec download {0}", newInspecVersion);
});

Task("InspecInstallNewVersion")
.Does(() =>
{
RunCafe("inspec install {0}", newInspecVersion);
});

var oldVersion = "12.16.42";

Task("DownloadOldVersion")

Task("ChefDownloadOldVersion")
.Does(() =>
{
RunCafe("chef download {0}", oldVersion);
RunCafe("chef download {0}", oldChefVersion);
});

Task("InstallOldVersion")
Task("ChefInstallOldVersion")
.Does(() =>
{
RunCafe("chef install {0}", oldVersion);
RunCafe("chef install {0}", oldChefVersion);
});

var newVersion = "12.17.44";

Task("DownloadNewVersion")
Task("ChefDownloadNewVersion")
.Does(() =>
{
RunCafe("chef download {0}", newVersion);
RunCafe("chef download {0}", newChefVersion);
});

Task("InstallNewVersion")
Task("ChefInstallNewVersion")
.Does(() =>
{
RunCafe("chef install {0}", newVersion);
RunCafe("chef install {0}", newChefVersion);
});


Expand Down Expand Up @@ -230,6 +252,12 @@ Task("StopService")
});


Task("StartService")
.Does(() =>
{
RunCafe(@"service start");
});

public void RunCafe(string argument, params string[] formatParameters)
{
var arguments = string.Format(argument, formatParameters);
Expand All @@ -245,13 +273,17 @@ Task("AcceptanceTest")
.IsDependentOn("ShowChefHelp")
.IsDependentOn("ShowChefRunHelp")
.IsDependentOn("RegisterService")
.IsDependentOn("DownloadOldVersion")
.IsDependentOn("InstallOldVersion")
.IsDependentOn("InspecDownloadOldVersion")
.IsDependentOn("InspecInstallOldVersion")
.IsDependentOn("ChefDownloadOldVersion")
.IsDependentOn("ChefInstallOldVersion")
.IsDependentOn("BootstrapPolicy")
.IsDependentOn("ShowStatus")
.IsDependentOn("ShowChefVersion")
.IsDependentOn("DownloadNewVersion")
.IsDependentOn("InstallNewVersion")
.IsDependentOn("ShowChefStatus")
.IsDependentOn("ShowJobStatus")
.IsDependentOn("InspecDownloadNewVersion")
.IsDependentOn("InspecInstallNewVersion")
.IsDependentOn("ChefDownloadNewVersion")
.IsDependentOn("ChefInstallNewVersion")
.IsDependentOn("RunChef")
.IsDependentOn("PauseChef")
.IsDependentOn("ResumeChef")
Expand Down
23 changes: 15 additions & 8 deletions docs/demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,24 @@ Let's get it installed:
- Run `cafe init` and reboot to add to PATH variable
- Run `cafe service register` which adds cafe to services
- Run `cafe service start` which starts the Server
- Run `cafe status` to see output
- Run `cafe job status` to see output
- View `http://localhost:59320/api/scheduler/status` - it's the same thing

### Control your node remotely
* Won't demonstrate, but talk about:
- update `client.json` on another machine to point at your node over port `59320`

### Install inspec on the node
- Run `cafe inspec status` and notice it's not installed
- Run `cafe inspec download 1.7.1` - places it in the staging folder (this could be done by a chef cookbook as well)
- Run `cafe chef install 1.7.1`
- Run `cafe inspec status`, it's installed, show add/remove programs

### Install chef-client on the node
- Run `cafe chef version` and notice that it is not installed
- Run `cafe chef download 12.16.42` - places it in the staging folder (this could be done by a chef cookbook as well)
- Run `cafe chef status` and notice that it is not installed
- Run `cafe chef download 12.16.42`
- Run `cafe chef install 12.16.42`
- Run `cafe chef version` and notice that it is installed, show add/remove programs
- Run `cafe chef status` and notice that it is installed, show add/remove programs

### Bootstrap the node

Expand All @@ -47,24 +53,25 @@ We want to operate chef with a windows mindset for easier adoption:
* Chef logging to its own file, rolled
* NLog controlling the level, pattern, etc.
* Rest of server that is consumable by a log4X log viewer, like Log4View
* Run `cafe status` and notice that the runs are in the history
* Run `cafe job all` and notice that the runs are in the history
* Run `cafe job [guid]` and get detailed information on a particular job

## Scheduling

* Schedule Chef to run every 30 seconds, defined in `server.json`
* Run `cafe service stop`
* Run `cafe service start`
* Easily view the schedule through the `cafe status` command
* Easily view the schedule through the `cafe job all` command
* Everything scheduled, including the ad-hoc things, are run **serially**. That means no conflicts!
* Keep running `cafe status` and notice what's happening. View the logs for a deeper view.
* Keep running `cafe job all` and notice what's happening. View the logs for a deeper view.

## Pausing

People are going to pause Chef. Why not give them an easy way to do it so you can track it?

* Pause chef with `cafe chef pause`
* Run `cafe chef run`
* Run `cafe status`. Notice that the task is queued but not run yet since it is paused.
* Run `cafe job all`. Notice that the task is queued but not run yet since it is paused.
* Go to `http://localhost:59320` and see that it is paused
* Run `cafe chef resume` and see that chef starts running

Expand Down
35 changes: 21 additions & 14 deletions src/cafe/Chef/ChefDownloader.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System;
using System.IO;
using cafe.LocalSystem;
using cafe.Server.Scheduling;
using cafe.Shared;
using NLog;

namespace cafe.Chef
{
public interface IDownloader
{
string Product { get; }
Result Download(string version, IMessagePresenter messagePresenter);
}

Expand All @@ -20,49 +20,56 @@ public class Downloader : IDownloader

private readonly IFileDownloader _fileDownloader;
private readonly IFileSystem _fileSystem;
private readonly string _product;
private readonly string _prefix;
private readonly string _target;

public Downloader(IFileDownloader fileDownloader, IFileSystem fileSystem)
public Downloader(IFileDownloader fileDownloader, IFileSystem fileSystem, string product, string prefix, string target)
{
_fileDownloader = fileDownloader;
_fileSystem = fileSystem;
_product = product;
_prefix = prefix;
_target = target;
}

public string Product => _product;

public Result Download(string version, IMessagePresenter messagePresenter)
{
messagePresenter.ShowMessage("Ensuring staging directory exists");
_fileSystem.EnsureDirectoryExists(StagingDirectory);
var destination = FullPathToStagedInstaller(version);
var destination = FullPathToStagedInstaller(version, _prefix);
if (_fileSystem.FileExists(destination))
{
messagePresenter.ShowMessage($"Download msi already exists, so not downloading again");
return Result.Successful();
}
var downloadLink = DownloadUriFor(version);
messagePresenter.ShowMessage($"Downloading Chef {version} from {downloadLink}");
var file = FilenameFor(version);
var downloadLink = DownloadUriFor(version, _product, _prefix, _target);
messagePresenter.ShowMessage($"Downloading {_product} {version} from {downloadLink}");
var result = _fileDownloader.Download(downloadLink, destination);
messagePresenter.ShowMessage($"Finished downloading Chef {version} from {downloadLink}");
messagePresenter.ShowMessage($"Finished downloading {_product} {version} from {downloadLink}");
Logger.Info(result);
return result.TranslateIfFailed($"Installer for Chef {version} could not be found at {downloadLink}");
return result.TranslateIfFailed($"Installer for {_product} {version} could not be found at {downloadLink}");
}


public static Uri DownloadUriFor(string version)
public static Uri DownloadUriFor(string version, string product, string prefix, string target)
{
// TODO: sanitize data so it can't be injected here
return new Uri(
$"https://packages.chef.io/files/stable/chef/{version}/windows/2012r2/{FilenameFor(version)}");
$"https://packages.chef.io/files/stable/{product}/{version}/windows/{target}/{FilenameFor(version, prefix)}");
}

public static string FilenameFor(string version)
public static string FilenameFor(string version, string prefix)
{
// TODO: sanitize data so it can't be injected here
return $@"chef-client-{version}-1-x64.msi";
return $@"{prefix}-{version}-1-x64.msi";
}

public static string FullPathToStagedInstaller(string version)
public static string FullPathToStagedInstaller(string version, string prefix)
{
return Path.Combine(StagingDirectory, FilenameFor(version));
return Path.Combine(StagingDirectory, FilenameFor(version, prefix));
}
}
}
9 changes: 7 additions & 2 deletions src/cafe/Chef/ChefInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,39 @@ public class ProductInstaller : IProductInstaller

private readonly IFileSystem _fileSystem;
private readonly IFileSystemCommands _commands;
private readonly string _prefix;
private readonly ProcessExecutor _processExecutor;

public ProductInstaller(IFileSystem fileSystem, ProcessExecutor processExecutor, IFileSystemCommands commands)
public ProductInstaller(IFileSystem fileSystem, ProcessExecutor processExecutor, IFileSystemCommands commands, string prefix)
{
_fileSystem = fileSystem;
_processExecutor = processExecutor;
_commands = commands;
_prefix = prefix;
}

public Result Uninstall(string productCode)
{
Logger.Debug($"Uninstalling product {productCode}");
var msiexec = FindFullPathToMsiExec();
return _processExecutor.ExecuteAndWaitForExit(msiexec, $"/qn /x {productCode}", LogInformation, LogError);
}

public Result Install(string version)
{
var fullPathToStagedInstaller = Downloader.FullPathToStagedInstaller(version);
var fullPathToStagedInstaller = Downloader.FullPathToStagedInstaller(version, _prefix);
if (!_commands.FileExists(fullPathToStagedInstaller))
{
Logger.Warn(
$"No file for version {version} was staged at {fullPathToStagedInstaller}. Either download it or stage it another way");
var failure = Result.Failure("There was no staged installer. Download the file first.");
return failure;
}
Logger.Debug($"Installing installer {fullPathToStagedInstaller}");
var msiexec = FindFullPathToMsiExec();
var result = _processExecutor.ExecuteAndWaitForExit(msiexec, $"/qn /L*V \"logs/installation.log\" /i \"{fullPathToStagedInstaller}\"",
LogInformation, LogError);
Logger.Debug($"Result of installing {fullPathToStagedInstaller} is {result}");
return result;
}

Expand Down
Loading

0 comments on commit d355cd5

Please sign in to comment.