@@ -17,17 +17,41 @@ limitations under the License.
17
17
package cmd
18
18
19
19
import (
20
+ "fmt"
20
21
"os"
22
+ "path/filepath"
21
23
22
24
"github.com/pkg/errors"
23
25
"github.com/spf13/cobra"
26
+ "k8s.io/apimachinery/pkg/runtime"
24
27
25
28
"sigs.k8s.io/cluster-api-provider-vsphere/packaging/flavorgen/flavors"
26
29
"sigs.k8s.io/cluster-api-provider-vsphere/packaging/flavorgen/flavors/env"
27
30
"sigs.k8s.io/cluster-api-provider-vsphere/packaging/flavorgen/flavors/util"
28
31
)
29
32
30
33
const flavorFlag = "flavor"
34
+ const outputDirFlag = "output-dir"
35
+
36
+ var (
37
+ flavorMappings = map [string ]string {
38
+ flavors .VIP : "cluster-template.yaml" ,
39
+ flavors .ExternalLoadBalancer : "cluster-template-external-loadbalancer.yaml" ,
40
+ flavors .ClusterClass : "clusterclass-template.yaml" ,
41
+ flavors .ClusterTopology : "cluster-template-topology.yaml" ,
42
+ flavors .Ignition : "cluster-template-ignition.yaml" ,
43
+ flavors .NodeIPAM : "cluster-template-node-ipam.yaml" ,
44
+ }
45
+
46
+ allFlavors = []string {
47
+ flavors .VIP ,
48
+ flavors .ExternalLoadBalancer ,
49
+ flavors .ClusterClass ,
50
+ flavors .Ignition ,
51
+ flavors .NodeIPAM ,
52
+ flavors .ClusterTopology ,
53
+ }
54
+ )
31
55
32
56
func RootCmd () * cobra.Command {
33
57
rootCmd := & cobra.Command {
@@ -36,8 +60,11 @@ func RootCmd() *cobra.Command {
36
60
RunE : func (command * cobra.Command , args []string ) error {
37
61
return RunRoot (command )
38
62
},
63
+ SilenceUsage : true ,
39
64
}
40
65
rootCmd .Flags ().StringP (flavorFlag , "f" , "" , "Name of flavor to compile" )
66
+ rootCmd .Flags ().StringP (outputDirFlag , "o" , "" , "Directory to store the generated flavor templates.\n By default the current directory is used.\n Use '-' to output the result to stdout." )
67
+
41
68
return rootCmd
42
69
}
43
70
@@ -52,30 +79,73 @@ func RunRoot(command *cobra.Command) error {
52
79
if err != nil {
53
80
return errors .Wrapf (err , "error accessing flag %s for command %s" , flavorFlag , command .Name ())
54
81
}
82
+ outputDir , err := command .Flags ().GetString (outputDirFlag )
83
+ if err != nil {
84
+ return errors .Wrapf (err , "error accessing flag %s for command %s" , outputDirFlag , command .Name ())
85
+ }
86
+ var outputFlavors []string
87
+ if flavor != "" {
88
+ outputFlavors = append (outputFlavors , flavor )
89
+ } else {
90
+ outputFlavors = allFlavors
91
+ }
92
+ generateMultiFlavors := len (outputFlavors ) > 1
93
+ for _ , f := range outputFlavors {
94
+ manifest , err := generateSingle (f )
95
+ if err != nil {
96
+ return err
97
+ }
98
+
99
+ yamlFileName , ok := flavorMappings [f ]
100
+ if ! ok {
101
+ return fmt .Errorf ("file mapping for flavor %q is missng in flavorMappings" , f )
102
+ }
103
+
104
+ if outputDir == "-" {
105
+ if generateMultiFlavors {
106
+ // use the yaml filename as a section delimiter
107
+ fmt .Printf ("### %s\n " , yamlFileName )
108
+ }
109
+ fmt .Print (manifest )
110
+ continue
111
+ }
112
+
113
+ yamlPath := filepath .Join (outputDir , yamlFileName )
114
+ err = os .WriteFile (yamlPath , []byte (manifest ), 0600 )
115
+ if err != nil {
116
+ return errors .Wrapf (err , "failed to save manifest content to file for flavor %s" , f )
117
+ }
118
+ }
119
+
120
+ return nil
121
+ }
122
+
123
+ func generateSingle (flavor string ) (string , error ) {
124
+ replacements := append ([]util.Replacement {}, util .DefaultReplacements ... )
125
+
126
+ var objs []runtime.Object
55
127
switch flavor {
56
128
case flavors .VIP :
57
- util . PrintObjects ( flavors .MultiNodeTemplateWithKubeVIP () )
129
+ objs = flavors .MultiNodeTemplateWithKubeVIP ()
58
130
case flavors .ExternalLoadBalancer :
59
- util . PrintObjects ( flavors .MultiNodeTemplateWithExternalLoadBalancer () )
131
+ objs = flavors .MultiNodeTemplateWithExternalLoadBalancer ()
60
132
case flavors .ClusterClass :
61
- util . PrintObjects ( flavors .ClusterClassTemplateWithKubeVIP () )
133
+ objs = flavors .ClusterClassTemplateWithKubeVIP ()
62
134
case flavors .ClusterTopology :
63
- additionalReplacements := []util.Replacement {
64
- {
65
- Kind : "Cluster" ,
66
- Name : "${CLUSTER_NAME}" ,
67
- Value : env .ControlPlaneMachineCountVar ,
68
- FieldPath : []string {"spec" , "topology" , "controlPlane" , "replicas" },
69
- },
70
- }
71
- util .Replacements = append (util .Replacements , additionalReplacements ... )
72
- util .PrintObjects (flavors .ClusterTopologyTemplateKubeVIP ())
135
+ objs = flavors .ClusterTopologyTemplateKubeVIP ()
136
+ replacements = append (replacements , util.Replacement {
137
+ Kind : "Cluster" ,
138
+ Name : "${CLUSTER_NAME}" ,
139
+ Value : env .ControlPlaneMachineCountVar ,
140
+ FieldPath : []string {"spec" , "topology" , "controlPlane" , "replicas" },
141
+ })
73
142
case flavors .Ignition :
74
- util . PrintObjects ( flavors .MultiNodeTemplateWithKubeVIPIgnition () )
143
+ objs = flavors .MultiNodeTemplateWithKubeVIPIgnition ()
75
144
case flavors .NodeIPAM :
76
- util . PrintObjects ( flavors .MultiNodeTemplateWithKubeVIPNodeIPAM () )
145
+ objs = flavors .MultiNodeTemplateWithKubeVIPNodeIPAM ()
77
146
default :
78
- return errors .Errorf ("invalid flavor" )
147
+ return "" , errors .Errorf ("invalid flavor" )
79
148
}
80
- return nil
149
+
150
+ return util .GenerateManifestYaml (objs , replacements ), nil
81
151
}
0 commit comments