Skip to content

Commit

Permalink
Move generic code to common package and clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
matbu committed Mar 22, 2024
1 parent 6e41688 commit 99b1947
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 212 deletions.
2 changes: 1 addition & 1 deletion cmd/cfg-diff.go
Expand Up @@ -58,7 +58,7 @@ or

func init() {
cfgDiffCmd.Flags().StringVarP(&configPatchFile, "configpatch", "o", "", "OpenShift configmap patch file path.")
cfgDiffCmd.Flags().StringVarP(&configFile, "configfile", "c", "", "OpenStack service INI config file path.")
cfgDiffCmd.Flags().StringVarP(&configFile, "configfile", "f", "", "OpenStack service INI config file path.")
cfgDiffCmd.Flags().StringVarP(&service, "service", "s", "", "OpenStack service, could be one of: Cinder, Glance...")
cfgDiffCmd.Flags().BoolVar(&frompod, "frompod", false, "Get config file directly from OpenShift service Pod.")
cfgDiffCmd.Flags().BoolVar(&frompodman, "frompodman", false, "Get config file directly from OpenStack podman container.")
Expand Down
5 changes: 4 additions & 1 deletion cmd/diff.go
Expand Up @@ -19,6 +19,7 @@ package cmd
import (
"fmt"
"os"

"github.com/openstack-k8s-operators/os-diff/pkg/godiff"
"github.com/openstack-k8s-operators/os-diff/pkg/servicecfg"

Expand All @@ -32,6 +33,7 @@ var quiet bool
var file1Cmd string
var file2Cmd string
var crd bool
var serviceCfgFile string

var diffCmd = &cobra.Command{
Use: "diff [path1] [path2]",
Expand Down Expand Up @@ -68,7 +70,7 @@ Example for directories:
path1 := args[0]
path2 := args[1]
if crd {
servicecfg.DiffEdpmCrdFromFile(path1, path2, "ovs_external_ids")
servicecfg.DiffEdpmCrdFromFile(path1, path2, "ovs_external_ids", serviceCfgFile)
return
}
if remote {
Expand Down Expand Up @@ -107,5 +109,6 @@ func init() {
diffCmd.Flags().BoolVar(&quiet, "quiet", false, "Do not print difference on the console and use logs report, only for files comparison")
diffCmd.Flags().BoolVar(&remote, "remote", false, "Run the diff remotely.")
diffCmd.Flags().BoolVar(&crd, "crd", false, "Compare a CRDs with a config file.")
diffCmd.Flags().StringVarP(&serviceCfgFile, "service-config", "f", "config.yaml", "Path for the Yaml config where the services are described.")
rootCmd.AddCommand(diffCmd)
}
48 changes: 7 additions & 41 deletions pkg/collectcfg/fetch.go
Expand Up @@ -21,34 +21,16 @@ import (
"encoding/json"
"fmt"
"os"
"github.com/openstack-k8s-operators/os-diff/pkg/common"
"os/exec"
"path"
"strings"

"github.com/openstack-k8s-operators/os-diff/pkg/common"

"gopkg.in/yaml.v3"
)

var config Config

// Service YAML Config Structure
type Service struct {
Enable bool `yaml:"enable"`
PodmanId string `yaml:"podman_id"`
PodmanImage string `yaml:"podman_image"`
PodmanName string `yaml:"podman_name"`
PodName string `yaml:"pod_name"`
ContainerName string `yaml:"container_name"`
StrictPodNameMatch bool `yaml:"strict_pod_name_match"`
Path []string `yaml:"path"`
Hosts []string `yaml:"hosts"`
ServiceCommand string `yaml:"service_command"`
CatOutput bool `yaml:"cat_output"`
}

type Config struct {
Services map[string]Service `yaml:"services"`
}
var config common.Config

// TripleO information structures:
type PodmanContainer struct {
Expand All @@ -57,23 +39,6 @@ type PodmanContainer struct {
Names []string `json:"Names"`
}

func LoadServiceConfig(configPath string) error {
file, err := os.Open(configPath)
if err != nil {
fmt.Println("Error opening file:", err)
return err
}
defer file.Close()

decoder := yaml.NewDecoder(file)
err = decoder.Decode(&config)
if err != nil {
fmt.Println("Error decoding YAML:", err)
return err
}
return nil
}

func dumpConfigFile(configPath string) error {
// Write updated data to config.yaml file
yamlData, err := yaml.Marshal(&config)
Expand Down Expand Up @@ -298,10 +263,11 @@ func FetchConfigFromEnv(configPath string,
localDir string, remoteDir string, tripleo bool, connection, sshCmd string, undercloud string) error {

var local bool
err := LoadServiceConfig(configPath)
cfg, err := common.LoadServiceConfigFile(configPath)
if err != nil {
return err
}
config = cfg

if connection == "local" {
local = true
Expand Down Expand Up @@ -362,14 +328,14 @@ func SetTripleODataEnv(configPath string, sshCmd string, filters []string, all b
}
data, _ := buildPodmanInfo(output, filters)
// Load config.yaml
err = LoadServiceConfig(configPath)
config, err = common.LoadServiceConfigFile(configPath)
if err != nil {
return err
}
// Update or add data to config
for name, info := range data {
if _, ok := config.Services[name]; !ok {
config.Services[name] = Service{}
config.Services[name] = common.Service{}
}
if entry, ok := config.Services[name]; ok {
entry.PodmanId = info["containerid"]
Expand Down
83 changes: 83 additions & 0 deletions pkg/common/utils.go
Expand Up @@ -18,10 +18,37 @@
package common

import (
"fmt"
"os"
"os/exec"
"reflect"
"strings"

"gopkg.in/yaml.v3"
)

var config Config

// Service YAML Config Structure
type Service struct {
Enable bool `yaml:"enable"`
PodmanId string `yaml:"podman_id"`
PodmanImage string `yaml:"podman_image"`
PodmanName string `yaml:"podman_name"`
PodName string `yaml:"pod_name"`
ContainerName string `yaml:"container_name"`
StrictPodNameMatch bool `yaml:"strict_pod_name_match"`
Path []string `yaml:"path"`
Hosts []string `yaml:"hosts"`
ServiceCommand string `yaml:"service_command"`
CatOutput bool `yaml:"cat_output"`
ConfigMapping map[string]string `yaml:"config_mapping"`
}

type Config struct {
Services map[string]Service `yaml:"services"`
}

// Shell execution functions:
func ExecCmd(cmd string) ([]string, error) {
output, err := exec.Command("bash", "-c", cmd).Output()
Expand Down Expand Up @@ -65,3 +92,59 @@ func StringInSlice(a string, list []string) bool {
}
return false
}

func GetNestedFieldValue(data interface{}, keyName string) interface{} {
val := reflect.ValueOf(data)
for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
val = val.Elem()
}
if val.Kind() != reflect.Struct {
return nil
}

field := val.FieldByName(keyName)
if !field.IsValid() {
return nil
}

return field.Interface()
}

func LoadServiceConfigFile(configPath string) (Config, error) {
file, err := os.Open(configPath)
if err != nil {
fmt.Println("Error opening file:", err)
return config, err
}
defer file.Close()

decoder := yaml.NewDecoder(file)
err = decoder.Decode(&config)
if err != nil {
fmt.Println("Error decoding YAML:", err)
return config, err
}
return config, nil
}

func ConvertToString(value interface{}) string {
switch v := value.(type) {
case string:
return v
case bool:
return fmt.Sprintf("%t", v)
case []string:
return fmt.Sprintf("%v", v)
default:
return fmt.Sprintf("%v", v)
}
}

func SnakeToCamel(s string) string {
parts := strings.Split(s, "_")
var result string
for _, part := range parts {
result += strings.Title(part)
}
return result
}
34 changes: 34 additions & 0 deletions pkg/godiff/utils.go
Expand Up @@ -372,3 +372,37 @@ func GetConfigFromRemote(remoteCmd string, configPath string) ([]byte, error) {
}
return []byte(out), nil
}

func CleanIniSections(config string) string {
lines := strings.Split(config, "\n")
sectionMap := make(map[string][]string)
currentSection := ""

for _, line := range lines {
line = strings.TrimSpace(line)
// Check if line is a section header
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
currentSection = strings.TrimPrefix(strings.TrimSuffix(line, "]"), "[")
continue
}
// Skip empty lines or lines without '='
if line == "" || !strings.Contains(line, "=") {
continue
}
// Append key-value pairs to section map
if currentSection != "" {
sectionMap[currentSection] = append(sectionMap[currentSection], line)
}
}
var sb strings.Builder
// Build updated INI string
for section, lines := range sectionMap {
sb.WriteString(fmt.Sprintf("[%s]\n", section))
for _, line := range lines {
sb.WriteString(fmt.Sprintf("%s\n", line))
}
sb.WriteString("\n")
}

return sb.String()
}
3 changes: 2 additions & 1 deletion pkg/servicecfg/cinder.go
Expand Up @@ -20,6 +20,7 @@ import (
"io/ioutil"
"strings"

"github.com/openstack-k8s-operators/os-diff/pkg/godiff"
"gopkg.in/yaml.v3"
)

Expand Down Expand Up @@ -89,5 +90,5 @@ func LoadCinderOpenShiftConfig(configPath string) string {
sb.WriteString(cinder.Spec.Cinder.Template.CustomServiceConfig)
}

return cleanIniSections(sb.String())
return godiff.CleanIniSections(sb.String())
}
73 changes: 20 additions & 53 deletions pkg/servicecfg/edpm.go
Expand Up @@ -19,33 +19,13 @@ package servicecfg
import (
"fmt"
"io/ioutil"
"os-diff/pkg/godiff"
"strings"

"gopkg.in/yaml.v2"
)

var config Config

// Service YAML Config Structure
type Service struct {
Enable bool `yaml:"enable"`
PodmanId string `yaml:"podman_id"`
PodmanImage string `yaml:"podman_image"`
PodmanName string `yaml:"podman_name"`
PodName string `yaml:"pod_name"`
ContainerName string `yaml:"container_name"`
StrictPodNameMatch bool `yaml:"strict_pod_name_match"`
Path []string `yaml:"path"`
Hosts []string `yaml:"hosts"`
ServiceCommand string `yaml:"service_command"`
CatOutput bool `yaml:"cat_output"`
ConfigMapping map[string]string `yaml:"config_mapping"`
}
"github.com/openstack-k8s-operators/os-diff/pkg/common"
"github.com/openstack-k8s-operators/os-diff/pkg/godiff"

type Config struct {
Services map[string]Service `yaml:"services"`
}
"gopkg.in/yaml.v3"
)

type OpenStackDataPlaneNodeSet struct {
APIVersion string `yaml:"apiVersion"`
Expand Down Expand Up @@ -129,29 +109,13 @@ type OpenStackDataPlaneNodeSet struct {
} `yaml:"spec"`
}

func LoadOpenStackDataPlaneNodeSetConfig(configPath string) string {
var sb strings.Builder
// Service structure
var service OpenStackDataPlaneNodeSet

yamlFile, err := ioutil.ReadFile(configPath)
if err != nil {
panic(err)
}

err = yaml.Unmarshal(yamlFile, &service)
if err != nil {
panic(err)
}

return cleanIniSections(sb.String())
}

func DiffEdpmCrdFromFile(srcFile string, EdpmPath string, serviceName string) error {
func DiffEdpmCrdFromFile(srcFile string, EdpmPath string, serviceName string, serviceCfgFile string) error {

var report []string
var config common.Config
// Load config file
LoadServiceConfigFile("config.yaml")
config, _ = common.LoadServiceConfigFile(serviceCfgFile)

//Load file
src, err := ioutil.ReadFile(srcFile)
if err != nil {
Expand Down Expand Up @@ -181,15 +145,18 @@ func DiffEdpmCrdFromFile(srcFile string, EdpmPath string, serviceName string) er
msg := fmt.Sprintf("Start to compare file contents for: %s and: %s \n", srcFile, EdpmPath)
report = append(report, msg)
//Compare File keys with Edpm according to mapping
if serviceName == "ovs_external_ids" {
for k, v := range config.Services[serviceName].ConfigMapping {
value := getNestedFieldValue(service.Spec.NodeTemplate.Ansible.AnsibleVars, snakeToCamel(v))
if srcMap[k] != ConvertToString(value) {
msg = fmt.Sprintf("-%s=%s\n", k, srcMap[k])
report = append(report, msg)
msg = fmt.Sprintf("+%s=%s\n", v, ConvertToString(value))
report = append(report, msg)
}
if _, ok := config.Services[serviceName]; !ok {
fmt.Println("Service not found: " + serviceName)
return nil
}

for k, v := range config.Services[serviceName].ConfigMapping {
value := common.GetNestedFieldValue(service.Spec.NodeTemplate.Ansible.AnsibleVars, common.SnakeToCamel(v))
if srcMap[k] != common.ConvertToString(value) {
msg = fmt.Sprintf("-%s=%s\n", k, srcMap[k])
report = append(report, msg)
msg = fmt.Sprintf("+%s=%s\n", v, common.ConvertToString(value))
report = append(report, msg)
}
}
godiff.PrintReport(report)
Expand Down
3 changes: 2 additions & 1 deletion pkg/servicecfg/glance.go
Expand Up @@ -20,6 +20,7 @@ import (
"io/ioutil"
"strings"

"github.com/openstack-k8s-operators/os-diff/pkg/godiff"
"gopkg.in/yaml.v3"
)

Expand Down Expand Up @@ -88,5 +89,5 @@ func LoadGlanceOpenShiftConfig(configPath string) string {
sb.WriteString(service.Spec.Glance.Template.CustomServiceConfig)
}

return cleanIniSections(sb.String())
return godiff.CleanIniSections(sb.String())
}

0 comments on commit 99b1947

Please sign in to comment.