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

Fix name argument for scale nodegroup #2417

Merged
merged 4 commits into from
Jul 10, 2020
Merged
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
8 changes: 4 additions & 4 deletions pkg/ctl/cmdutils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Cmd struct {

ClusterConfigFile string

ProviderConfig *api.ProviderConfig
ProviderConfig api.ProviderConfig
ClusterConfig *api.ClusterConfig

Include, Exclude []string
Expand Down Expand Up @@ -58,10 +58,10 @@ func (c *Cmd) NewCtl() (*eks.ClusterProvider, error) {
}
}

ctl := eks.New(c.ProviderConfig, c.ClusterConfig)
ctl := eks.New(&c.ProviderConfig, c.ClusterConfig)

if !ctl.IsSupportedRegion() {
return nil, ErrUnsupportedRegion(c.ProviderConfig)
return nil, ErrUnsupportedRegion(&c.ProviderConfig)
}

return ctl, nil
Expand All @@ -71,7 +71,7 @@ func (c *Cmd) NewCtl() (*eks.ClusterProvider, error) {
func AddResourceCmd(flagGrouping *FlagGrouping, parentVerbCmd *cobra.Command, newCmd func(*Cmd)) {
c := &Cmd{
CobraCommand: &cobra.Command{},
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},

Plan: true, // always on by default
Wait: false, // varies in some commands
Expand Down
19 changes: 8 additions & 11 deletions pkg/ctl/cmdutils/configfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,22 @@ type commonClusterConfigLoader struct {
flagsIncompatibleWithoutConfigFile sets.String
validateWithConfigFile func() error
validateWithoutConfigFile func() error
nameArgumentAllowed bool
}

var (
defaultFlagsIncompatibleWithConfigFile = sets.NewString(
defaultFlagsIncompatibleWithConfigFile = [...]string{
"name",
"region",
"version",
"cluster",
"namepace",
)
defaultFlagsIncompatibleWithoutConfigFile = sets.NewString(
}
defaultFlagsIncompatibleWithoutConfigFile = [...]string{
"only",
"include",
"exclude",
"only-missing",
)
}
)

func newCommonClusterConfigLoader(cmd *Cmd) *commonClusterConfigLoader {
Expand All @@ -58,9 +57,9 @@ func newCommonClusterConfigLoader(cmd *Cmd) *commonClusterConfigLoader {
Cmd: cmd,

validateWithConfigFile: nilValidatorFunc,
flagsIncompatibleWithConfigFile: defaultFlagsIncompatibleWithConfigFile,
flagsIncompatibleWithConfigFile: sets.NewString(defaultFlagsIncompatibleWithConfigFile[:]...),
validateWithoutConfigFile: nilValidatorFunc,
flagsIncompatibleWithoutConfigFile: defaultFlagsIncompatibleWithoutConfigFile,
flagsIncompatibleWithoutConfigFile: sets.NewString(defaultFlagsIncompatibleWithoutConfigFile[:]...),
}
}

Expand Down Expand Up @@ -99,10 +98,8 @@ func (l *commonClusterConfigLoader) Load() error {
}
}

if !l.nameArgumentAllowed {
if l.NameArg != "" {
return ErrCannotUseWithConfigFile(fmt.Sprintf("name argument %q", l.NameArg))
}
if l.flagsIncompatibleWithConfigFile.Has("name") && l.NameArg != "" {
return ErrCannotUseWithConfigFile("name argument")
}

if meta.Name == "" {
Expand Down
56 changes: 48 additions & 8 deletions pkg/ctl/cmdutils/configfile_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmdutils_test
package cmdutils

import (
"path/filepath"
Expand All @@ -8,7 +8,6 @@ import (
"github.com/spf13/cobra"

api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
. "github.com/weaveworks/eksctl/pkg/ctl/cmdutils"
"github.com/weaveworks/eksctl/pkg/ctl/cmdutils/filter"
)

Expand Down Expand Up @@ -63,7 +62,7 @@ var _ = Describe("cmdutils configfile", func() {

err := NewMetadataLoader(cmd).Load()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal(ErrCannotUseWithConfigFile(`name argument "foo-3"`).Error()))
Expect(err.Error()).To(Equal(ErrCannotUseWithConfigFile(`name argument`).Error()))

fs := cmd.CobraCommand.Flags()

Expand All @@ -79,6 +78,47 @@ var _ = Describe("cmdutils configfile", func() {
}
})

Describe("name argument", func() {
When("given as --name switch", func() {
It("succeeds", func() {
cfg := api.NewClusterConfig()
cobraCmd := newCmd()
name := "foo-2"
cobraCmd.SetArgs([]string{"--name", name})

cmd := &Cmd{
ClusterConfig: cfg,
NameArg: name,
CobraCommand: cobraCmd,
ClusterConfigFile: examplesDir + "01-simple-cluster.yaml",
ProviderConfig: api.ProviderConfig{},
}
l := newCommonClusterConfigLoader(cmd)
l.flagsIncompatibleWithConfigFile.Delete("name")

err := l.Load()
Expect(err).ToNot(HaveOccurred())
})
})
When("given as positional argument", func() {
It("succeeds", func() {
cfg := api.NewClusterConfig()
cmd := &Cmd{
ClusterConfig: cfg,
NameArg: "foo-2",
CobraCommand: newCmd(),
ClusterConfigFile: examplesDir + "01-simple-cluster.yaml",
ProviderConfig: api.ProviderConfig{},
}
l := newCommonClusterConfigLoader(cmd)
l.flagsIncompatibleWithConfigFile.Delete("name")

err := l.Load()
Expect(err).ToNot(HaveOccurred())
})
})
})

It("load all of example file", func() {
examples, err := filepath.Glob(examplesDir + "*.yaml")
Expect(err).ToNot(HaveOccurred())
Expand All @@ -89,7 +129,7 @@ var _ = Describe("cmdutils configfile", func() {
CobraCommand: newCmd(),
ClusterConfigFile: example,
ClusterConfig: api.NewClusterConfig(),
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},
}

err := NewMetadataLoader(cmd).Load()
Expand Down Expand Up @@ -122,7 +162,7 @@ var _ = Describe("cmdutils configfile", func() {
CobraCommand: newCmd(),
ClusterConfigFile: filepath.Join(examplesDir, natTest.configFile),
ClusterConfig: api.NewClusterConfig(),
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},
}

params := &CreateClusterCmdParams{WithoutNodeGroup: true, Managed: false}
Expand Down Expand Up @@ -172,7 +212,7 @@ var _ = Describe("cmdutils configfile", func() {
cmd := &Cmd{
CobraCommand: newCmd(),
ClusterConfig: api.NewClusterConfig(),
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},
}

ngFilter := filter.NewNodeGroupFilter()
Expand Down Expand Up @@ -236,7 +276,7 @@ var _ = Describe("cmdutils configfile", func() {
CobraCommand: newCmd(),
ClusterConfigFile: filepath.Join(examplesDir, loaderTest.configFile),
ClusterConfig: api.NewClusterConfig(),
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},
}

ngFilter := filter.NewNodeGroupFilter()
Expand Down Expand Up @@ -270,7 +310,7 @@ var _ = Describe("cmdutils configfile", func() {
CobraCommand: newCmd(),
ClusterConfigFile: configFilePath,
ClusterConfig: api.NewClusterConfig(),
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},
}

params := &CreateClusterCmdParams{
Expand Down
2 changes: 1 addition & 1 deletion pkg/ctl/cmdutils/fargate.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func NewGetFargateProfileLoader(cmd *Cmd, options *fargate.Options) ClusterConfi

func flagsIncompatibleWithConfigFileExcept(items ...string) sets.String {
set := sets.NewString(fargateProfileFlagsIncompatibleWithConfigFile...)
set = set.Union(defaultFlagsIncompatibleWithConfigFile)
set = set.Union(sets.NewString(defaultFlagsIncompatibleWithConfigFile[:]...))
set.Delete(items...)
return set
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/ctl/cmdutils/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
// NewScaleNodeGroupLoader will load config or use flags for 'eksctl scale nodegroup'
func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroup) ClusterConfigLoader {
l := newCommonClusterConfigLoader(cmd)
l.nameArgumentAllowed = true

l.flagsIncompatibleWithConfigFile.Insert(
"nodes",
"nodes-min",
"nodes-max",
)
l.flagsIncompatibleWithConfigFile.Delete("name")

l.validateWithConfigFile = func() error {
if err := validateNameArgument(cmd, ng); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/ctl/cmdutils/scale_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var _ = Describe("scale node group config file loader", func() {
CobraCommand: newCmd(),
ClusterConfigFile: "test_data/scale-ng-test.yaml",
ClusterConfig: api.NewClusterConfig(),
ProviderConfig: &api.ProviderConfig{},
ProviderConfig: api.ProviderConfig{},
NameArg: params.name,
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/create/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C
cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) {
fs.StringVarP(&cfg.Metadata.Name, "name", "n", "", fmt.Sprintf("EKS cluster name (generated if unspecified, e.g. %q)", exampleClusterName))
cmdutils.AddStringToStringVarPFlag(fs, &cfg.Metadata.Tags, "tags", "", map[string]string{}, "Used to tag the AWS resources")
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
fs.StringSliceVar(&params.AvailabilityZones, "zones", nil, "(auto-select if unspecified)")
cmdutils.AddVersionFlag(fs, cfg.Metadata, "")
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
Expand Down Expand Up @@ -82,7 +82,7 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C
fs.StringVar(cfg.VPC.NAT.Gateway, "vpc-nat-mode", api.ClusterSingleNAT, "VPC NAT mode, valid options: HighlyAvailable, Single, Disable")
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, true)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true)

cmd.FlagSetGroup.InFlagSet("Output kubeconfig", func(fs *pflag.FlagSet) {
cmdutils.AddCommonFlagsForKubeconfig(fs, &params.KubeconfigPath, &params.AuthenticatorRoleARN, &params.SetContext, &params.AutoKubeconfigPath, exampleClusterName)
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/create/fargate.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ func configureCreateFargateProfileCmd(cmd *cmdutils.Cmd) *fargate.CreateOptions
})
cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) {
cmdutils.AddClusterFlag(fs, cmd.ClusterConfig.Metadata)
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, false)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false)
return &options
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/create/iamidentitymapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ func createIAMIdentityMappingCmd(cmd *cmdutils.Cmd) {
fs.StringArrayVar(&groups, "group", []string{}, "Group within Kubernetes to which IAM role is mapped")
cmdutils.AddIAMIdentityMappingARNFlags(fs, cmd, &arn)
cmdutils.AddClusterFlagWithDeprecated(fs, cfg.Metadata)
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, false)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false)
}

func doCreateIAMIdentityMapping(cmd *cmdutils.Cmd, arn string, username string, groups []string) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/create/iamserviceaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ func createIAMServiceAccountCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *

cmdutils.AddIAMServiceAccountFilterFlags(fs, &cmd.Include, &cmd.Exclude)
cmdutils.AddApproveFlag(fs, cmd)
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, true)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true)
}

func doCreateIAMServiceAccount(cmd *cmdutils.Cmd, overrideExistingServiceAccounts bool) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/create/nodegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func createNodeGroupCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils
cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) {
fs.StringVar(&cfg.Metadata.Name, "cluster", "", "name of the EKS cluster to add the nodegroup to")
cmdutils.AddStringToStringVarPFlag(fs, &cfg.Metadata.Tags, "tags", "", map[string]string{}, "Used to tag the AWS resources")
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddVersionFlag(fs, cfg.Metadata, `for nodegroups "auto" and "latest" can be used to automatically inherit version from the control plane or force latest`)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddNodeGroupFilterFlags(fs, &cmd.Include, &cmd.Exclude)
Expand All @@ -72,7 +72,7 @@ func createNodeGroupCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils
fs.BoolVarP(&params.installNeuronDevicePlugin, "install-neuron-plugin", "", true, "Install Neuron plugin for Inferentia nodes")
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, true)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true)
}

func doCreateNodeGroups(cmd *cmdutils.Cmd, ng *api.NodeGroup, params createNodeGroupParams) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/delete/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func deleteClusterCmd(cmd *cmdutils.Cmd) {

cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) {
fs.StringVarP(&cfg.Metadata.Name, "name", "n", "", "EKS cluster name")
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)

cmd.Wait = false
cmdutils.AddWaitFlag(fs, &cmd.Wait, "deletion of all resources")
Expand All @@ -47,7 +47,7 @@ func deleteClusterCmd(cmd *cmdutils.Cmd) {
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, true)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true)
}

func handleErrors(errs []error, subject string) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/delete/fargate.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ func configureDeleteFargateProfileCmd(cmd *cmdutils.Cmd) *fargate.Options {
})
cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) {
cmdutils.AddClusterFlag(fs, cmd.ClusterConfig.Metadata)
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddWaitFlag(fs, &cmd.Wait, "wait for the deletion of the Fargate profile, which may take from a couple seconds to a couple minutes.")
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, false)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false)
return &opts
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/delete/iamidentitymapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ func deleteIAMIdentityMappingCmd(cmd *cmdutils.Cmd) {
fs.BoolVar(&all, "all", false, "Delete all matching mappings instead of just one")
cmdutils.AddIAMIdentityMappingARNFlags(fs, cmd, &arn)
cmdutils.AddClusterFlagWithDeprecated(fs, cfg.Metadata)
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, false)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false)
}

func doDeleteIAMIdentityMapping(cmd *cmdutils.Cmd, arn string, all bool) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/delete/iamserviceaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ func deleteIAMServiceAccountCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *
cmdutils.AddIAMServiceAccountFilterFlags(fs, &cmd.Include, &cmd.Exclude)
fs.BoolVar(&onlyMissing, "only-missing", false, "Only delete nodegroups that are not defined in the given config file")
cmdutils.AddApproveFlag(fs, cmd)
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)

cmd.Wait = false
cmdutils.AddWaitFlag(fs, &cmd.Wait, "deletion of all resources")
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, true)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true)
}

func doDeleteIAMServiceAccount(cmd *cmdutils.Cmd, serviceAccount *api.ClusterIAMServiceAccount, onlyMissing bool) error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ctl/delete/nodegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func deleteNodeGroupWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cm

cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) {
fs.StringVar(&cfg.Metadata.Name, "cluster", "", "EKS cluster name")
cmdutils.AddRegionFlag(fs, cmd.ProviderConfig)
cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig)
fs.StringVarP(&ng.Name, "name", "n", "", "Name of the nodegroup to delete")
cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile)
cmdutils.AddApproveFlag(fs, cmd)
Expand All @@ -48,7 +48,7 @@ func deleteNodeGroupWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cm
cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout)
})

cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, cmd.ProviderConfig, true)
cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true)
}

func doDeleteNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroup, updateAuthConfigMap, deleteNodeGroupDrain, onlyMissing bool) error {
Expand Down
Loading