Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/common/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func (r *Runner) TagFile(file string) {
}
logger.Info(fmt.Sprintf("Tagging %v\n", file))
blocks, err := parser.ParseFile(file)
utils.AppendSkippesRunner(&r.skippedResources)
if err != nil {
logger.Info(fmt.Sprintf("Failed to parse file %v with parser %v", file, reflect.TypeOf(parser)))
continue
Expand Down
6 changes: 6 additions & 0 deletions src/common/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ import (

// RemoveGcpInvalidChars Source of regex: https://cloud.google.com/compute/docs/labeling-resources
var RemoveGcpInvalidChars = regexp.MustCompile(`[^\p{Ll}\p{Lo}\p{N}_-]`)
var SkipArr = make([]string, 0)

func AppendSkippesRunner(skippedResources *[]string) {
*skippedResources = append(*skippedResources, SkipArr...)
SkipArr = SkipArr[:0]
}

func InSlice[T comparable](elems []T, v T) bool {
for _, s := range elems {
Expand Down
11 changes: 9 additions & 2 deletions src/common/yaml/yaml_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const SingleIndent = " "
func WriteYAMLFile(readFilePath string, blocks []structure.IBlock, writeFilePath string, tagsAttributeName string, resourcesStartToken string) error {
// #nosec G304
// read file bytes

originFileSrc, err := os.ReadFile(readFilePath)
if err != nil {
return fmt.Errorf("failed to read file %s because %s", readFilePath, err)
Expand Down Expand Up @@ -278,7 +279,6 @@ func MapResourcesLineYAML(filePath string, resourceNames []string, resourcesStar
logger.Warning(fmt.Sprintf("failed to read file %s", filePath))
return nil
}

readResources := false
latestResourceName := ""
fileLines := strings.Split(string(file), "\n")
Expand All @@ -287,12 +287,19 @@ func MapResourcesLineYAML(filePath string, resourceNames []string, resourcesStar
for i, line := range fileLines {
cleanContent := strings.TrimSpace(line)
if strings.HasPrefix(cleanContent, resourcesStartToken+":") {
if strings.ToUpper(strings.TrimSpace(fileLines[i-1])) == "#YOR:SKIPALL" {
utils.SkipArr = append(utils.SkipArr, resourceNames...)
}
readResources = true
resourcesIndent = countLeadingSpaces(line)
continue
}

if readResources {
if i > 0 {
if strings.ToUpper(strings.TrimSpace(fileLines[i-1])) == "#YOR.SKIP" {
utils.SkipArr = append(utils.SkipArr, strings.Trim(strings.TrimSpace(line), ":"))
}
}
lineIndent := countLeadingSpaces(line)
if lineIndent <= resourcesIndent && strings.TrimSpace(line) != "" && !strings.Contains(line, "#") {
// No longer inside resources block, get the last line of the previous resource if exists
Expand Down
15 changes: 14 additions & 1 deletion src/terraform/structure/terraform_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func (p *TerraformParser) ParseFile(filePath string) ([]structure.IBlock, error)
if err != nil {
return nil, fmt.Errorf("failed to read file %s because %s", filePath, err)
}
lines := strings.Split(string(src), "\n")

// parse the file into hclwrite.File and hclsyntax.File to allow getting existing tags and lines
hclFile, diagnostics := hclwrite.ParseConfig(src, filePath, hcl.InitialPos)
Expand All @@ -150,14 +151,15 @@ func (p *TerraformParser) ParseFile(filePath string) ([]structure.IBlock, error)
}

syntaxBlocks := hclSyntaxFile.Body.(*hclsyntax.Body).Blocks

skipAll := false
rawBlocks := hclFile.Body().Blocks()
parsedBlocks := make([]structure.IBlock, 0)
for i, block := range rawBlocks {
if !utils.InSlice(SupportedBlockTypes, block.Type()) {
continue
}
blockID := strings.Join(block.Labels(), ".")

terraformBlock, err := p.parseBlock(block, filePath)
if err != nil {
if strings.HasPrefix(err.Error(), "resource belongs to skipped") || strings.HasPrefix(err.Error(), "could not find client") {
Expand All @@ -174,6 +176,17 @@ func (p *TerraformParser) ParseFile(filePath string) ([]structure.IBlock, error)
}
terraformBlock.Init(filePath, block)
terraformBlock.AddHclSyntaxBlock(syntaxBlocks[i])
line := terraformBlock.GetLines().Start
if line > 1 && line <= len(lines) {
lineAbove := lines[line-2]
if strings.ToUpper(strings.TrimSpace(lineAbove))== "#YOR:SKIPALL" {
skipAll = true
}

if strings.ToUpper(strings.TrimSpace(lineAbove)) == "#YOR:SKIP" || skipAll {
utils.SkipArr = append(utils.SkipArr, terraformBlock.GetResourceID())
}
}
parsedBlocks = append(parsedBlocks, terraformBlock)
}

Expand Down
49 changes: 49 additions & 0 deletions src/terraform/structure/terraform_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,52 @@ import (
"github.com/stretchr/testify/assert"
)

func TestTerraformParser_SkipResourceByComment(t *testing.T) {
t.Run("SkipAll comment added all resources to utils.SkipArr", func(t *testing.T) {
// Initialize TerraformParser and parse file with all resources containing skip comment
p := &TerraformParser{}
p.Init("../../../tests/terraform/skipComment/", nil)
defer p.Close()
filePath := "../../../tests/terraform/skipComment/skipAll.tf"
_, err := p.ParseFile(filePath)
if err != nil {
t.Errorf("failed to read hcl file because %s", err)
}
exceptedSkipResources := []string{"aws_vpc.example_vpc", "aws_subnet.example_subnet", "aws_instance.example_instance"}
assert.Equal(t, exceptedSkipResources, utils.SkipArr)
defer resetSkipArr()
})

t.Run("No resources with skip comment in the file, utils.SkipArr should be empty", func(t *testing.T) {
// Initialize TerraformParser and parse file with no skip tags
p := &TerraformParser{}
p.Init("../../../tests/terraform/skipComment/", nil)
defer p.Close()
filePath := "../../../tests/terraform/skipComment/noSkip.tf"
_, err := p.ParseFile(filePath)
if err != nil {
t.Errorf("failed to read hcl file because %s", err)
}
assert.Empty(t, utils.SkipArr)
defer resetSkipArr()
})

t.Run("One resource with skip comment, only that resource added to utils.SkipArr", func(t *testing.T) {
// Initialize TerraformParser and parse file with one resource containing skip tag
p := &TerraformParser{}
p.Init("../../../tests/terraform/skipComment/", nil)
defer p.Close()
filePath := "../../../tests/terraform/skipComment/skipOne.tf"
_, err := p.ParseFile(filePath)
if err != nil {
t.Errorf("failed to read hcl file because %s", err)
}
exceptedSkipResources := []string{"aws_instance.example_instance"}
assert.Equal(t, exceptedSkipResources, utils.SkipArr)
defer resetSkipArr()
})
}

func TestTerraformParser_ParseFile(t *testing.T) {
t.Run("parse aws eks file", func(t *testing.T) {
p := &TerraformParser{}
Expand Down Expand Up @@ -787,3 +833,6 @@ func compareTokenArrays(got []hclwrite.Tokens, want []hclwrite.Tokens) bool {

return true
}
func resetSkipArr() {
utils.SkipArr = []string{}
}
15 changes: 15 additions & 0 deletions tests/terraform/skipComment/noSkip.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "aws_vpc" "example_vpc" {
cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-1a"
}

resource "aws_instance" "example_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.example_subnet.id
}
16 changes: 16 additions & 0 deletions tests/terraform/skipComment/skipAll.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# yor:skip all
resource "aws_vpc" "example_vpc" {
cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-1a"
}

resource "aws_instance" "example_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.example_subnet.id
}
15 changes: 15 additions & 0 deletions tests/terraform/skipComment/skipOne.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "aws_vpc" "example_vpc" {
cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-1a"
}
# yor:skip
resource "aws_instance" "example_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.example_subnet.id
}