Skip to content

Instantly share code, notes, and snippets.

@ninjarobot
Created November 5, 2021 01:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ninjarobot/b027de0f17271a810786132b23405d76 to your computer and use it in GitHub Desktop.
Save ninjarobot/b027de0f17271a810786132b23405d76 to your computer and use it in GitHub Desktop.
Builds autoinstall ISO for Ubuntu F# dev environment
#r "nuget: FsCloudInit"
#r "nuget: DiscUtils.Containers"
open System
open System.IO
open FsCloudInit
open FsCloudInit.Builders
open DiscUtils
open YamlDotNet.Serialization
let bootstrapScript = """
#!/bin/bash
set -eux
cd /home/ubuntu
python3 -m venv venvs/ansible
source venvs/ansible/bin/activate
pip install ansible
rm -rf autodevenv # in case we need to rerun this
git clone https://github.com/ninjarobot/autodevenv.git
cd autodevenv
git checkout 2c6749ddddf0055dc518ec3d0793dc510294fae8
# Need to become_user in playbooks since cloud-init runs as root.
sed -i '29 i \ become: yes' playbooks/vscode.yml
sed -i '30 i \ become_user: ubuntu' playbooks/vscode.yml
sed -i '36 i \ become: yes' playbooks/vscode.yml
sed -i '37 i \ become_user: ubuntu' playbooks/vscode.yml
sed -i '40 i \ become: yes' playbooks/vscode.yml
sed -i '41 i \ become_user: ubuntu' playbooks/vscode.yml
echo "localhost" > hosts
ansible-playbook -i hosts playbooks/dotnet_preview.yml -c local
ansible-playbook -i hosts playbooks/vscode.yml -c local
"""
/// A little example cloud-config for bootstrapping after unattended install.
let cloudConfig =
cloudConfig {
package_update true
add_packages [
"python3.8-venv"
"git"
"ubuntu-desktop"
]
write_files [
writeFile {
path "/home/ubuntu/bootstrap-dev-env.sh"
content bootstrapScript
permissions "755"
owner "ubuntu"
}
]
run_commands [
"chown -R ubuntu:ubuntu /home/ubuntu".Split null
[ "bash"; "/home/ubuntu/bootstrap-dev-env.sh" ]
[ "reboot" ]
]
}
/// Build the unattended installation with embedded cloud-config - password is 'fsharp'
let autoinstall (config:CloudConfig) =
let homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
[
"autoinstall",
[
"version", box 1
"identity", [
"username", box "ubuntu"
"password", box "$6$dev$Aq8omSFQXCKU9lgpnejGu7UFx9jw5IG4MdxxzoC3/YU86ubxvSg5H0m8TUgNvmHzkektVy/ubW536s.opkuqz/"
"hostname", box "fsharpvm"
] |> dict |> box
"ssh", [
"authorized-keys", box [| (File.ReadAllText(Path.Combine (homeDir, ".ssh/id_rsa.pub"))) |]
"install-server", box true
] |> dict |> box
"user-data", box config.ConfigModel
] |> dict
] |> dict
/// Serialize to Ubuntu's cloud-config YAML
let writeAutoinstall (config:CloudConfig) =
let serializer =
SerializerBuilder()
.WithNamingConvention(YamlDotNet.Serialization.NamingConventions.UnderscoredNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults)
.Build()
System.String.Concat ("#cloud-config", System.Environment.NewLine, serializer.Serialize (autoinstall config))
// Output the autoinstall just for debugging purposes.
writeAutoinstall cloudConfig |> System.Console.WriteLine
// Generate an ISO to attach to the VM for unattended installation.
Containers.SetupHelper.SetupContainers()
let iso = Iso9660.CDBuilder(VolumeIdentifier="CIDATA")
iso.AddFile("user-data", System.Text.Encoding.UTF8.GetBytes (writeAutoinstall cloudConfig))
iso.AddFile("meta-data", [||])
iso.Build("cloudinit.iso")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment