Skip to content

Commit

Permalink
Merge "CLI: move code around a bit"
Browse files Browse the repository at this point in the history
  • Loading branch information
Microzuul CI authored and Gerrit Code Review committed Jan 4, 2024
2 parents 10dd9e2 + 485c431 commit 8827f8a
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 149 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ RUN go mod download
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/
COPY cli/cmd/ cli/cmd/

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
Expand Down
86 changes: 86 additions & 0 deletions cli/cmd/apply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright © 2023 Red Hat
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

/*
"apply" subcommand applies a SF CR manifest without the need for CRDs on the cluster.
*/

import (
"errors"
"os"

sfv1 "github.com/softwarefactory-project/sf-operator/api/v1"
"github.com/softwarefactory-project/sf-operator/controllers"
"github.com/spf13/cobra"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/yaml"
)

func applyCmd(kmd *cobra.Command, args []string) {
cliCtx, err := GetCLIContext(kmd)
if err != nil {
ctrl.Log.Error(err, "Error initializing:")
os.Exit(1)
}
ns := cliCtx.Namespace
sfResource, _ := kmd.Flags().GetString("cr")
hasManifest := &cliCtx.Manifest
if sfResource == "" && hasManifest != nil {
sfResource = cliCtx.Manifest
}
if (sfResource != "" && ns == "") || (sfResource == "" && ns != "") {
err := errors.New("standalone mode requires both --cr and --namespace to be set")
ctrl.Log.Error(err, "Argument error:")
os.Exit(1)
} else if sfResource != "" && ns != "" {
var sf sfv1.SoftwareFactory
dat, err := os.ReadFile(sfResource)
if err != nil {
ctrl.Log.Error(err, "Error reading manifest:")
os.Exit(1)
}
if err := yaml.Unmarshal(dat, &sf); err != nil {
ctrl.Log.Error(err, "Error interpreting the SF custom resource:")
os.Exit(1)
}
ctrl.Log.Info("Applying custom resource with the following parameters:",
"CR", sf,
"CR name", sf.ObjectMeta.Name,
"Namespace", ns)
controllers.Standalone(sf, ns, cliCtx.KubeContext)
os.Exit(0)
}
}

func MkApplyCmd() *cobra.Command {

var (
sfResource string

applyCmd = &cobra.Command{
Use: "apply",
Short: "Apply a SoftwareFactory Custom Resource to a cluster",
Long: `This command can be used to deploy a SoftwareFactory resource without installing the operator or its associated CRDs on a cluster.
This will run the operator runtime locally, deploy the resource's components on the cluster, then exit.`,
Run: applyCmd,
}
)

applyCmd.Flags().StringVar(&sfResource, "cr", "", "The path to the CR to apply.")
return applyCmd
}
115 changes: 115 additions & 0 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
Copyright © 2023 Red Hat
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 provides subcommands for the main.go CLI
package cmd

import (
"errors"

"github.com/spf13/cobra"
"github.com/spf13/viper"
ctrl "sigs.k8s.io/controller-runtime"
)

// CLI config struct
type SoftwareFactoryConfigContext struct {
ConfigRepository string `mapstructure:"config-repository-path"`
Manifest string `mapstructure:"manifest-file"`
IsStandalone bool `mapstructure:"standalone"`
Namespace string `mapstructure:"namespace"`
KubeContext string `mapstructure:"kube-context"`
FQDN string `mapstructure:"fqdn"`
Dev struct {
AnsibleMicroshiftRolePath string `mapstructure:"ansible-microshift-role-path"`
Microshift struct {
Host string `mapstructure:"host"`
User string `mapstructure:"user"`
InventoryFile string `mapstructure:"inventory-file"`
} `mapstructure:"microshift"`
Tests struct {
ExtraVars map[string]string `mapstructure:"extra-vars"`
} `mapstructure:"tests"`
} `mapstructure:"development"`
Components struct {
Nodepool struct {
CloudsFile string `mapstructure:"clouds-file"`
KubeFile string `mapstructure:"kube-file"`
} `mapstructure:"nodepool"`
} `mapstructure:"components"`
}

type SoftwareFactoryConfig struct {
Contexts map[string]SoftwareFactoryConfigContext `mapstructure:"contexts"`
Default string `mapstructure:"default-context"`
}

func loadConfigFile(command *cobra.Command) (cliConfig SoftwareFactoryConfig, err error) {
configPath, _ := command.Flags().GetString("config")
viper.SetConfigFile(configPath)
err = viper.ReadInConfig()
if err != nil {
return
}
err = viper.Unmarshal(&cliConfig)
return
}

func getContextFromFile(command *cobra.Command) (ctxName string, cliContext SoftwareFactoryConfigContext, err error) {
cliConfig, err := loadConfigFile(command)
if err != nil {
return
}
ctx, _ := command.Flags().GetString("context")
if ctx == "" {
ctx = cliConfig.Default
}
for c := range cliConfig.Contexts {
if ctx == "" || ctx == c {
return c, cliConfig.Contexts[c], nil
}
}
return ctxName, cliContext, errors.New("context not found")
}

func GetCLIContext(command *cobra.Command) (SoftwareFactoryConfigContext, error) {
var cliContext SoftwareFactoryConfigContext
var ctxName string
var err error
configPath, _ := command.Flags().GetString("config")
if configPath != "" {
ctxName, cliContext, err = getContextFromFile(command)
if err != nil {
ctrl.Log.Error(err, "Could not load config file")
} else {
ctrl.Log.Info("Using configuration context " + ctxName)
}
}
// Override with defaults
// We don't set a default namespace here so as not to interfere with rootcommand.
ns, _ := command.Flags().GetString("namespace")
if cliContext.Namespace == "" {
cliContext.Namespace = ns
}
fqdn, _ := command.Flags().GetString("fqdn")
if fqdn == "" {
fqdn = "sfop.me"
}
if cliContext.FQDN == "" {
cliContext.FQDN = fqdn
}
return cliContext, nil
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ require (
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)

replace (
github.com/softwarefactory-project/sf-operator/cli/cmd => ./cli/cmd
)
Loading

0 comments on commit 8827f8a

Please sign in to comment.