diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..726aa9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.terraform* +.tfvars +terraform.tfstate* \ No newline at end of file diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..d95517c --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,32 @@ +version: '3' + +tasks: + install: + dir: scripts/dependencies + cmds: + - chmod +x terraform.sh && ./terraform.sh + silent: true + plan: + dir: terraform + cmds: + - terraform plan -var-file=".tfvars" + silent: true + apply: + dir: terraform + cmds: + - terraform apply -var-file=".tfvars" + silent: true + destroy: + dir: terraform + cmds: + - terraform destroy -var-file=".tfvars" + silent: true + init: + dir: terraform + cmds: + - terraform init + silent: true + run: + cmds: + - go run . + silent: true \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e97df3e --- /dev/null +++ b/go.mod @@ -0,0 +1,25 @@ +module github.com/utibeabasi6/ebs-playground + +go 1.21.5 + +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gofiber/fiber/v2 v2.52.1 // indirect + github.com/gofiber/template v1.8.3 // indirect + github.com/gofiber/template/html/v2 v2.1.1 // indirect + github.com/gofiber/utils v1.1.0 // indirect + github.com/google/uuid v1.5.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + golang.org/x/sys v0.15.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3d26ca4 --- /dev/null +++ b/go.sum @@ -0,0 +1,42 @@ +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gofiber/fiber/v2 v2.52.1 h1:1RoU2NS+b98o1L77sdl5mboGPiW+0Ypsi5oLmcYlgHI= +github.com/gofiber/fiber/v2 v2.52.1/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc= +github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= +github.com/gofiber/template/html/v2 v2.1.1 h1:QEy3O3EBkvwDthy5bXVGUseOyO6ldJoiDxlF4+MJiV8= +github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQbNa4x1CVNFW0wju0= +github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= +github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/main.go b/main.go new file mode 100644 index 0000000..b43969d --- /dev/null +++ b/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "log" + + human "github.com/dustin/go-humanize" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/template/html/v2" + "github.com/shirou/gopsutil/disk" +) + +func fetchDiskSpace() { + formatter := "%-14s %7s %7s %7s %4s %s\n" + fmt.Printf(formatter, "Filesystem", "Size", "Used", "Avail", "Use%", "Mounted on") + + parts, _ := disk.Partitions(false) + for _, p := range parts { + device := p.Mountpoint + s, _ := disk.Usage(device) + + if s.Total == 0 { + continue + } + + percent := fmt.Sprintf("%2.f%%", s.UsedPercent) + + fmt.Printf(formatter, + s.Fstype, + human.Bytes(s.Total), + human.Bytes(s.Used), + human.Bytes(s.Free), + percent, + p.Mountpoint, + ) + } + +} + +func main() { + engine := html.New("./templates", ".html") + app := fiber.New(fiber.Config{ + Views: engine, + }) + + app.Get("/", func(c *fiber.Ctx) error { + fetchDiskSpace() + + // Render index template + return c.Render("index", fiber.Map{ + "Title": "Hello, World!", + }) + }) + + log.Println("Starting server on port 3000") + log.Fatal(app.Listen(":3000")) +} diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100644 index 0000000..a11557b --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Create the volume group +vgcreate ebs-pg-vg /dev/xvdf /dev/xvdg /dev/xvdh + +# Create logical volumes +sudo lvcreate -l 50%FREE -n lv1 ebs-pg-vg +sudo lvcreate -l 100%FREE -n lv2 ebs-pg-vg + +# Create filesystems on logical volumes +sudo mkfs.ext4 /dev/ebs-pg-vg/lv1 +sudo mkfs.ext4 /dev/ebs-pg-vg/lv2 + +# Create mount directory +mkdir -p /home/ubuntu/mounts/lv1 +mkdir -p /home/ubuntu/mounts/lv2 + +# Mount filesystems +sudo su -c "echo '$(sudo blkid /dev/ebs-pg-vg/lv1 | awk '{print $2}') /home/ubuntu/mounts/lv1 ext4 defaults 0 0' >> /etc/fstab" +sudo su -c "echo '$(sudo blkid /dev/ebs-pg-vg/lv2 | awk '{print $2}') /home/ubuntu/mounts/lv2 ext4 defaults 0 0' >> /etc/fstab" +sudo mount -a diff --git a/scripts/dependencies/terraform.sh b/scripts/dependencies/terraform.sh new file mode 100755 index 0000000..c4b6f6a --- /dev/null +++ b/scripts/dependencies/terraform.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Install terraform +sudo apt-get update && sudo apt-get install -y gnupg software-properties-common +wget -O- https://apt.releases.hashicorp.com/gpg | \ +gpg --dearmor | \ +sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null +gpg --no-default-keyring \ +--keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \ +--fingerprint +echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \ +https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \ +sudo tee /etc/apt/sources.list.d/hashicorp.list +sudo apt update +sudo apt-get install terraform \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..266a536 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,11 @@ + + + + + + EBS Playground + + +

Hello World

+ + \ No newline at end of file diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..a637a06 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,67 @@ +locals { + device_letter_list = ["f", "g", "h"] +} + +data "aws_vpc" "main" { + default = true + } + +resource "aws_key_pair" "main" { + key_name = var.instance_name + public_key = var.instance_public_key +} + +resource "aws_instance" "main" { + ami = var.instance_ami + instance_type = var.instance_type + availability_zone = var.ebs_availability_zone + key_name = aws_key_pair.main.key_name + security_groups = [ aws_security_group.main.name ] + user_data_base64 = filebase64("../scripts/bootstrap.sh") + + tags = { + Name = var.instance_name + } +} + +resource "aws_ebs_volume" "main" { + count = var.ebs_volume_count + availability_zone = var.ebs_availability_zone + size = var.ebs_volume_size + + tags = { + Name = "${var.instance_name}-volume-${count.index}" + } +} + +resource "aws_volume_attachment" "ebs_attatchment" { + count = var.ebs_volume_count + device_name = "/dev/sd${local.device_letter_list[count.index]}" + volume_id = aws_ebs_volume.main[count.index].id + instance_id = aws_instance.main.id +} + + +resource "aws_security_group" "main" { + name = "main" + description = "Allow traffic" + vpc_id = data.aws_vpc.main.id + + tags = { + Name = "main" + } +} + +resource "aws_vpc_security_group_ingress_rule" "allow_ssh" { + security_group_id = aws_security_group.main.id + cidr_ipv4 = "0.0.0.0/0" + from_port = 22 + ip_protocol = "tcp" + to_port = 22 +} + +resource "aws_vpc_security_group_egress_rule" "allow_all" { + security_group_id = aws_security_group.main.id + cidr_ipv4 = "0.0.0.0/0" + ip_protocol = -1 +} \ No newline at end of file diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..f163584 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,4 @@ +output "instance_ip" { + description = "The IP address of the instance" + value = aws_instance.main.public_ip +} \ No newline at end of file diff --git a/terraform/terraform.tf b/terraform/terraform.tf new file mode 100644 index 0000000..49e3cbf --- /dev/null +++ b/terraform/terraform.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +# Configure the AWS Provider +provider "aws" { + region = "us-east-1" +} + +provider "random" {} + diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..68a92f3 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,40 @@ +variable "instance_name" { + type = string + description = "The name of the AWS instance" + default = "ebs-playground" +} + +variable "instance_ami" { + type = string + description = "The AMI id for the AWS instance" + default = "ami-07d9b9ddc6cd8dd30" +} + +variable "instance_public_key" { + type = string + description = "The public key for SSH" +} + +variable "instance_type" { + type = string + description = "The AWS instance type" + default = "t2.micro" +} + +variable "ebs_volume_count" { + type = number + description = "Number of ebs volumes to create" + default = 3 +} + +variable "ebs_volume_size" { + type = number + description = "Size (in GB) of each EBS volumes" + default = 10 +} + +variable "ebs_availability_zone" { + type = string + description = "Availability zone to deploy the EBS volumes in" + default = "us-east-1a" +} \ No newline at end of file