-
Notifications
You must be signed in to change notification settings - Fork 222
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Wrapper for Multipath Configuration Update
* Adds wrapper to handle CRUD operations on the multipath configuration.
- Loading branch information
Showing
20 changed files
with
2,276 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright 2024 NetApp, Inc. All Rights Reserved. | ||
|
||
package mpathconfig | ||
|
||
//go:generate mockgen -destination=../../../mocks/mock_nodeprep/mock_mpathconfig/mock_config.go github.com/netapp/trident/internal/nodeprep/mpathconfig MpathConfiguration | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/hpe-storage/common-host-libs/mpathconfig" | ||
|
||
. "github.com/netapp/trident/logging" | ||
"github.com/netapp/trident/utils/errors" | ||
) | ||
|
||
const ( | ||
MultiPathConfigurationLocation = mpathconfig.MPATHCONF | ||
) | ||
|
||
type MpathConfiguration interface { | ||
GetRootSection() MpathConfigurationSection | ||
GetSection(sectionName string) (MpathConfigurationSection, error) | ||
PrintConf() []string | ||
SaveConfig(filePath string) error | ||
} | ||
|
||
var _ MpathConfiguration = &Configuration{} | ||
|
||
type Configuration struct { | ||
configuration *mpathconfig.Configuration | ||
} | ||
|
||
func (c *Configuration) GetRootSection() MpathConfigurationSection { | ||
return &Section{configuration: c.configuration, section: c.configuration.GetRoot()} | ||
} | ||
|
||
func (c *Configuration) GetSection(sectionName string) (MpathConfigurationSection, error) { | ||
if c.configuration == nil { | ||
return nil, errors.UnsupportedError(fmt.Sprintf("error getting section %s: empty configuration", sectionName)) | ||
} | ||
|
||
section, err := c.configuration.GetSection(sectionName, "") | ||
if err != nil { | ||
return nil, errors.NotFoundError("error getting section %s: %v", sectionName, err) | ||
} | ||
return &Section{configuration: c.configuration, section: section}, nil | ||
} | ||
|
||
func (c *Configuration) PrintConf() []string { | ||
if c.configuration == nil { | ||
return nil | ||
} | ||
return c.configuration.PrintConf() | ||
} | ||
|
||
func (c *Configuration) SaveConfig(filePath string) error { | ||
f, err := os.Create(filePath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer func() { | ||
_ = f.Close() | ||
}() | ||
|
||
s := c.PrintConf() | ||
w := bufio.NewWriter(f) | ||
for _, line := range s { | ||
if _, err = w.WriteString(line); err != nil { | ||
Log().WithField("fileName", filePath).WithError(err).Error("Error writing to multipath configuration file") | ||
} | ||
} | ||
if err = w.Flush(); err != nil { | ||
Log().WithField("fileName", filePath).WithError(err).Error("Error flushing multipath configuration file") | ||
return errors.New(fmt.Sprintf("error flushing multipath configuration file: %v", err)) | ||
} | ||
|
||
return err | ||
} | ||
|
||
func New() (MpathConfiguration, error) { | ||
return NewFromFile(os.DevNull) | ||
} | ||
|
||
func NewFromFile(filename string) (MpathConfiguration, error) { | ||
mpathCfg, err := mpathconfig.ParseConfig(filename) | ||
if err != nil { | ||
return nil, fmt.Errorf("error creating mpath config: %v", err) | ||
} | ||
return &Configuration{configuration: mpathCfg}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
// Copyright 2024 NetApp, Inc. All Rights Reserved. | ||
|
||
package mpathconfig_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/netapp/trident/internal/nodeprep/mpathconfig" | ||
) | ||
|
||
func TestNew(t *testing.T) { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
assert.NotNil(t, config) | ||
assert.IsType(t, &mpathconfig.Configuration{}, config) | ||
} | ||
|
||
func TestNewFromFile(t *testing.T) { | ||
type parameters struct { | ||
fileName string | ||
assertError assert.ErrorAssertionFunc | ||
assertConfig assert.ValueAssertionFunc | ||
} | ||
|
||
tests := map[string]parameters{ | ||
"test with a valid file": { | ||
fileName: os.DevNull, | ||
assertError: assert.NoError, | ||
assertConfig: assert.NotNil, | ||
}, | ||
"test with an invalid file": { | ||
fileName: "dd435124-8ef6-4c0c-b926-13f7c1f53ede.conf", | ||
assertError: assert.Error, | ||
assertConfig: assert.Nil, | ||
}, | ||
} | ||
|
||
for name, params := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
config, err := mpathconfig.NewFromFile(params.fileName) | ||
if params.assertError != nil { | ||
params.assertError(t, err) | ||
} | ||
if params.assertConfig != nil { | ||
params.assertConfig(t, config) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestConfiguration_GetRootSection(t *testing.T) { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
assert.NotNil(t, config) | ||
|
||
section := config.GetRootSection() | ||
assert.NotNil(t, section) | ||
assert.IsType(t, &mpathconfig.Section{}, section) | ||
} | ||
|
||
func TestConfiguration_GetSection(t *testing.T) { | ||
type parameters struct { | ||
getConfig func() mpathconfig.MpathConfiguration | ||
sectionName string | ||
assertError assert.ErrorAssertionFunc | ||
assertSection assert.ValueAssertionFunc | ||
} | ||
|
||
tests := map[string]parameters{ | ||
"get default section from uninitialized configuration": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
return &mpathconfig.Configuration{} | ||
}, | ||
sectionName: mpathconfig.DefaultsSectionName, | ||
assertError: assert.Error, | ||
assertSection: assert.Nil, | ||
}, | ||
"get default section from empty configuration": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
return config | ||
}, | ||
sectionName: mpathconfig.DefaultsSectionName, | ||
assertError: assert.Error, | ||
assertSection: assert.Nil, | ||
}, | ||
"get default section from configuration that has a default section": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
|
||
_, err = config.GetRootSection().AddSection(mpathconfig.DefaultsSectionName) | ||
assert.Nil(t, err) | ||
|
||
return config | ||
}, | ||
sectionName: mpathconfig.DefaultsSectionName, | ||
assertError: assert.NoError, | ||
assertSection: assert.NotNil, | ||
}, | ||
"get invalid section from configuration that has a default section": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
|
||
_, err = config.GetRootSection().AddSection(mpathconfig.DefaultsSectionName) | ||
assert.Nil(t, err) | ||
|
||
return config | ||
}, | ||
sectionName: "invalid", | ||
assertError: assert.Error, | ||
assertSection: assert.Nil, | ||
}, | ||
} | ||
|
||
for name, params := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
config := params.getConfig() | ||
|
||
section, err := config.GetSection(params.sectionName) | ||
if params.assertError != nil { | ||
params.assertError(t, err) | ||
} | ||
if params.assertSection != nil { | ||
params.assertSection(t, section) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestConfiguration_PrintConf(t *testing.T) { | ||
type parameters struct { | ||
getConfig func() mpathconfig.MpathConfiguration | ||
expectedOutput []string | ||
} | ||
|
||
tests := map[string]parameters{ | ||
"print uninitialized configuration": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
return &mpathconfig.Configuration{} | ||
}, | ||
expectedOutput: nil, | ||
}, | ||
"print empty configuration": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
return config | ||
}, | ||
expectedOutput: nil, | ||
}, | ||
"print configuration with a default section": { | ||
getConfig: func() mpathconfig.MpathConfiguration { | ||
config, err := mpathconfig.New() | ||
assert.Nil(t, err) | ||
|
||
_, err = config.GetRootSection().AddSection(mpathconfig.DefaultsSectionName) | ||
assert.Nil(t, err) | ||
|
||
return config | ||
}, | ||
expectedOutput: []string{"defaults {\n", "}\n"}, | ||
}, | ||
} | ||
|
||
for name, params := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
config := params.getConfig() | ||
output := config.PrintConf() | ||
assert.Equal(t, params.expectedOutput, output) | ||
}) | ||
} | ||
} | ||
|
||
func TestConfiguration_SaveConfig(t *testing.T) { | ||
config, err := mpathconfig.New() | ||
assert.NoError(t, err) | ||
defaultSection, err := config.GetRootSection().AddSection(mpathconfig.DefaultsSectionName) | ||
assert.NoError(t, err) | ||
err = defaultSection.SetProperty("find_multipaths", "no") | ||
assert.NoError(t, err) | ||
assert.Nil(t, config.SaveConfig(os.DevNull)) | ||
} |
Oops, something went wrong.