github.com/avenga/couper@v1.12.2/config/configload/merge_internal_test.go (about)

     1  package configload
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"github.com/google/go-cmp/cmp"
     8  	"github.com/hashicorp/hcl/v2"
     9  	"github.com/hashicorp/hcl/v2/gohcl"
    10  	"github.com/hashicorp/hcl/v2/hclsyntax"
    11  	"github.com/hashicorp/hcl/v2/hclwrite"
    12  
    13  	"github.com/avenga/couper/config/parser"
    14  	"github.com/avenga/couper/internal/test"
    15  )
    16  
    17  func Test_mergeServers_ServerTLS(t *testing.T) {
    18  	tests := []struct {
    19  		name    string
    20  		content []string
    21  		want    string
    22  		wantErr bool
    23  	}{
    24  		{"normal, one file", []string{`server {
    25    tls {
    26      server_certificate {
    27        attr1 = "val1"
    28      }
    29      server_certificate {
    30        attr1 = "val2"
    31      }
    32      client_certificate {
    33        attr1 = "val3"
    34      }
    35    }
    36  }`}, `server {
    37    tls {
    38      client_certificate {
    39        attr1 = "val3"
    40      }
    41      server_certificate {
    42        attr1 = "val1"
    43      }
    44      server_certificate {
    45        attr1 = "val2"
    46      }
    47    }
    48  }
    49  `, false},
    50  		{"two files, override", []string{`server {
    51    tls {
    52      server_certificate {
    53        attr1 = "val1"
    54      }
    55      server_certificate {
    56        attr1 = "val2"
    57      }
    58      server_certificate "named" {
    59        attr1 = "val3"
    60      }
    61      client_certificate {
    62        attr1 = "val1"
    63      }
    64      client_certificate {
    65        attr1 = "val2"
    66      }
    67      client_certificate "named" {
    68        attr1 = "val3"
    69      }
    70    }
    71  }`, `server {
    72    tls {
    73      server_certificate {
    74        attr2 = "val4"
    75      }
    76      server_certificate "named" {
    77        attr2 = "val5"
    78      }
    79      client_certificate {
    80        attr2 = "val6"
    81      }
    82      client_certificate "named" {
    83        attr2 = "val7"
    84      }
    85    }
    86  }`}, `server {
    87    tls {
    88      client_certificate {
    89        attr2 = "val6"
    90      }
    91      server_certificate {
    92        attr2 = "val4"
    93      }
    94      client_certificate "named" {
    95        attr2 = "val7"
    96      }
    97      server_certificate "named" {
    98        attr2 = "val5"
    99      }
   100    }
   101  }
   102  `, false},
   103  		{"two files, merge", []string{`server {
   104    tls {
   105      server_certificate "example1.com" {
   106        attr1 = "val1"
   107      }
   108      client_certificate "a" {
   109        attr1 = "val2"
   110      }
   111      client_certificate {
   112        attr1 = "val3"
   113      }
   114    }
   115  }`, `server {
   116    tls {
   117      server_certificate "example2.com" {
   118        attr2 = "val2"
   119      }
   120      server_certificate {
   121        attr2 = "val3"
   122      }
   123      client_certificate "b" {
   124        attr2 = "val6"
   125      }
   126    }
   127  }`}, `server {
   128    tls {
   129      client_certificate {
   130        attr1 = "val3"
   131      }
   132      server_certificate {
   133        attr2 = "val3"
   134      }
   135      client_certificate "a" {
   136        attr1 = "val2"
   137      }
   138      client_certificate "b" {
   139        attr2 = "val6"
   140      }
   141      server_certificate "example1.com" {
   142        attr1 = "val1"
   143      }
   144      server_certificate "example2.com" {
   145        attr2 = "val2"
   146      }
   147    }
   148  }
   149  `, false},
   150  	}
   151  	for _, tt := range tests {
   152  		t.Run(tt.name, func(st *testing.T) {
   153  			hlp := test.New(st)
   154  
   155  			parsedBodies, err := parseBodies(tt.content)
   156  			hlp.Must(err)
   157  
   158  			blocks, err := mergeServers(parsedBodies, nil)
   159  			hlp.Must(err)
   160  
   161  			result := writeBlocks(blocks)
   162  
   163  			if (err != nil) != tt.wantErr {
   164  				t.Errorf("bodiesToConfig() error = %v, wantErr %v", err, tt.wantErr)
   165  				return
   166  			}
   167  
   168  			if diff := cmp.Diff(result, tt.want); diff != "" {
   169  				t.Error(diff)
   170  			}
   171  		})
   172  	}
   173  }
   174  
   175  func Test_mergeDefinitions_BackendTLS(t *testing.T) {
   176  	tests := []struct {
   177  		name    string
   178  		content []string
   179  		want    string
   180  		wantErr bool
   181  	}{
   182  		{"normal, one file", []string{`definitions {
   183    backend "one" {
   184      tls {
   185        server_ca_certificate_file = "same.crt"
   186      }
   187    }
   188  }`}, `definitions {
   189    backend "one" {
   190      tls {
   191        server_ca_certificate_file = "same.crt"
   192      }
   193    }
   194  }
   195  `, false},
   196  		{"two files, replace", []string{`definitions {
   197    backend "one" {
   198      origin = "https://localhost"
   199      tls {
   200        server_ca_certificate_file = "one.crt"
   201      }
   202    }
   203  }`, `definitions {
   204    backend "one" {
   205      tls {
   206        server_ca_certificate_file = "two.crt"
   207      }
   208    }
   209  }`}, `definitions {
   210    backend "one" {
   211      tls {
   212        server_ca_certificate_file = "two.crt"
   213      }
   214    }
   215  }
   216  `, false},
   217  		{"two files, append", []string{`definitions {
   218    backend "one" {
   219      tls {
   220        server_ca_certificate_file = "one.crt"
   221      }
   222    }
   223  }`, `definitions {
   224    backend "two" {
   225      tls {
   226        server_ca_certificate_file = "two.crt"
   227      }
   228    }
   229  }`}, `definitions {
   230    backend "one" {
   231      tls {
   232        server_ca_certificate_file = "one.crt"
   233      }
   234    }
   235    backend "two" {
   236      tls {
   237        server_ca_certificate_file = "two.crt"
   238      }
   239    }
   240  }
   241  `, false},
   242  	}
   243  	for _, tt := range tests {
   244  		t.Run(tt.name, func(st *testing.T) {
   245  			hlp := test.New(st)
   246  
   247  			parsedBodies, err := parseBodies(tt.content)
   248  			hlp.Must(err)
   249  
   250  			block, _, err := mergeDefinitions(parsedBodies)
   251  			hlp.Must(err)
   252  
   253  			result := writeBlocks(hclsyntax.Blocks{block})
   254  
   255  			if (err != nil) != tt.wantErr {
   256  				t.Errorf("bodiesToConfig() error = %v, wantErr %v", err, tt.wantErr)
   257  				return
   258  			}
   259  
   260  			if diff := cmp.Diff(result, tt.want); diff != "" {
   261  				t.Error(diff)
   262  			}
   263  		})
   264  	}
   265  }
   266  
   267  func writeBlocks(blocks hclsyntax.Blocks) string {
   268  	f := hclwrite.NewEmptyFile()
   269  	root := f.Body()
   270  
   271  	appendSorted(root, blocks)
   272  
   273  	b := &bytes.Buffer{}
   274  	_, _ = f.WriteTo(b)
   275  	return b.String()
   276  }
   277  
   278  func parseBodies(bodies []string) ([]*hclsyntax.Body, error) {
   279  	var parsedBodies []*hclsyntax.Body
   280  	for _, bodyStr := range bodies {
   281  		body, err := parser.Load([]byte(bodyStr), "")
   282  		if err != nil {
   283  			return nil, err
   284  		}
   285  		parsedBodies = append(parsedBodies, body)
   286  	}
   287  	return parsedBodies, nil
   288  }
   289  
   290  func appendBlock(parent *hclwrite.Body, block *hclsyntax.Block) {
   291  	writeBlock := gohcl.EncodeAsBlock(block, block.Type)
   292  	writeBlock.SetLabels(block.Labels)
   293  
   294  	appendSorted(writeBlock.Body(), block.Body.Blocks)
   295  
   296  	appendAttrs(writeBlock.Body(), block.Body.Attributes)
   297  
   298  	parent.AppendBlock(writeBlock)
   299  }
   300  
   301  func appendAttrs(parent *hclwrite.Body, attributes hclsyntax.Attributes) {
   302  	for _, attr := range attributes {
   303  		v, _ := attr.Expr.Value(&hcl.EvalContext{})
   304  		parent.SetAttributeValue(attr.Name, v)
   305  	}
   306  }
   307  
   308  func appendSorted(parent *hclwrite.Body, blocks hclsyntax.Blocks) {
   309  	named := namedBlocks{}
   310  	for _, block := range blocks {
   311  		if len(block.Labels) > 0 {
   312  			named[block.Type+"_"+block.Labels[0]] = block
   313  		} else {
   314  			appendBlock(parent, block)
   315  		}
   316  	}
   317  	for _, k := range getSortedMapKeys(named) {
   318  		appendBlock(parent, named[k])
   319  	}
   320  }