/cupboard

A tool to provision local environments using the .NET SDK.

Primary LanguageC#MIT LicenseMIT

Cupboard

A framework for provisioning local environments to a desired state, using the .NET SDK.

⚠ Disclaimer:
Currently in preview. Use at own risk.

Introduction

In Cupboard, you define catalogs, manifests, and resources.

  • 🍎 Resources: A resource describes the desired state for some part of a system.
    This might be a file, directory, package, etc.
  • 🌳 Manifests:
    A manifest contains one or many resources.
  • 🌍 Catalogs:
    A catalog contains one or many manifests.

1. Create a console application

Start by creating a new console application targeting .NET5.0.
Add a reference to the Cupboard NuGet package.

> dotnet new console
> dotnet add package Cupboard

2. Create a manifest

Let's start by creating a manifest that defines what should be run.

Note that resources don't do anything when they're declared.
They describe what WILL be done when executed.

public sealed class Chocolatey : Manifest
{
    public override void Execute(ManifestContext context)
    {
        // Download
        context.Resource<Download>("https://chocolatey.org/install.ps1")
            .ToFile("~/install-chocolatey.ps1");

        // Set execution policy
        context.Resource<RegistryKey>("Set execution policy")
            .Path(@"HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell\ExecutionPolicy")
            .Value("Unrestricted", RegistryKeyValueKind.String);

        // Install
        context.Resource<PowerShellScript>("Install Chocolatey")
            .Script("~/install-chocolatey.ps1")
            .Unless("if (Test-Path \"$($env:ProgramData)/chocolatey/choco.exe\") { exit 1 }")
            .After<RegistryKey>("Set execution policy")
            .After<Download>("https://chocolatey.org/install.ps1");

        // Install VSCode via Chocolatey
        context.Resource<ChocolateyPackage>("vscode")
            .Ensure(PackageState.Installed)
            .After<PowerShellScript>("Install Chocolatey");
    }

3. Create a catalog

When we have a Manifest, we need to create a Catalog containing the manifest.
We'll also add a condition that excludes non-Windows environments.

public sealed class MyWindowsComputer : Catalog
{
    public override void Execute(CatalogContext context)
    {
        if (context.Facts["os.platform"] != OSPlatform.Windows) 
        {
            return;
        }

        context.UseManifest<Chocolatey>();
    }
}

4. Create the entry-point

To run the application, we need to add an application entry-point and create a CupboardHost.
We must also explicitly add the catalogs to the CupboardHostBuilder instance.

public static class Program
{
    public static int Main(string[] args)
    {
        return CupboardHost.CreateBuilder()
            .AddCatalog<MyWindowsComputer>()
            .Build()
            .Run(args);
    }
}

5. Run the configuration

Now, open up a terminal in administrator mode and execute the build.

> dotnet run -- --verbosity diagnostic

Cupboard will show you a summary of what will be changed, which you will have to approve.

❯ dotnet run -- --verbosity diagnostic

β”Œβ”€Plan───────────────────────────────────────────────────────────────────────────────┐
β”‚                                                                                    β”‚
β”‚   #  β”‚ Provider                 β”‚ Resource                                         β”‚
β”‚  ────┼──────────────────────────┼────────────────────────────────────────────────  β”‚
β”‚   1  β”‚ RegistryKey              β”‚ Set execution policy                             β”‚
β”‚   2  β”‚ Download                 β”‚ https://chocolatey.org/install.ps1               β”‚
β”‚   3  β”‚ PowerShellScript         β”‚ Install Chocolatey                               β”‚
β”‚   4  β”‚ ChocolateyPackage        β”‚ vscode                                           β”‚
β”‚                                                                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€Breakdown──────────────────────────────────────────────────────────────────────────┐
β”‚                                                                                    β”‚
β”‚  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  β”‚
β”‚  β–  RegistryKey 1   β–  Download 1   β–  PowerShellScript 1   β–  ChocolateyPackage 1     β”‚
β”‚                                                                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

WARNING: This will change the state of the current machine.
Are you sure you want to continue? [y/n] (n): _

Building

We're using Cake as a dotnet tool for building. So make sure that you've restored Cake by running the following in the repository root:

> dotnet tool restore

After that, running the build is as easy as writing:

> dotnet cake

Copyright

Copyright (c) 2021 Patrik Svensson