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

test #536

Closed
wants to merge 5 commits into from
Closed

test #536

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
9 changes: 8 additions & 1 deletion src/cloudformation/structure/cloudformation_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
type CloudformationParser struct {
*types.YamlParser
*types.JSONParser
skippedByCommentList []string
}

const TagsAttributeName = "Tags"
Expand Down Expand Up @@ -61,6 +62,10 @@ func (p *CloudformationParser) GetSupportedFileExtensions() []string {
return []string{common.YamlFileType.Extension, common.YmlFileType.Extension, common.CFTFileType.Extension, common.JSONFileType.Extension}
}

func (p *CloudformationParser) GetSkipResourcesByComment() []string {
return p.skippedByCommentList
}

// ValidFile Validate file has AWSTemplateFormatVersion
func (p *CloudformationParser) ValidFile(filePath string) bool {
// #nosec G304
Expand Down Expand Up @@ -113,6 +118,7 @@ func goformationParse(file string) (*cloudformation.Template, error) {
}

func (p *CloudformationParser) ParseFile(filePath string) ([]structure.IBlock, error) {
skipResourcesByComment := make([]string, 0)
goformationLock.Lock()
template, err := goformationParse(filePath)
goformationLock.Unlock()
Expand All @@ -138,7 +144,8 @@ func (p *CloudformationParser) ParseFile(filePath string) ([]structure.IBlock, e
var resourceNamesToLines map[string]*structure.Lines
switch utils.GetFileFormat(filePath) {
case common.YmlFileType.FileFormat, common.YamlFileType.FileFormat:
resourceNamesToLines = yaml.MapResourcesLineYAML(filePath, resourceNames, ResourcesStartToken)
resourceNamesToLines, skipResourcesByComment = yaml.MapResourcesLineYAML(filePath, resourceNames, ResourcesStartToken)
p.skippedByCommentList = append(p.skippedByCommentList, skipResourcesByComment...)
case common.JSONFileType.FileFormat:
var fileBracketsMapping map[int]json.BracketPair
resourceNamesToLines, fileBracketsMapping = json.MapResourcesLineJSON(filePath, resourceNames)
Expand Down
12 changes: 6 additions & 6 deletions src/cloudformation/structure/cloudformation_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
directory := "../../../tests/cloudformation/resources/ebs"
cfnParser := CloudformationParser{}
cfnParser.Init(directory, nil)
cfnBlocks, err := cfnParser.ParseFile(directory + "/ebs.yaml")
cfnBlocks, _, err := cfnParser.ParseFile(directory + "/ebs.yaml")

Check failure on line 22 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 3 variables but cfnParser.ParseFile returns 2 values
if err != nil {
t.Errorf("ParseFile() error = %v", err)
return
Expand All @@ -42,7 +42,7 @@
directory := "../../../tests/cloudformation/resources/ebs"
cfnParser := CloudformationParser{}
cfnParser.Init(directory, nil)
cfnBlocks, err := cfnParser.ParseFile(directory + "/ebs.json")
cfnBlocks, _, err := cfnParser.ParseFile(directory + "/ebs.json")

Check failure on line 45 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 3 variables but cfnParser.ParseFile returns 2 values
if err != nil {
t.Errorf("ParseFile() error = %v", err)
return
Expand All @@ -66,7 +66,7 @@
cfnParser := CloudformationParser{}
cfnParser.Init(directory, nil)
sourceFile := directory + "/base.template"
cfnBlocks, _ := cfnParser.ParseFile(sourceFile)
cfnBlocks, _, _ := cfnParser.ParseFile(sourceFile)

Check failure on line 69 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 3 variables but cfnParser.ParseFile returns 2 values

rawFileLines, _ := cfnParser.FileToResourcesLines.Load(sourceFile)
resourceLines := rawFileLines.(structure.Lines)
Expand All @@ -81,15 +81,15 @@
cfnParser := CloudformationParser{}
cfnParser.Init(directory, nil)
sourceFile := directory + "/cfn.yaml"
cfnBlocks, _ := cfnParser.ParseFile(sourceFile)
cfnBlocks, _, _ := cfnParser.ParseFile(sourceFile)

Check failure on line 84 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 3 variables but cfnParser.ParseFile returns 2 values
assert.Equal(t, 3, len(cfnBlocks))
})

t.Run("parse Policy_PolicyTag", func(t *testing.T) {
directory := "../../../tests/cloudformation/resources/special_tags"
cfnParser := CloudformationParser{}
cfnParser.Init(directory, nil)
cfnBlocks, err := cfnParser.ParseFile(directory + "/cfn.yaml")
cfnBlocks, err, _ := cfnParser.ParseFile(directory + "/cfn.yaml")

Check failure on line 92 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 3 variables but cfnParser.ParseFile returns 2 values
if err != nil {
t.Errorf("ParseFile() error = %v", err)
return
Expand Down Expand Up @@ -123,7 +123,7 @@
expected := map[string]*structure.Lines{
"NewVolume": {Start: 3, End: 15},
}
actual := yaml.MapResourcesLineYAML(filePath, resourcesNames, ResourcesStartToken)

Check failure on line 126 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 1 variable but yaml.MapResourcesLineYAML returns 2 values
compareLines(t, expected, actual)
})

Expand All @@ -136,7 +136,7 @@
"EC2LaunchTemplateResource0": {Start: 18, End: 23},
"EC2LaunchTemplateResource1": {Start: 24, End: 34},
}
actual := yaml.MapResourcesLineYAML(filePath, resourcesNames, ResourcesStartToken)

Check failure on line 139 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 1 variable but yaml.MapResourcesLineYAML returns 2 values
compareLines(t, expected, actual)
})

Expand Down Expand Up @@ -169,7 +169,7 @@
tagGroup.SetTags(extraTags)
tagGroup.InitTagGroup("", []string{}, []string{})
writeFilePath := directory + "/" + testFileName + "_tagged." + fileType
cfnBlocks, err := cfnParser.ParseFile(readFilePath)
cfnBlocks, _, err := cfnParser.ParseFile(readFilePath)

Check failure on line 172 in src/cloudformation/structure/cloudformation_parser_test.go

View workflow job for this annotation

GitHub Actions / unit-test (1.19)

assignment mismatch: 3 variables but cfnParser.ParseFile returns 2 values
for _, block := range cfnBlocks {
err := tagGroup.CreateTagsForBlock(block)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions src/common/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ type IParser interface {
WriteFile(readFilePath string, blocks []structure.IBlock, writeFilePath string) error
GetSkippedDirs() []string
GetSupportedFileExtensions() []string
GetSkipResourcesByComment() []string
Close()
}
10 changes: 8 additions & 2 deletions src/common/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,17 @@ func (r *Runner) isSkippedResourceType(resourceType string) bool {
return false
}

func (r *Runner) isSkippedResource(resource string) bool {
func (r *Runner) isSkippedResource(resource string, skipResourcesByComment []string) bool {
for _, skippedResource := range r.skippedResources {
if resource == skippedResource {
return true
}
}
for _, skippedResource := range skipResourcesByComment {
if resource == skippedResource {
return true
}
}
return false
}

Expand All @@ -186,7 +191,8 @@ func (r *Runner) TagFile(file string) {
if r.isSkippedResourceType(block.GetResourceType()) {
continue
}
if r.isSkippedResource(block.GetResourceID()) {
skipResourcesByComment := parser.GetSkipResourcesByComment()
if r.isSkippedResource(block.GetResourceID(), skipResourcesByComment) {
continue
}
if block.IsBlockTaggable() {
Expand Down
16 changes: 13 additions & 3 deletions src/common/yaml/yaml_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,9 @@ func FindTagsLinesYAML(textLines []string, tagsAttributeName string) (structure.
return tagsLines, tagsExist
}

func MapResourcesLineYAML(filePath string, resourceNames []string, resourcesStartToken string) map[string]*structure.Lines {
func MapResourcesLineYAML(filePath string, resourceNames []string, resourcesStartToken string) (map[string]*structure.Lines, []string) {
resourceToLines := make(map[string]*structure.Lines)
skipResourcesByComment := make([]string, 0)
for _, resourceName := range resourceNames {
// initialize a map between resource name and its lines in file
resourceToLines[resourceName] = &structure.Lines{Start: -1, End: -1}
Expand All @@ -276,7 +277,7 @@ func MapResourcesLineYAML(filePath string, resourceNames []string, resourcesStar
file, err := os.ReadFile(filePath)
if err != nil {
logger.Warning(fmt.Sprintf("failed to read file %s", filePath))
return nil
return nil, skipResourcesByComment
}

readResources := false
Expand All @@ -287,12 +288,21 @@ 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" {
skipResourcesByComment = append(skipResourcesByComment, resourceNames...)
}
readResources = true
resourcesIndent = countLeadingSpaces(line)
continue
}

if readResources {
if i > 0 {
if strings.ToUpper(strings.TrimSpace(fileLines[i-1])) == "#YOR:SKIP" {
skipResourcesByComment = append(skipResourcesByComment, 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 Expand Up @@ -325,7 +335,7 @@ func MapResourcesLineYAML(filePath string, resourceNames []string, resourcesStar
// Handle last line of resource is last line of file
resourceToLines[latestResourceName].End = findLastNonEmptyLine(fileLines, len(fileLines)-1)
}
return resourceToLines
return resourceToLines, skipResourcesByComment
}

func countLeadingSpaces(line string) int {
Expand Down
11 changes: 9 additions & 2 deletions src/serverless/structure/serverless_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const FunctionsSectionName = "functions"
const FunctionType = "function"

type ServerlessParser struct {
YamlParser types.YamlParser
YamlParser types.YamlParser
skippedByCommentList []string
}

var slsParseLock sync.Mutex
Expand Down Expand Up @@ -71,7 +72,12 @@ func (p *ServerlessParser) ValidFile(file string) bool {
return true
}

func (p *ServerlessParser) GetSkipResourcesByComment() []string {
return p.skippedByCommentList
}

func (p *ServerlessParser) ParseFile(filePath string) ([]structure.IBlock, error) {
skipResourcesByComment := make([]string, 0)
parsedBlocks := make([]structure.IBlock, 0)
fileFormat := utils.GetFileFormat(filePath)
fileName := filepath.Base(filePath)
Expand Down Expand Up @@ -101,7 +107,8 @@ func (p *ServerlessParser) ParseFile(filePath string) ([]structure.IBlock, error
}
switch utils.GetFileFormat(filePath) {
case common.YmlFileType.FileFormat, common.YamlFileType.FileFormat:
resourceNamesToLines = yamlUtils.MapResourcesLineYAML(filePath, resourceNames, FunctionsSectionName)
resourceNamesToLines, skipResourcesByComment = yamlUtils.MapResourcesLineYAML(filePath, resourceNames, FunctionsSectionName)
p.skippedByCommentList = append(p.skippedByCommentList, skipResourcesByComment...)
default:
return nil, fmt.Errorf("unsupported file type %s", utils.GetFileFormat(filePath))
}
Expand Down
18 changes: 18 additions & 0 deletions src/terraform/structure/terraform_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type TerraformParser struct {
moduleInstallDir string
downloadedPaths []string
tfClientLock sync.Mutex
skippedByCommentList []string
}

func (p *TerraformParser) Name() string {
Expand Down Expand Up @@ -121,6 +122,10 @@ func (p *TerraformParser) GetSourceFiles(directory string) ([]string, error) {
return files, nil
}

func (p *TerraformParser) GetSkipResourcesByComment() []string {
return p.skippedByCommentList
}

func (p *TerraformParser) ValidFile(_ string) bool {
return true
}
Expand All @@ -132,6 +137,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 @@ -151,6 +157,7 @@ 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 {
Expand All @@ -174,6 +181,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 {
p.skippedByCommentList = append(p.skippedByCommentList, terraformBlock.GetResourceID())
}
}
parsedBlocks = append(parsedBlocks, terraformBlock)
}

Expand Down
29 changes: 29 additions & 0 deletions tests/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,35 @@ func TestRunResults(t *testing.T) {
})
}

func TestSkipResourcesByComment(t *testing.T) {
t.Run("Test tagging terraform and cloudFormation files and skip resource by comment", func(t *testing.T) {
yorRunner := runner.Runner{}
err := yorRunner.Init(&clioptions.TagOptions{
Directory: "./skipComment",
TagGroups: getTagGroups(),
Parsers: []string{"Terraform", "CloudFormation"},
})
tfFileBytes, _ := os.ReadFile("./skipComment/skipResource.tf")
yamlFileBytes, _ := os.ReadFile("./skipComment/skipResource.yaml")
defer func() {
_ = os.WriteFile("./skipComment/skipResource.tf", tfFileBytes, 0644)
_ = os.WriteFile("./skipComment/skipResource.yaml", yamlFileBytes, 0644)
}()
failIfErr(t, err)
reportService, err := yorRunner.TagDirectory()
failIfErr(t, err)

reportService.CreateReport()
report := reportService.GetReport()

newTags := report.NewResourceTags
for _, newTag := range newTags {
assert.NotEqual(t, "aws_vpc.example_vpc", newTag.ResourceID)
assert.NotEqual(t, "NewVolume1", newTag.ResourceID)
}
})
}

func TestTagUncommittedResults(t *testing.T) {
t.Run("Test tagging twice no result second time", func(t *testing.T) {
terragoatPath := utils.CloneRepo(utils.TerragoatURL, "063dc2db3bb036160ed39d3705508ee8293a27c8")
Expand Down
24 changes: 24 additions & 0 deletions tests/integration/skipComment/skipResource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#yor:skip
resource "aws_vpc" "example_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
}
}

resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-1a"
tags = {
yor_name = "example_subnet"
yor_trace = "74091a97-d11a-4500-a0c3-af942a0d8e00"
}
}

resource "aws_instance" "example_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.example_subnet.id
tags = {
}
}
25 changes: 25 additions & 0 deletions tests/integration/skipComment/skipResource.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample EBS Volume with EC2 instance template
Resources:
NewVolume:
Type: AWS::EC2::Volume
Properties:
Size: 100
Encrypted: true
#Encrypted: false
AvailabilityZone: us-west-2a
Tags:
- Key: yor_trace
Value: d5e1032c-34e9-428d-8b17-4dff36d05e68
- Key: yor_name
Value: NewVolume
#yor:skip
NewVolume1:
Type: AWS::EC2::Volume
Properties:
Size: 100
Encrypted: true
#Encrypted: false
AvailabilityZone: us-west-2a
Tags:
DeletionPolicy: Snapshot
Loading