func NewPluginConfig(errorHandler func(error)) *PluginConfig { pluginPath := filepath.Join(confighelpers.PluginRepoDir(), ".cf", "plugins") return &PluginConfig{ data: NewData(), mutex: new(sync.RWMutex), initOnce: new(sync.Once), persistor: configuration.NewDiskPersistor(filepath.Join(pluginPath, "config.json")), onError: errorHandler, pluginPath: pluginPath, } }
func NewRepositoryFromFilepath(filepath string, errorHandler func(error)) Repository { if errorHandler == nil { return nil } return NewRepositoryFromPersistor(configuration.NewDiskPersistor(filepath), errorHandler) }
func Main(traceEnv string, args []string) { //handle `cf -v` for cf version if len(args) == 2 && (args[1] == "-v" || args[1] == "--version") { args[1] = "version" } //handles `cf` if len(args) == 1 { args = []string{args[0], "help"} } //handles `cf [COMMAND] -h ...` //rearrange args to `cf help COMMAND` and let `command help` to print out usage args = append([]string{args[0]}, handleHelp(args[1:])...) newArgs, isVerbose := handleVerbose(args) args = newArgs errFunc := func(err error) { if err != nil { ui := terminal.NewUI( os.Stdin, Writer, terminal.NewTeePrinter(Writer), trace.NewLogger(Writer, isVerbose, traceEnv, ""), ) ui.Failed(fmt.Sprintf("Config error: %s", err)) } } // Only used to get Trace, so our errorHandler doesn't matter, since it's not used configPath, err := confighelpers.DefaultFilePath() if err != nil { errFunc(err) } config := coreconfig.NewRepositoryFromFilepath(configPath, errFunc) defer config.Close() traceConfigVal := config.Trace() // Writer is assigned in writer_unix.go/writer_windows.go traceLogger := trace.NewLogger(Writer, isVerbose, traceEnv, traceConfigVal) deps := commandregistry.NewDependency(Writer, traceLogger, os.Getenv("CF_DIAL_TIMEOUT")) defer handlePanics(args, deps.TeePrinter, deps.Logger) defer deps.Config.Close() //handle `cf --build` if len(args) == 2 && (args[1] == "--build" || args[1] == "-b") { deps.UI.Say(T("{{.CFName}} was built with Go version: {{.GoVersion}}", map[string]interface{}{ "CFName": args[0], "GoVersion": runtime.Version(), })) os.Exit(0) } warningProducers := []net.WarningProducer{} for _, warningProducer := range deps.Gateways { warningProducers = append(warningProducers, warningProducer) } warningsCollector := net.NewWarningsCollector(deps.UI, warningProducers...) commandsloader.Load() //run core command cmdName := args[1] cmd := cmdRegistry.FindCommand(cmdName) if cmd != nil { meta := cmd.MetaData() flagContext := flags.NewFlagContext(meta.Flags) flagContext.SkipFlagParsing(meta.SkipFlagParsing) cmdArgs := args[2:] err = flagContext.Parse(cmdArgs...) if err != nil { usage := cmdRegistry.CommandUsage(cmdName) deps.UI.Failed(T("Incorrect Usage") + "\n\n" + err.Error() + "\n\n" + usage) } cmd = cmd.SetDependency(deps, false) cmdRegistry.SetCommand(cmd) requirementsFactory := requirements.NewFactory(deps.Config, deps.RepoLocator) reqs := cmd.Requirements(requirementsFactory, flagContext) for _, req := range reqs { err = req.Execute() if err != nil { deps.UI.Failed(err.Error()) } } err = cmd.Execute(flagContext) if err != nil { ui := terminal.NewUI(os.Stdin, Writer, terminal.NewTeePrinter(Writer), traceLogger) ui.Failed(err.Error()) } warningsCollector.PrintWarnings() os.Exit(0) } //non core command, try plugin command server := netrpc.NewServer() rpcService, err := rpc.NewRpcService(deps.TeePrinter, deps.TeePrinter, deps.Config, deps.RepoLocator, rpc.NewCommandRunner(), deps.Logger, Writer, server) if err != nil { deps.UI.Say(T("Error initializing RPC service: ") + err.Error()) os.Exit(1) } pluginPath := filepath.Join(confighelpers.PluginRepoDir(), ".cf", "plugins") pluginConfig := pluginconfig.NewPluginConfig( func(err error) { deps.UI.Failed(fmt.Sprintf("Error read/writing plugin config: %s, ", err.Error())) }, configuration.NewDiskPersistor(filepath.Join(pluginPath, "config.json")), pluginPath, ) pluginList := pluginConfig.Plugins() ran := rpc.RunMethodIfExists(rpcService, args[1:], pluginList) if !ran { deps.UI.Say("'" + args[1] + T("' is not a registered command. See 'cf help'")) suggestCommands(cmdName, deps.UI, append(cmdRegistry.ListCommands(), pluginConfig.ListCommands()...)) os.Exit(1) } }
func newAppPresenter() appPresenter { var presenter appPresenter pluginPath := filepath.Join(confighelpers.PluginRepoDir(), ".cf", "plugins") pluginConfig := pluginconfig.NewPluginConfig( func(err error) { //fail silently when running help }, configuration.NewDiskPersistor(filepath.Join(pluginPath, "config.json")), pluginPath, ) plugins := pluginConfig.Plugins() maxNameLen := commandregistry.Commands.MaxCommandNameLength() maxNameLen = maxPluginCommandNameLength(plugins, maxNameLen) presentCommand := func(commandName string) (presenter cmdPresenter) { cmd := commandregistry.Commands.FindCommand(commandName) presenter.Name = cmd.MetaData().Name padding := strings.Repeat(" ", maxNameLen-utf8.RuneCountInString(presenter.Name)) presenter.Name = presenter.Name + padding presenter.Description = cmd.MetaData().Description return } presentPluginCommands := func() []cmdPresenter { var presenters []cmdPresenter var pluginPresenter cmdPresenter for _, pluginMetadata := range plugins { for _, cmd := range pluginMetadata.Commands { pluginPresenter.Name = cmd.Name padding := strings.Repeat(" ", maxNameLen-utf8.RuneCountInString(pluginPresenter.Name)) pluginPresenter.Name = pluginPresenter.Name + padding pluginPresenter.Description = cmd.HelpText presenters = append(presenters, pluginPresenter) } } return presenters } presenter.Name = os.Args[0] presenter.Usage = T("A command line tool to interact with Cloud Foundry") presenter.Version = cf.Version + "-" + cf.BuiltOnDate presenter.Commands = []groupedCommands{ { Name: T("GETTING STARTED"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("help"), presentCommand("version"), presentCommand("login"), presentCommand("logout"), presentCommand("passwd"), presentCommand("target"), }, { presentCommand("api"), presentCommand("auth"), }, }, }, { Name: T("APPS"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("apps"), presentCommand("app"), }, { presentCommand("push"), presentCommand("scale"), presentCommand("delete"), presentCommand("rename"), }, { presentCommand("start"), presentCommand("stop"), presentCommand("restart"), presentCommand("restage"), presentCommand("restart-app-instance"), }, { presentCommand("events"), presentCommand("files"), presentCommand("logs"), }, { presentCommand("env"), presentCommand("set-env"), presentCommand("unset-env"), }, { presentCommand("stacks"), presentCommand("stack"), }, { presentCommand("copy-source"), }, { presentCommand("create-app-manifest"), }, { presentCommand("get-health-check"), presentCommand("set-health-check"), presentCommand("enable-ssh"), presentCommand("disable-ssh"), presentCommand("ssh-enabled"), presentCommand("ssh"), }, }, }, { Name: T("SERVICES"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("marketplace"), presentCommand("services"), presentCommand("service"), }, { presentCommand("create-service"), presentCommand("update-service"), presentCommand("delete-service"), presentCommand("rename-service"), }, { presentCommand("create-service-key"), presentCommand("service-keys"), presentCommand("service-key"), presentCommand("delete-service-key"), }, { presentCommand("bind-service"), presentCommand("unbind-service"), }, { presentCommand("bind-route-service"), presentCommand("unbind-route-service"), }, { presentCommand("create-user-provided-service"), presentCommand("update-user-provided-service"), }, }, }, { Name: T("ORGS"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("orgs"), presentCommand("org"), }, { presentCommand("create-org"), presentCommand("delete-org"), presentCommand("rename-org"), }, }, }, { Name: T("SPACES"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("spaces"), presentCommand("space"), }, { presentCommand("create-space"), presentCommand("delete-space"), presentCommand("rename-space"), }, { presentCommand("allow-space-ssh"), presentCommand("disallow-space-ssh"), presentCommand("space-ssh-allowed"), }, }, }, { Name: T("DOMAINS"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("domains"), presentCommand("create-domain"), presentCommand("delete-domain"), presentCommand("create-shared-domain"), presentCommand("delete-shared-domain"), }, { presentCommand("router-groups"), }, }, }, { Name: T("ROUTES"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("routes"), presentCommand("create-route"), presentCommand("check-route"), presentCommand("map-route"), presentCommand("unmap-route"), presentCommand("delete-route"), presentCommand("delete-orphaned-routes"), }, }, }, { Name: T("BUILDPACKS"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("buildpacks"), presentCommand("create-buildpack"), presentCommand("update-buildpack"), presentCommand("rename-buildpack"), presentCommand("delete-buildpack"), }, }, }, { Name: T("USER ADMIN"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("create-user"), presentCommand("delete-user"), }, { presentCommand("org-users"), presentCommand("set-org-role"), presentCommand("unset-org-role"), }, { presentCommand("space-users"), presentCommand("set-space-role"), presentCommand("unset-space-role"), }, }, }, { Name: T("ORG ADMIN"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("quotas"), presentCommand("quota"), presentCommand("set-quota"), }, { presentCommand("create-quota"), presentCommand("delete-quota"), presentCommand("update-quota"), }, { presentCommand("share-private-domain"), presentCommand("unshare-private-domain"), }, }, }, { Name: T("SPACE ADMIN"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("space-quotas"), presentCommand("space-quota"), presentCommand("create-space-quota"), presentCommand("update-space-quota"), presentCommand("delete-space-quota"), presentCommand("set-space-quota"), presentCommand("unset-space-quota"), }, }, }, { Name: T("SERVICE ADMIN"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("service-auth-tokens"), presentCommand("create-service-auth-token"), presentCommand("update-service-auth-token"), presentCommand("delete-service-auth-token"), }, { presentCommand("service-brokers"), presentCommand("create-service-broker"), presentCommand("update-service-broker"), presentCommand("delete-service-broker"), presentCommand("rename-service-broker"), }, { presentCommand("migrate-service-instances"), presentCommand("purge-service-offering"), presentCommand("purge-service-instance"), }, { presentCommand("service-access"), presentCommand("enable-service-access"), presentCommand("disable-service-access"), }, }, }, { Name: T("SECURITY GROUP"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("security-group"), presentCommand("security-groups"), presentCommand("create-security-group"), presentCommand("update-security-group"), presentCommand("delete-security-group"), presentCommand("bind-security-group"), presentCommand("unbind-security-group"), }, { presentCommand("bind-staging-security-group"), presentCommand("staging-security-groups"), presentCommand("unbind-staging-security-group"), }, { presentCommand("bind-running-security-group"), presentCommand("running-security-groups"), presentCommand("unbind-running-security-group"), }, }, }, { Name: T("ENVIRONMENT VARIABLE GROUPS"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("running-environment-variable-group"), presentCommand("staging-environment-variable-group"), presentCommand("set-staging-environment-variable-group"), presentCommand("set-running-environment-variable-group"), }, }, }, { Name: T("FEATURE FLAGS"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("feature-flags"), presentCommand("feature-flag"), presentCommand("enable-feature-flag"), presentCommand("disable-feature-flag"), }, }, }, { Name: T("ADVANCED"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("curl"), presentCommand("config"), presentCommand("oauth-token"), presentCommand("ssh-code"), }, }, }, { Name: T("ADD/REMOVE PLUGIN REPOSITORY"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("add-plugin-repo"), presentCommand("remove-plugin-repo"), presentCommand("list-plugin-repos"), presentCommand("repo-plugins"), }, }, }, { Name: T("ADD/REMOVE PLUGIN"), CommandSubGroups: [][]cmdPresenter{ { presentCommand("plugins"), presentCommand("install-plugin"), presentCommand("uninstall-plugin"), }, }, }, { Name: T("INSTALLED PLUGIN COMMANDS"), CommandSubGroups: [][]cmdPresenter{ presentPluginCommands(), }, }, } return presenter }
func NewDependency(writer io.Writer, logger trace.Printer) Dependency { deps := Dependency{} deps.TeePrinter = terminal.NewTeePrinter(writer) deps.UI = terminal.NewUI(os.Stdin, writer, deps.TeePrinter, logger) errorHandler := func(err error) { if err != nil { deps.UI.Failed(fmt.Sprintf("Config error: %s", err)) } } configPath, err := confighelpers.DefaultFilePath() if err != nil { errorHandler(err) } deps.Config = coreconfig.NewRepositoryFromFilepath(configPath, errorHandler) deps.ManifestRepo = manifest.NewDiskRepository() deps.AppManifest = manifest.NewGenerator() pluginPath := filepath.Join(confighelpers.PluginRepoDir(), ".cf", "plugins") deps.PluginConfig = pluginconfig.NewPluginConfig( errorHandler, configuration.NewDiskPersistor(filepath.Join(pluginPath, "config.json")), pluginPath, ) terminal.UserAskedForColors = deps.Config.ColorEnabled() terminal.InitColorSupport() deps.Gateways = map[string]net.Gateway{ "cloud-controller": net.NewCloudControllerGateway(deps.Config, time.Now, deps.UI, logger), "uaa": net.NewUAAGateway(deps.Config, deps.UI, logger), "routing-api": net.NewRoutingAPIGateway(deps.Config, time.Now, deps.UI, logger), } deps.RepoLocator = api.NewRepositoryLocator(deps.Config, deps.Gateways, logger) deps.PluginModels = &PluginModels{Application: nil} deps.PlanBuilder = planbuilder.NewBuilder( deps.RepoLocator.GetServicePlanRepository(), deps.RepoLocator.GetServicePlanVisibilityRepository(), deps.RepoLocator.GetOrganizationRepository(), ) deps.ServiceBuilder = servicebuilder.NewBuilder( deps.RepoLocator.GetServiceRepository(), deps.PlanBuilder, ) deps.BrokerBuilder = brokerbuilder.NewBuilder( deps.RepoLocator.GetServiceBrokerRepository(), deps.ServiceBuilder, ) deps.PluginRepo = pluginrepo.NewPluginRepo() deps.ServiceHandler = actors.NewServiceHandler( deps.RepoLocator.GetOrganizationRepository(), deps.BrokerBuilder, deps.ServiceBuilder, ) deps.ServicePlanHandler = actors.NewServicePlanHandler( deps.RepoLocator.GetServicePlanRepository(), deps.RepoLocator.GetServicePlanVisibilityRepository(), deps.RepoLocator.GetOrganizationRepository(), deps.PlanBuilder, deps.ServiceBuilder, ) deps.WordGenerator = generator.NewWordGenerator() deps.AppZipper = appfiles.ApplicationZipper{} deps.AppFiles = appfiles.ApplicationFiles{} deps.PushActor = actors.NewPushActor(deps.RepoLocator.GetApplicationBitsRepository(), deps.AppZipper, deps.AppFiles) deps.ChecksumUtil = utils.NewSha1Checksum("") deps.Logger = logger return deps }
pluginDir = filepath.Join(fakePluginRepoDir, ".cf", "plugins") err = os.MkdirAll(pluginDir, 0700) Expect(err).NotTo(HaveOccurred()) fileutils.CopyPathToPath(filepath.Join(fixtureDir, "test_1.exe"), filepath.Join(pluginDir, "test_1.exe")) fileutils.CopyPathToPath(filepath.Join(fixtureDir, "test_2.exe"), filepath.Join(pluginDir, "test_2.exe")) confighelpers.PluginRepoDir = func() string { return fakePluginRepoDir } pluginPath := filepath.Join(confighelpers.PluginRepoDir(), ".cf", "plugins") pluginConfig = pluginconfig.NewPluginConfig( func(err error) { Expect(err).ToNot(HaveOccurred()) }, configuration.NewDiskPersistor(filepath.Join(pluginPath, "config.json")), pluginPath, ) pluginConfig.SetPlugin("test_1.exe", pluginconfig.PluginMetadata{Location: filepath.Join(pluginDir, "test_1.exe")}) pluginConfig.SetPlugin("test_2.exe", pluginconfig.PluginMetadata{Location: filepath.Join(pluginDir, "test_2.exe")}) }) AfterEach(func() { err := os.RemoveAll(fakePluginRepoDir) Expect(err).NotTo(HaveOccurred()) }) runCommand := func(args ...string) bool { return testcmd.RunCLICommand("uninstall-plugin", args, requirementsFactory, updateCommandDependency, false, ui) }