Skip to content

getistio fetch: add name flag in fetch #26

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

Merged
merged 9 commits into from
Mar 2, 2021
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
111 changes: 102 additions & 9 deletions cmd/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,24 @@ package cmd

import (
"fmt"
"strings"

"github.com/Masterminds/semver"
"github.com/spf13/cobra"

"github.com/tetratelabs/getistio/api"
"github.com/tetratelabs/getistio/src/istioctl"
"github.com/tetratelabs/getistio/src/manifest"
"github.com/tetratelabs/getistio/src/util/logger"
)

type fetchFlags struct {
name, version, flavor string
flavorVersion int64
}

func newFetchCmd(homedir string) *cobra.Command {
var (
flagVersion string
flagFlavor string
flagFlavorVersion int
)
var flag fetchFlags

cmd := &cobra.Command{
Use: "fetch",
Expand All @@ -47,6 +51,9 @@ $ getistio fetch --version 1.7 --flavor tetrate --flavor-version 0
# Fetch the istioctl of version=1.7.4 flavor=tetrate flavor-version=0
$ getistio fetch --version 1.7.4 --flavor tetrate --flavor-version 0

# Fetch the istioctl of version=1.7.4 flavor=tetrate flavor-version=0 using name
$ getistio fetch --name 1.7.4-tetrate-v0

# Fetch the latest istioctl of version=1.7.4 and flavor=tetratefips
$ getistio fetch --version 1.7.4 --flavor tetratefips

Expand Down Expand Up @@ -75,8 +82,12 @@ For more information, please refer to "getistio list --help" command.
if err != nil {
return fmt.Errorf("error fetching manifest: %v", err)
}
d, err := fetchParams(&flag, ms)
if err != nil {
return err
}

d, err := istioctl.Fetch(homedir, flagVersion, flagFlavor, flagFlavorVersion, ms)
err = istioctl.Fetch(homedir, d, ms)
if err != nil {
return err
}
Expand All @@ -97,8 +108,90 @@ For more information, please refer to "getistio list --help" command.

flags := cmd.Flags()
flags.SortFlags = false
flags.StringVarP(&flagVersion, "version", "", "", "Version of istioctl e.g. \"--version 1.7.4\"")
flags.StringVarP(&flagFlavor, "flavor", "", "", "Flavor of istioctl, e.g. \"--flavor tetrate\" or --flavor tetratefips\" or --flavor istio\"")
flags.IntVarP(&flagFlavorVersion, "flavor-version", "", -1, "Version of the flavor, e.g. \"--version 1\"")
flags.StringVarP(&flag.name, "name", "", "", "Name of distribution, e.g. 1.9.0-istio-v0")
flags.StringVarP(&flag.version, "version", "", "", "Version of istioctl e.g. \"--version 1.7.4\". When --name flag is set, this will not be used.")
flags.StringVarP(&flag.flavor, "flavor", "", "",
"Flavor of istioctl, e.g. \"--flavor tetrate\" or --flavor tetratefips\" or --flavor istio\". When --name flag is set, this will not be used.")
flags.Int64VarP(&flag.flavorVersion, "flavor-version", "", -1,
"Version of the flavor, e.g. \"--version 1\". When --name flag is set, this will not be used.")
return cmd
}

func fetchParams(flags *fetchFlags,
ms *api.Manifest) (*api.IstioDistribution, error) {
if len(flags.name) != 0 {
d, err := api.IstioDistributionFromString(flags.name)
if err != nil {
return nil, fmt.Errorf("cannot parse given name %s to istio distribution", flags.name)
}
return d, nil
}
if flags.flavor != api.IstioDistributionFlavorTetrate &&
flags.flavor != api.IstioDistributionFlavorTetrateFIPS &&
flags.flavor != api.IstioDistributionFlavorIstio {
flags.flavor = api.IstioDistributionFlavorTetrate
logger.Infof("fallback to the %s flavor since --flavor flag is not given or not supported\n", flags.flavor)
}
if len(flags.version) == 0 {
for _, m := range ms.IstioDistributions {
if m.Flavor == flags.flavor {
return m, nil
}
}
}

ret := &api.IstioDistribution{Version: flags.version, Flavor: flags.flavor, FlavorVersion: flags.flavorVersion}

if strings.Count(flags.version, ".") == 1 {
// In the case where patch version is not given,
// we find the latest patch version
var (
latest *api.IstioDistribution
prev *semver.Version
)

v, err := semver.NewVersion(flags.version)
if err != nil {
return nil, err
}

for _, d := range ms.IstioDistributions {
cur, err := semver.NewVersion(d.Version)
if err != nil {
return nil, err
}

if d.Flavor == ret.Flavor && cur.Minor() == v.Minor() && (prev == nil || cur.GreaterThan(prev)) {
prev = cur
latest = d
}
}

if latest == nil {
return nil, fmt.Errorf("invalid version %s", ret.Version)
}

ret.Version = latest.Version
logger.Infof("fallback to %s which is the latest patch version in the given verion minor %s\n",
ret.Version, flags.version)
}

if ret.FlavorVersion < 0 {
// search the latest flavor version in this flavor
var found bool
for _, m := range ms.IstioDistributions {
if m.Version == ret.Version && m.Flavor == ret.Flavor {
ret.FlavorVersion = m.FlavorVersion
found = true
break
}
}
if !found {
return nil, fmt.Errorf("unsupported version=%s and flavor=%s", ret.Version, ret.Flavor)
}
logger.Infof("fallback to the flavor %d version which is the latest one in %s-%s\n",
ret.FlavorVersion, ret.Version, ret.Flavor)
}

return ret, nil
}
150 changes: 150 additions & 0 deletions cmd/fetch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright 2021 Tetrate
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"

"github.com/tetratelabs/getistio/api"
)

func Test_fetchParams(t *testing.T) {
type tc struct {
flag *fetchFlags
mf *api.Manifest
exp *api.IstioDistribution
}

for i, c := range []tc{
{
// no args -> fall back to the latest tetrate flavor
flag: &fetchFlags{flavorVersion: -1},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
},
exp: &api.IstioDistribution{Version: "1.7.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
{
// all given
flag: &fetchFlags{version: "1.7.3", flavorVersion: 100, flavor: api.IstioDistributionFlavorTetrate},
exp: &api.IstioDistribution{Version: "1.7.3", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrate},
},
{
// given name
flag: &fetchFlags{name: "1.7.3-tetrate-v100"},
exp: &api.IstioDistribution{Version: "1.7.3", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrate},
},
{
// flavor not given
flag: &fetchFlags{version: "1.7.3", flavorVersion: 100},
exp: &api.IstioDistribution{Version: "1.7.3", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrate},
},
{
// flavorVersion not given -> fall back to the latest flavor version
flag: &fetchFlags{version: "1.7.3", flavor: api.IstioDistributionFlavorTetrateFIPS, flavorVersion: -1},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 50, Flavor: api.IstioDistributionFlavorTetrateFIPS},
{Version: "1.7.3", FlavorVersion: 10000000, Flavor: api.IstioDistributionFlavorTetrate},
},
},
exp: &api.IstioDistribution{Version: "1.7.3", FlavorVersion: 50, Flavor: api.IstioDistributionFlavorTetrateFIPS},
},
{
// version not given -> choose the latest version given flavor in manifest
flag: &fetchFlags{flavor: api.IstioDistributionFlavorIstio, flavorVersion: 0},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrateFIPS},
{Version: "1.8.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorIstio},
},
},
exp: &api.IstioDistribution{Version: "1.8.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorIstio},
},
{
// version and flavor version not given -> choose the latest version given flavor in manifest
flag: &fetchFlags{flavor: api.IstioDistributionFlavorIstio, flavorVersion: -1},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrateFIPS},
{Version: "1.8.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorIstio},
},
},
exp: &api.IstioDistribution{Version: "1.8.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorIstio},
},
{
// flavorVersion not given -> not found error
flag: &fetchFlags{version: "1.7.3", flavor: api.IstioDistributionFlavorTetrateFIPS, flavorVersion: -1},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 50, Flavor: api.IstioDistributionFlavorTetrate},
},
},
},
{
// flavor, flavorVersion not given -> fall back to the latest tetrate flavor
flag: &fetchFlags{version: "1.7.3", flavorVersion: -1},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrateFIPS},
{Version: "1.7.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
},
exp: &api.IstioDistribution{Version: "1.7.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
{
// patch version is not given in 'version', so should fallback to the latest patch version in the minor version
flag: &fetchFlags{version: "1.7", flavor: api.IstioDistributionFlavorTetrateFIPS, flavorVersion: -1},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.3", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrate},
{Version: "1.7.1", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrateFIPS},
{Version: "1.8.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
},
exp: &api.IstioDistribution{Version: "1.7.1", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrateFIPS},
},
{
// patch version is not given in 'version', so should fallback to the latest patch version in the minor version
flag: &fetchFlags{version: "1.7", flavorVersion: 0},
mf: &api.Manifest{
IstioDistributions: []*api.IstioDistribution{
{Version: "1.7.100", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrate},
{Version: "1.7.20", FlavorVersion: 20, Flavor: api.IstioDistributionFlavorTetrate},
{Version: "1.7.1", FlavorVersion: 1, Flavor: api.IstioDistributionFlavorTetrate},
{Version: "1.7.1", FlavorVersion: 100, Flavor: api.IstioDistributionFlavorTetrateFIPS},
{Version: "1.8.3", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
},
exp: &api.IstioDistribution{Version: "1.7.100", FlavorVersion: 0, Flavor: api.IstioDistributionFlavorTetrate},
},
} {
t.Run(fmt.Sprintf("%d-th case", i), func(t *testing.T) {
actual, err := fetchParams(c.flag, c.mf)
if c.exp == nil {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, c.exp, actual)
}
})

}
}
10 changes: 7 additions & 3 deletions doc/en/getistio-cli/reference/getistio_fetch/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ $ getistio fetch --version 1.7 --flavor tetrate --flavor-version 0
# Fetch the istioctl of version=1.7.4 flavor=tetrate flavor-version=0
$ getistio fetch --version 1.7.4 --flavor tetrate --flavor-version 0

# Fetch the istioctl of version=1.7.4 flavor=tetrate flavor-version=0 using name
$ getistio fetch --name 1.7.4-tetrate-v0

# Fetch the latest istioctl of version=1.7.4 and flavor=tetratefips
$ getistio fetch --version 1.7.4 --flavor tetratefips

Expand Down Expand Up @@ -52,9 +55,10 @@ For more information, please refer to "getistio list --help" command.
#### Options

```
--version string Version of istioctl e.g. "--version 1.7.4"
--flavor string Flavor of istioctl, e.g. "--flavor tetrate" or --flavor tetratefips" or --flavor istio"
--flavor-version int Version of the flavor, e.g. "--version 1" (default -1)
--name string Name of distribution, e.g. 1.9.0-istio-v0
--version string Version of istioctl e.g. "--version 1.7.4". When --name flag is set, this will not be used.
--flavor string Flavor of istioctl, e.g. "--flavor tetrate" or --flavor tetratefips" or --flavor istio". When --name flag is set, this will not be used.
--flavor-version int Version of the flavor, e.g. "--version 1". When --name flag is set, this will not be used. (default -1)
-h, --help help for fetch
```

Expand Down
Loading