Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: (IAC-1066) Add Hadolint, ShellCheck TFLint Checks, and Ansible Lint via GitHub Actions #78

Merged
merged 30 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
75baa0f
initial linter files, untested
jarpat Jun 16, 2023
424f81b
add copy statement for the lint config
jarpat Jun 16, 2023
9f3d978
add install lint
jarpat Jun 16, 2023
c28cb0d
try setting collections path
jarpat Jun 16, 2023
c1cee5e
ansible-lint update
jarpat Jun 16, 2023
989ae69
ansible-lint update
jarpat Jun 16, 2023
4390898
address Hadolint warnings
jarpat Jun 16, 2023
53f7d54
resolve additional Hadolint warnings
jarpat Jun 16, 2023
8aa4eb8
resolve ShellCheck warnings
jarpat Jun 16, 2023
435ab21
address TFLint warnings
jarpat Jun 16, 2023
612ccdb
terraform fmt
jarpat Jun 16, 2023
3984f81
workflow file doc
jarpat Jun 16, 2023
fbbd8f3
initial set of ansible-lint fixes
jarpat Jun 16, 2023
399d4d0
resolve key-order issues
jarpat Jun 16, 2023
8a4b062
block spacing
jarpat Jun 16, 2023
afe6411
clear trailing spaces
jarpat Jun 19, 2023
a365a68
give plays names
jarpat Jun 19, 2023
6ef28c6
jinja formatting
jarpat Jun 19, 2023
efe6cb7
spacing and task name cap
jarpat Jun 19, 2023
c3a368b
linting config update
jarpat Jun 19, 2023
0f3f0c0
linting config update
jarpat Jun 19, 2023
e100f89
add file exclusion
jarpat Jun 19, 2023
0183b17
update config and workflow
jarpat Jun 19, 2023
95e2fe6
remove unused var
jarpat Jun 19, 2023
3f2d8a0
revert some shellcheck changes around array reading
jarpat Jun 19, 2023
89243ce
shellcheckrc changes
jarpat Jun 19, 2023
7b19a37
get sshpass deps
jarpat Jun 19, 2023
e6e2398
add newline
jarpat Jun 20, 2023
89b2848
move yaml doc separator down
jarpat Jun 20, 2023
676d4d6
update task name after review
jarpat Jul 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .github/workflows/linter-analysis.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Linter Analysis
on:
push:
branches: [ '*' ] # '*' will cause the workflow to run on all commits to all branches.

jobs:
# Hadolint: Job-1
Hadolint:
name: Hadolint
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3

- name: Run Hadolint Action
uses: jbergstroem/[email protected]
with:
dockerfile: ./Dockerfile
config_file: linting-configs/.hadolint.yaml
error_level: 1 # Fail CI based on hadolint output (-1: never, 0: error, 1: warning, 2: info)

# ShellCheck: Job-2
ShellCheck:
name: ShellCheck
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3

# .shellcheckrc is read from the current dir
- name: Copy Config to Parent Level Directory
run: cp $(pwd)/linting-configs/.shellcheckrc .

- name: Run ShellCheck Action
uses: ludeeus/action-shellcheck@master
with:
severity: error

# TFLint: Job-3
TFLint:
name: TFLint
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3

- name: Cache Plugin Directory
uses: actions/cache@v3
with:
path: ~/.tflint.d/plugins
key: ubuntu-latest-tflint-${{ hashFiles('.tflint.hcl') }}

- name: Setup TFLint
uses: terraform-linters/[email protected]
with:
tflint_version: latest
github_token: ${{ secrets.LINTER_TOKEN }}

- name: Initializing viya4-iac-k8s
run: terraform init

- name: Initializing TFLint
run: TFLINT_LOG=info tflint --init -c "$(pwd)/linting-configs/.tflint.hcl"

- name: Run TFLint Action
run: TFLINT_LOG=info tflint -c "$(pwd)/linting-configs/.tflint.hcl" --recursive

# ansible-lint: Job-4
Ansible-Lint:
name: ansible-lint
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3

# The latest ansible/ansible-lint-action removed the
# ability to specify configs from other dirs
- name: Copy Config to Parent Level Directory
run: cp $(pwd)/linting-configs/.ansible-lint .

# ansible-lint does not seem to recognize the .yaml
# extension for the requirements file and it is not
# configurable
- name: Updates requirements extension
run: cp $(pwd)/requirements.yaml requirements.yml

- name: Install requirements.yaml
run: ansible-galaxy install -r ./requirements.yaml

- name: Run ansible-lint Action
uses: ansible/[email protected]
env:
ANSIBLE_ROLES_PATH: "./roles"
11 changes: 6 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Base layer
FROM ubuntu:22.04 as baseline
RUN apt-get update && apt-get upgrade -y \
&& apt-get install -y python3 python3-dev python3-pip curl unzip gnupg \
RUN apt-get update && apt-get upgrade -y --no-install-recommends \
&& apt-get install -y python3 python3-dev python3-pip curl unzip gnupg --no-install-recommends \
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 1 \
&& update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
Expand All @@ -14,13 +14,14 @@ ARG TERRAFORM_VERSION=1.4.5-*

WORKDIR /build

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
thpang marked this conversation as resolved.
Show resolved Hide resolved
RUN curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - \
&& echo "deb [arch=amd64] https://apt.releases.hashicorp.com focal main" > /etc/apt/sources.list.d/tf.list \
&& apt-get update \
&& curl -sLO https://storage.googleapis.com/kubernetes-release/release/v{$KUBECTL_VERSION}/bin/linux/amd64/kubectl && chmod 755 ./kubectl \
&& curl -sLO https://storage.googleapis.com/kubernetes-release/release/v$KUBECTL_VERSION/bin/linux/amd64/kubectl && chmod 755 ./kubectl \
thpang marked this conversation as resolved.
Show resolved Hide resolved
&& curl -ksLO https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 && chmod 755 get-helm-3 \
&& ./get-helm-3 --version v$HELM_VERSION --no-sudo \
&& apt-get install -y terraform=$TERRAFORM_VERSION \
&& apt-get install -y terraform=$TERRAFORM_VERSION --no-install-recommends \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# Installation steps
Expand All @@ -38,7 +39,7 @@ COPY . /viya4-iac-k8s/

ENV HOME=/viya4-iac-k8s

RUN pip install -r ./requirements.txt \
RUN pip install -r ./requirements.txt --no-cache-dir \
&& ansible-galaxy install -r ./requirements.yaml \
&& chmod 755 /viya4-iac-k8s/docker-entrypoint.sh /viya4-iac-k8s/oss-k8s.sh \
&& terraform init \
Expand Down
1 change: 0 additions & 1 deletion docs/CONFIG-VARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ Terraform input variables can be set in the following ways:
| Name | Description | Type | Default | Notes |
| :--- | :--- | :--- | :--- | :--- |
| vsphere_server | Name of the vSphere server | string | | |
| vsphere_cluster | Name of the vSphere cluster | string | | |
| vsphere_datacenter | Name of the vSphere data center | string | | |
| vsphere_datastore | Name of the vSphere data store to use for the VMs | string | | |
| vsphere_resource_pool | Name of the vSphere resource pool to use for the VMs | string | | |
Expand Down
2 changes: 0 additions & 2 deletions docs/REQUIREMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ In order to leverage vSphere or vCenter, the following items are required for us

| vSphere Item | Description |
| --- | :--- |
|vsphere_cluster | Name of the vSphere cluster |
|vsphere_datacenter | Name of the vSphere data center |
|vsphere_datastore | Name of the vSphere data store to use for the VMs |
|vsphere_resource_pool | Name of the vSphere resource pool to use for the VMs |
Expand Down Expand Up @@ -193,7 +192,6 @@ gateway = "10.18.0.1" # Gateway for servers
netmask = "16" # Netmask providing network access to your gateway

# vSphere
vsphere_cluster = "" # Name of the vSphere cluster
vsphere_datacenter = "" # Name of the vSphere data center
vsphere_datastore = "" # Name of the vSphere data store to use for the VMs
vsphere_resource_pool = "" # Name of the vSphere resource pool to use for the VMs
Expand Down
6 changes: 3 additions & 3 deletions examples/bare-metal/sample-ansible-vars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ kubernetes_service_subnet : ""
kubernetes_pod_subnet : ""

# Kubernetes - VIP : https://kube-vip.io
#
#
# Useful links:
#
# VIP IP : https://kube-vip.io/docs/installation/static/
Expand Down Expand Up @@ -72,7 +72,7 @@ kubernetes_loadbalancer : "" # Load Balancer accepted values [kube_vip,metallb]
# - "192.168.10.0/24"
# - "192.168.9.1-192.168.9.5"
#
# NOTE: If you are assigning a static IP using the loadBalancerIP value in your
# NOTE: If you are assigning a static IP using the loadBalancerIP value in your
# load balancer controller when using `metallb` that IP must fall within the
# address range you provide below. If you are using `kube_vip` you do not
# have this limitation.
Expand Down Expand Up @@ -105,7 +105,7 @@ control_plane_ssh_key_name : "cp_ssh"
# NOTE: There are no quotes around the label and taint elements
# These are literal converted to strings when applying
# into the cluster
#
#

## Labels
node_labels:
Expand Down
1 change: 0 additions & 1 deletion examples/vsphere/sample-terraform-dhcp.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ netmask = "" # Network interface netmask

# vSphere
vsphere_server = "" # Name of the vSphere server
vsphere_cluster = "" # Name of the vSphere cluster
vsphere_datacenter = "" # Name of the vSphere data center
vsphere_datastore = "" # Name of the vSphere data store to use for the VMs
vsphere_resource_pool = "" # Name of the vSphere resource pool to use for the VMs
Expand Down
1 change: 0 additions & 1 deletion examples/vsphere/sample-terraform-minimal.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ netmask = "" # Network interface netmask

# vSphere
vsphere_server = "" # Name of the vSphere server
vsphere_cluster = "" # Name of the vSphere cluster
vsphere_datacenter = "" # Name of the vSphere data center
vsphere_datastore = "" # Name of the vSphere data store to use for the VMs
vsphere_resource_pool = "" # Name of the vSphere resource pool to use for the VMs
Expand Down
1 change: 0 additions & 1 deletion examples/vsphere/sample-terraform-static-ips.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ netmask = "" # Network interface netmask

# vSphere
vsphere_server = "" # Name of the vSphere server
vsphere_cluster = "" # Name of the vSphere cluster
vsphere_datacenter = "" # Name of the vSphere data center
vsphere_datastore = "" # Name of the vSphere data store to use for the VMs
vsphere_resource_pool = "" # Name of the vSphere resource pool to use for the VMs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ netmask = "" # Network interface netmask

# vSphere
vsphere_server = "" # Name of the vSphere server
vsphere_cluster = "" # Name of the vSphere cluster
vsphere_datacenter = "" # Name of the vSphere data center
vsphere_datastore = "" # Name of the vSphere data store to use for the VMs
vsphere_resource_pool = "" # Name of the vSphere resource pool to use for the VMs
Expand Down
1 change: 0 additions & 1 deletion examples/vsphere/sample-terraform-vi.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ netmask = "" # Network interface netmask

# vSphere
vsphere_server = "" # Name of the vSphere server
vsphere_cluster = "" # Name of the vSphere cluster
vsphere_datacenter = "" # Name of the vSphere data center
vsphere_datastore = "" # Name of the vSphere data store to use for the VMs
vsphere_resource_pool = "" # Name of the vSphere resource pool to use for the VMs
Expand Down
50 changes: 50 additions & 0 deletions linting-configs/.ansible-lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
# .ansible-lint

profile: moderate
verbosity: 1
strict: true

# Enforce variable names to follow pattern below, in addition to Ansible own
# requirements, like avoiding python identifiers. To disable add `var-naming`
# to skip_list.
var_naming_pattern: ^[a-zA-Z0-9_]*$

use_default_rules: true

# Ansible-lint is able to recognize and load skip rules stored inside
# `.ansible-lint-ignore` (or `.config/ansible-lint-ignore.txt`) files.
# To skip a rule just enter filename and tag, like "playbook.yml package-latest"
# on a new line.
dhoucgitter marked this conversation as resolved.
Show resolved Hide resolved
skip_list:
- role-name # roles are dynamically selected based on user's choice so we do need to use paths
- yaml[line-length] # it's easier to understand/debug the underlying command when it's not broken up, excessively long lines that make sense to split up should be caught during code review,
- name[template] # task name is being templated, this can be ignored
- command-instead-of-shell # shell should only be used when necessary, swap to command TODO future update requires functionality change
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note:
Ignoring command-instead-of-shell, command-instead-of-module, and deprecated-module linting warnings for now. To resolve these linter warnings it requires a change of functionality which I was trying to avoid with this PR. I've created a Jira ticket to address these as part of a future sprint. These are not breaking or high priority warnings that need immediate attention, just nice to have.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IAC-1088, for any internal users seeing this.

- command-instead-of-module # there are some cases where command calls could be replaced with modules TODO future update requires functionality change
- deprecated-module # In future look for suitable replacement TODO future update requires functionality change

# Ansible-lint does not automatically load rules that have the 'opt-in' tag.
# You must enable opt-in rules by listing each rule 'id' below.
enable_list:
- args
- empty-string-compare
- no-log-password
- no-same-owner
- yaml

# exclude_paths included in this file are parsed relative to this file's location
# and not relative to the CWD of execution. CLI arguments passed to the --exclude
# option are parsed relative to the CWD of execution.
exclude_paths:
- examples/bare-metal/sample-ansible-vars.yaml # ignore this file, spacing is done for doc purposes

# Offline mode disables installation of requirements.yml and schema refreshing
offline: false

# Define required Ansible's variables to satisfy syntax check
extra_vars:
kubernetes_cri: containerd
kubernetes_cni: calico
kubernetes_loadbalancer: kube_vip
deployment_type: vsphere
3 changes: 3 additions & 0 deletions linting-configs/.hadolint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignored:
- DL3008 # Specify version with apt-get install -y <package>=<version> : https://github.com/hadolint/hadolint/wiki/DL3008
- DL3015 # Require --no-install-recommends to get all required packages for sshpass
6 changes: 6 additions & 0 deletions linting-configs/.shellcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Review 'man shellcheck' section 'RC FILES' for instructions on adding directives.

# Allow using `which` since it gives full paths and is common enough
# https://github.com/koalaman/shellcheck/wiki/SC2230
# https://www.shellcheck.net/wiki/SC2068 we split the string back into an array
disable=SC2230,SC2068
27 changes: 27 additions & 0 deletions linting-configs/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# For more information on configuring TFlint; see https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/config.md

# For more information on plugins see https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/plugins.md

# For more information on TFlint Ruleset for Terraform; see https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.3.0/docs/rules/README.md

# For more information on TFlint Ruleset for GCP, see https://github.com/terraform-linters/tflint-ruleset-google/blob/master/README.md

config {
# Enables module inspection.
module = true
}

plugin "terraform" {
enabled = true
preset = "recommended"
}

# We specify the versions and providers in the top level versions.tf.
# This stops it from throwing a warning when scanning our modules
# in ./modules
rule "terraform_required_version" {
enabled = false
}
rule "terraform_required_providers" {
enabled = false
}
4 changes: 2 additions & 2 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ locals {
control_plane_ips = flatten(sort(flatten([for item in values(module.control_plane) : values(item)])))

## System nodes
system_nodes = local.node_pools == null ? {} : { for k, v in local.node_pools : k => v if k == "system" }
system_node_ips = flatten(sort(flatten([for item in values(module.system) : values(item)])))
system_nodes = local.node_pools == null ? {} : { for k, v in local.node_pools : k => v if k == "system" }
# system_node_ips = flatten(sort(flatten([for item in values(module.system) : values(item)]))) not used, ref for future use

## Nodes
nodes = local.node_pools == null ? {} : { for k, v in local.node_pools : k => v if(k != "control_plane" && k != "system") }
Expand Down
1 change: 0 additions & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ module "postgresql" {
datacenter_id = data.vsphere_datacenter.dc.id
template = var.vsphere_template
cluster_domain = var.cluster_domain
cluster_name = local.cluster_name
dns_servers = var.dns_servers
netmask = var.netmask
gateway = var.gateway
Expand Down
2 changes: 1 addition & 1 deletion modules/server/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ resource "vsphere_virtual_machine" "server" {
disk {
label = "disk0"
size = var.disk_size
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
thin_provisioned = data.vsphere_virtual_machine.template.disks[0].thin_provisioned
}

clone {
Expand Down
4 changes: 0 additions & 4 deletions modules/server/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ variable "cluster_domain" {
type = string
}

variable "cluster_name" {
type = string
}

variable "datacenter_id" {
type = string
}
Expand Down
6 changes: 3 additions & 3 deletions modules/vm/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ data "vsphere_virtual_machine" "template" {

locals {
static_config = (length(var.ip_addresses) > 0 ? true : false)
ip_addresses = local.static_config ? var.ip_addresses : vsphere_virtual_machine.dhcp.*.default_ip_address
ip_addresses = local.static_config ? var.ip_addresses : vsphere_virtual_machine.dhcp[*].default_ip_address
}

resource "vsphere_virtual_machine" "static" {
Expand All @@ -43,7 +43,7 @@ resource "vsphere_virtual_machine" "static" {
disk {
label = "os-disk-01"
size = var.disk_size
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
thin_provisioned = data.vsphere_virtual_machine.template.disks[0].thin_provisioned
unit_number = 0
}
dynamic "disk" {
Expand Down Expand Up @@ -99,7 +99,7 @@ resource "vsphere_virtual_machine" "dhcp" {
disk {
label = "os-disk-01"
size = var.disk_size
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
thin_provisioned = data.vsphere_virtual_machine.template.disks[0].thin_provisioned
unit_number = 0
}
dynamic "disk" {
Expand Down
Loading