github.com/bmoylan/distgo@v1.18.0/cmd/root.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "io/ioutil" 19 "os" 20 "time" 21 22 godelconfig "github.com/palantir/godel/framework/godel/config" 23 "github.com/palantir/godel/framework/pluginapi" 24 "github.com/palantir/pkg/cobracli" 25 "github.com/pkg/errors" 26 "github.com/spf13/cobra" 27 "gopkg.in/yaml.v2" 28 29 "github.com/palantir/distgo/assetapi" 30 "github.com/palantir/distgo/dister" 31 "github.com/palantir/distgo/dister/disterfactory" 32 "github.com/palantir/distgo/distgo" 33 "github.com/palantir/distgo/distgo/config" 34 "github.com/palantir/distgo/dockerbuilder" 35 "github.com/palantir/distgo/dockerbuilder/dockerbuilderfactory" 36 "github.com/palantir/distgo/projectversioner/projectversionerfactory" 37 "github.com/palantir/distgo/publisher" 38 "github.com/palantir/distgo/publisher/publisherfactory" 39 ) 40 41 var ( 42 debugFlagVal bool 43 projectDirFlagVal string 44 distgoConfigFileFlagVal string 45 godelConfigFileFlagVal string 46 assetsFlagVal []string 47 48 cliProjectVersionerFactory distgo.ProjectVersionerFactory 49 cliDisterFactory distgo.DisterFactory 50 cliDefaultDisterCfg config.DisterConfig 51 cliDockerBuilderFactory distgo.DockerBuilderFactory 52 cliPublisherFactory distgo.PublisherFactory 53 ) 54 55 var rootCmd = &cobra.Command{ 56 Use: "distgo", 57 } 58 59 func Execute() int { 60 return cobracli.ExecuteWithDebugVarAndDefaultParams(rootCmd, &debugFlagVal) 61 } 62 63 func restoreRootFlagsFn() func() { 64 origProjectDirFlagVal := projectDirFlagVal 65 origDistgoConfigFileFlagVal := distgoConfigFileFlagVal 66 origGodelConfigFileFlagVal := godelConfigFileFlagVal 67 origAssetsFlagVal := assetsFlagVal 68 return func() { 69 projectDirFlagVal = origProjectDirFlagVal 70 distgoConfigFileFlagVal = origDistgoConfigFileFlagVal 71 godelConfigFileFlagVal = origGodelConfigFileFlagVal 72 assetsFlagVal = origAssetsFlagVal 73 } 74 } 75 76 func InitAssetCmds(args []string) error { 77 restoreFn := restoreRootFlagsFn() 78 // parse the flags to retrieve the value of the "--assets" flag. Ignore any errors that occur in flag parsing so 79 // that, if provided flags are invalid, the regular logic handles the error printing. 80 _ = rootCmd.ParseFlags(args) 81 allAssets, err := assetapi.LoadAssets(assetsFlagVal) 82 // restore the root flags to undo any parsing done by rootCmd.ParseFlags 83 restoreFn() 84 if err != nil { 85 return err 86 } 87 88 // load publisher assets 89 assetPublishers, upgraderPublishers, err := publisher.AssetPublisherCreators(allAssets[assetapi.Publisher]...) 90 if err != nil { 91 return err 92 } 93 94 cliPublisherFactory, err = publisherfactory.New(assetPublishers, upgraderPublishers) 95 if err != nil { 96 return err 97 } 98 99 publisherTypeNames := cliPublisherFactory.Types() 100 var publishers []distgo.Publisher 101 for _, typeName := range publisherTypeNames { 102 publisher, err := cliPublisherFactory.NewPublisher(typeName) 103 if err != nil { 104 return errors.Wrapf(err, "failed to create publisher %q", typeName) 105 } 106 publishers = append(publishers, publisher) 107 } 108 109 // add publish commands based on assets 110 addPublishSubcommands(publisherTypeNames, publishers) 111 112 return nil 113 } 114 115 func init() { 116 pluginapi.AddDebugPFlagPtr(rootCmd.PersistentFlags(), &debugFlagVal) 117 pluginapi.AddProjectDirPFlagPtr(rootCmd.PersistentFlags(), &projectDirFlagVal) 118 pluginapi.AddConfigPFlagPtr(rootCmd.PersistentFlags(), &distgoConfigFileFlagVal) 119 pluginapi.AddGodelConfigPFlagPtr(rootCmd.PersistentFlags(), &godelConfigFileFlagVal) 120 pluginapi.AddAssetsPFlagPtr(rootCmd.PersistentFlags(), &assetsFlagVal) 121 122 rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { 123 allAssets, err := assetapi.LoadAssets(assetsFlagVal) 124 if err != nil { 125 return err 126 } 127 128 // parameters will become non-nil if/when support for projectversioner assets are added 129 cliProjectVersionerFactory, err = projectversionerfactory.New(nil, nil) 130 if err != nil { 131 return err 132 } 133 134 assetDisters, upgraderDisters, err := dister.AssetDisterCreators(allAssets[assetapi.Dister]...) 135 if err != nil { 136 return err 137 } 138 cliDisterFactory, err = disterfactory.New(assetDisters, upgraderDisters) 139 if err != nil { 140 return err 141 } 142 143 cliDefaultDisterCfg, err = disterfactory.DefaultConfig() 144 if err != nil { 145 return err 146 } 147 148 assetDockerBuilders, upgraderDockerBuilders, err := dockerbuilder.AssetDockerBuilderCreators(allAssets[assetapi.DockerBuilder]...) 149 if err != nil { 150 return err 151 } 152 cliDockerBuilderFactory, err = dockerbuilderfactory.New(assetDockerBuilders, upgraderDockerBuilders) 153 if err != nil { 154 return err 155 } 156 157 return nil 158 } 159 } 160 161 func distgoProjectParamFromFlags() (distgo.ProjectInfo, distgo.ProjectParam, error) { 162 return distgoProjectParamFromVals(projectDirFlagVal, distgoConfigFileFlagVal, godelConfigFileFlagVal, cliProjectVersionerFactory, cliDisterFactory, cliDefaultDisterCfg, cliDockerBuilderFactory, cliPublisherFactory) 163 } 164 165 func distgoConfigModTime() *time.Time { 166 if distgoConfigFileFlagVal == "" { 167 return nil 168 } 169 fi, err := os.Stat(distgoConfigFileFlagVal) 170 if err != nil { 171 return nil 172 } 173 modTime := fi.ModTime() 174 return &modTime 175 } 176 177 func distgoProjectParamFromVals(projectDir, distgoConfigFile, godelConfigFile string, projectVersionerFactory distgo.ProjectVersionerFactory, disterFactory distgo.DisterFactory, defaultDisterCfg config.DisterConfig, dockerBuilderFactory distgo.DockerBuilderFactory, publisherFactory distgo.PublisherFactory) (distgo.ProjectInfo, distgo.ProjectParam, error) { 178 var distgoCfg config.ProjectConfig 179 if distgoConfigFile != "" { 180 cfg, err := loadConfigFromFile(distgoConfigFile) 181 if err != nil { 182 return distgo.ProjectInfo{}, distgo.ProjectParam{}, err 183 } 184 distgoCfg = cfg 185 } 186 if godelConfigFile != "" { 187 excludes, err := godelconfig.ReadGodelConfigExcludesFromFile(godelConfigFile) 188 if err != nil { 189 return distgo.ProjectInfo{}, distgo.ProjectParam{}, err 190 } 191 distgoCfg.Exclude.Add(excludes) 192 } 193 projectParam, err := distgoCfg.ToParam(projectDir, projectVersionerFactory, disterFactory, defaultDisterCfg, dockerBuilderFactory, publisherFactory) 194 if err != nil { 195 return distgo.ProjectInfo{}, distgo.ProjectParam{}, err 196 } 197 projectInfo, err := projectParam.ProjectInfo(projectDirFlagVal) 198 if err != nil { 199 return distgo.ProjectInfo{}, distgo.ProjectParam{}, err 200 } 201 return projectInfo, projectParam, nil 202 } 203 204 func loadConfigFromFile(cfgFile string) (config.ProjectConfig, error) { 205 cfgBytes, err := ioutil.ReadFile(cfgFile) 206 if os.IsNotExist(err) { 207 return config.ProjectConfig{}, nil 208 } 209 if err != nil { 210 return config.ProjectConfig{}, errors.Wrapf(err, "failed to read configuration file") 211 } 212 upgradedCfgBytes, err := config.UpgradeConfig(cfgBytes, cliProjectVersionerFactory, cliDisterFactory, cliDockerBuilderFactory, cliPublisherFactory) 213 if err != nil { 214 return config.ProjectConfig{}, errors.Wrapf(err, "failed to upgrade configuration") 215 } 216 217 var cfg config.ProjectConfig 218 if err := yaml.Unmarshal(upgradedCfgBytes, &cfg); err != nil { 219 return config.ProjectConfig{}, errors.Wrapf(err, "failed to unmarshal configuration") 220 } 221 return cfg, nil 222 }