1/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package types
18
19import (
20	"fmt"
21	"regexp"
22	"sort"
23	"strings"
24
25	"k8s.io/gengo/namer"
26)
27
28// ToGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
29// if it cannot parse the string.
30func ToGroupVersion(gv string) (GroupVersion, error) {
31	// this can be the internal version for the legacy kube types
32	// TODO once we've cleared the last uses as strings, this special case should be removed.
33	if (len(gv) == 0) || (gv == "/") {
34		return GroupVersion{}, nil
35	}
36
37	switch strings.Count(gv, "/") {
38	case 0:
39		return GroupVersion{Group(gv), ""}, nil
40	case 1:
41		i := strings.Index(gv, "/")
42		return GroupVersion{Group(gv[:i]), Version(gv[i+1:])}, nil
43	default:
44		return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv)
45	}
46}
47
48type sortableSliceOfVersions []string
49
50func (a sortableSliceOfVersions) Len() int      { return len(a) }
51func (a sortableSliceOfVersions) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
52func (a sortableSliceOfVersions) Less(i, j int) bool {
53	vi, vj := strings.TrimLeft(a[i], "v"), strings.TrimLeft(a[j], "v")
54	major := regexp.MustCompile("^[0-9]+")
55	viMajor, vjMajor := major.FindString(vi), major.FindString(vj)
56	viRemaining, vjRemaining := strings.TrimLeft(vi, viMajor), strings.TrimLeft(vj, vjMajor)
57	switch {
58	case len(viRemaining) == 0 && len(vjRemaining) == 0:
59		return viMajor < vjMajor
60	case len(viRemaining) == 0 && len(vjRemaining) != 0:
61		// stable version is greater than unstable version
62		return false
63	case len(viRemaining) != 0 && len(vjRemaining) == 0:
64		// stable version is greater than unstable version
65		return true
66	}
67	// neither are stable versions
68	if viMajor != vjMajor {
69		return viMajor < vjMajor
70	}
71	// assuming at most we have one alpha or one beta version, so if vi contains "alpha", it's the lesser one.
72	return strings.Contains(viRemaining, "alpha")
73}
74
75// Determine the default version among versions. If a user calls a group client
76// without specifying the version (e.g., c.CoreV1(), instead of c.CoreV1()), the
77// default version will be returned.
78func defaultVersion(versions []PackageVersion) Version {
79	var versionStrings []string
80	for _, version := range versions {
81		versionStrings = append(versionStrings, version.Version.String())
82	}
83	sort.Sort(sortableSliceOfVersions(versionStrings))
84	return Version(versionStrings[len(versionStrings)-1])
85}
86
87// ToGroupVersionInfo is a helper function used by generators for groups.
88func ToGroupVersionInfo(groups []GroupVersions, groupGoNames map[GroupVersion]string) []GroupVersionInfo {
89	var groupVersionPackages []GroupVersionInfo
90	for _, group := range groups {
91		for _, version := range group.Versions {
92			groupGoName := groupGoNames[GroupVersion{Group: group.Group, Version: version.Version}]
93			groupVersionPackages = append(groupVersionPackages, GroupVersionInfo{
94				Group:                Group(namer.IC(group.Group.NonEmpty())),
95				Version:              Version(namer.IC(version.Version.String())),
96				PackageAlias:         strings.ToLower(groupGoName + version.Version.NonEmpty()),
97				GroupGoName:          groupGoName,
98				LowerCaseGroupGoName: namer.IL(groupGoName),
99			})
100		}
101	}
102	return groupVersionPackages
103}
104
105func ToGroupInstallPackages(groups []GroupVersions, groupGoNames map[GroupVersion]string) []GroupInstallPackage {
106	var groupInstallPackages []GroupInstallPackage
107	for _, group := range groups {
108		defaultVersion := defaultVersion(group.Versions)
109		groupGoName := groupGoNames[GroupVersion{Group: group.Group, Version: defaultVersion}]
110		groupInstallPackages = append(groupInstallPackages, GroupInstallPackage{
111			Group:               Group(namer.IC(group.Group.NonEmpty())),
112			InstallPackageAlias: strings.ToLower(groupGoName),
113		})
114	}
115	return groupInstallPackages
116}
117
118// NormalizeGroupVersion calls normalizes the GroupVersion.
119//func NormalizeGroupVersion(gv GroupVersion) GroupVersion {
120//	return GroupVersion{Group: gv.Group.NonEmpty(), Version: gv.Version, NonEmptyVersion: normalization.Version(gv.Version)}
121//}
122