github.com/jmrodri/operator-sdk@v0.5.0/pkg/test/main_entry.go (about) 1 // Copyright 2018 The Operator-SDK Authors 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 test 16 17 import ( 18 "bytes" 19 "flag" 20 "fmt" 21 "io/ioutil" 22 "os" 23 "os/exec" 24 "os/signal" 25 "path/filepath" 26 "syscall" 27 "testing" 28 29 "k8s.io/client-go/tools/clientcmd" 30 31 "github.com/operator-framework/operator-sdk/pkg/k8sutil" 32 "github.com/operator-framework/operator-sdk/pkg/scaffold" 33 log "github.com/sirupsen/logrus" 34 ) 35 36 const ( 37 ProjRootFlag = "root" 38 KubeConfigFlag = "kubeconfig" 39 NamespacedManPathFlag = "namespacedMan" 40 GlobalManPathFlag = "globalMan" 41 SingleNamespaceFlag = "singleNamespace" 42 TestNamespaceEnv = "TEST_NAMESPACE" 43 LocalOperatorFlag = "localOperator" 44 ) 45 46 func MainEntry(m *testing.M) { 47 projRoot := flag.String(ProjRootFlag, "", "path to project root") 48 kubeconfigPath := flag.String(KubeConfigFlag, "", "path to kubeconfig") 49 globalManPath := flag.String(GlobalManPathFlag, "", "path to operator manifest") 50 namespacedManPath := flag.String(NamespacedManPathFlag, "", "path to rbac manifest") 51 singleNamespace = flag.Bool(SingleNamespaceFlag, false, "enable single namespace mode") 52 localOperator := flag.Bool(LocalOperatorFlag, false, "enable if operator is running locally (not in cluster)") 53 flag.Parse() 54 // go test always runs from the test directory; change to project root 55 err := os.Chdir(*projRoot) 56 if err != nil { 57 log.Fatalf("Failed to change directory to project root: %v", err) 58 } 59 if err := setup(kubeconfigPath, namespacedManPath, *localOperator); err != nil { 60 log.Fatalf("Failed to set up framework: %v", err) 61 } 62 // setup local operator command, but don't start it yet 63 var localCmd *exec.Cmd 64 var localCmdOutBuf, localCmdErrBuf bytes.Buffer 65 if *localOperator { 66 // TODO: make a generic 'up-local' function to deduplicate shared code between this and cmd/up/local 67 // taken from commands/operator-sdk/cmd/up/local.go 68 runArgs := append([]string{"run"}, []string{filepath.Join(scaffold.ManagerDir, scaffold.CmdFile)}...) 69 localCmd = exec.Command("go", runArgs...) 70 localCmd.Stdout = &localCmdOutBuf 71 localCmd.Stderr = &localCmdErrBuf 72 c := make(chan os.Signal) 73 signal.Notify(c, os.Interrupt, syscall.SIGTERM) 74 go func() { 75 <-c 76 err := localCmd.Process.Signal(os.Interrupt) 77 if err != nil { 78 log.Fatalf("Failed to terminate the operator: (%v)", err) 79 } 80 os.Exit(0) 81 }() 82 if *kubeconfigPath != "" { 83 localCmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", k8sutil.KubeConfigEnvVar, *kubeconfigPath)) 84 } else { 85 // we can hardcode index 0 as that is the highest priority kubeconfig to be loaded and will always 86 // be populated by NewDefaultClientConfigLoadingRules() 87 localCmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", k8sutil.KubeConfigEnvVar, clientcmd.NewDefaultClientConfigLoadingRules().Precedence[0])) 88 } 89 localCmd.Env = append(localCmd.Env, fmt.Sprintf("%v=%v", k8sutil.WatchNamespaceEnvVar, Global.Namespace)) 90 } 91 // setup context to use when setting up crd 92 ctx := NewTestCtx(nil) 93 // os.Exit stops the program before the deferred functions run 94 // to fix this, we put the exit in the defer as well 95 defer func() { 96 // start local operator before running tests 97 if *localOperator { 98 err := localCmd.Start() 99 if err != nil { 100 log.Fatalf("Failed to run operator locally: (%v)", err) 101 } 102 log.Info("Started local operator") 103 } 104 exitCode := m.Run() 105 if *localOperator { 106 err := localCmd.Process.Kill() 107 if err != nil { 108 log.Warn("Failed to stop local operator process") 109 } 110 log.Infof("Local operator stdout: %s", string(localCmdOutBuf.Bytes())) 111 log.Infof("Local operator stderr: %s", string(localCmdErrBuf.Bytes())) 112 } 113 ctx.CleanupNoT() 114 os.Exit(exitCode) 115 }() 116 // create crd 117 if *kubeconfigPath != "incluster" { 118 globalYAML, err := ioutil.ReadFile(*globalManPath) 119 if err != nil { 120 log.Fatalf("Failed to read global resource manifest: %v", err) 121 } 122 err = ctx.createFromYAML(globalYAML, true, &CleanupOptions{TestContext: ctx}) 123 if err != nil { 124 log.Fatalf("Failed to create resource(s) in global resource manifest: %v", err) 125 } 126 } 127 }