github.com/apptainer/singularity@v3.1.1+incompatible/cmd/internal/cli/run_help_linux.go (about)

     1  // Copyright (c) 2018-2019, Sylabs Inc. All rights reserved.
     2  // This software is licensed under a 3-clause BSD license. Please consult the
     3  // LICENSE.md file distributed with the sources of this project regarding your
     4  // rights to use or distribute this software.
     5  
     6  package cli
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  
    14  	"github.com/opencontainers/runtime-tools/generate"
    15  	"github.com/spf13/cobra"
    16  	"github.com/sylabs/singularity/docs"
    17  	"github.com/sylabs/singularity/internal/pkg/buildcfg"
    18  	"github.com/sylabs/singularity/internal/pkg/runtime/engines/config"
    19  	"github.com/sylabs/singularity/internal/pkg/runtime/engines/config/oci"
    20  	singularityConfig "github.com/sylabs/singularity/internal/pkg/runtime/engines/singularity/config"
    21  	"github.com/sylabs/singularity/internal/pkg/sylog"
    22  	"github.com/sylabs/singularity/internal/pkg/util/exec"
    23  )
    24  
    25  const (
    26  	standardHelpPath = "/.singularity.d/runscript.help"
    27  	appHelpPath      = "/scif/apps/%s/scif/runscript.help"
    28  	runHelpCommand   = "if [ ! -f \"%s\" ]\nthen\n    echo \"No help sections were defined for this image\"\nelse\n    /bin/cat %s\nfi"
    29  )
    30  
    31  func init() {
    32  	RunHelpCmd.Flags().SetInterspersed(false)
    33  
    34  	RunHelpCmd.Flags().StringVar(&AppName, "app", "", "Show the help for an app")
    35  	RunHelpCmd.Flags().SetAnnotation("app", "envkey", []string{"APP"})
    36  
    37  	SingularityCmd.AddCommand(RunHelpCmd)
    38  }
    39  
    40  // RunHelpCmd singularity run-help <image>
    41  var RunHelpCmd = &cobra.Command{
    42  	DisableFlagsInUseLine: true,
    43  	PreRun:                sylabsToken,
    44  	Args:                  cobra.ExactArgs(1),
    45  	Run: func(cmd *cobra.Command, args []string) {
    46  		// Sanity check
    47  		if _, err := os.Stat(args[0]); err != nil {
    48  			sylog.Fatalf("container not found: %s", err)
    49  		}
    50  
    51  		// Help prints (if set) the sourced %help section on the definition file
    52  		abspath, err := filepath.Abs(args[0])
    53  		if err != nil {
    54  			sylog.Fatalf("While getting absolute path: %s", err)
    55  		}
    56  		name := filepath.Base(abspath)
    57  
    58  		a := []string{"/bin/sh", "-c", getCommand(getHelpPath(cmd))}
    59  		starter := buildcfg.LIBEXECDIR + "/singularity/bin/starter-suid"
    60  		procname := "Singularity help"
    61  		Env := []string{sylog.GetEnvVar()}
    62  
    63  		engineConfig := singularityConfig.NewConfig()
    64  		ociConfig := &oci.Config{}
    65  		generator := generate.Generator{Config: &ociConfig.Spec}
    66  		engineConfig.OciConfig = ociConfig
    67  
    68  		generator.SetProcessArgs(a)
    69  		generator.SetProcessCwd("/")
    70  		engineConfig.SetImage(abspath)
    71  
    72  		cfg := &config.Common{
    73  			EngineName:   singularityConfig.Name,
    74  			ContainerID:  name,
    75  			EngineConfig: engineConfig,
    76  		}
    77  
    78  		configData, err := json.Marshal(cfg)
    79  		if err != nil {
    80  			sylog.Fatalf("CLI Failed to marshal CommonEngineConfig: %s\n", err)
    81  		}
    82  
    83  		if err := exec.Pipe(starter, []string{procname}, Env, configData); err != nil {
    84  			sylog.Fatalf("%s", err)
    85  		}
    86  	},
    87  
    88  	Use:     docs.RunHelpUse,
    89  	Short:   docs.RunHelpShort,
    90  	Long:    docs.RunHelpLong,
    91  	Example: docs.RunHelpExample,
    92  }
    93  
    94  func getCommand(helpFile string) string {
    95  	return fmt.Sprintf(runHelpCommand, helpFile, helpFile)
    96  }
    97  
    98  func getHelpPath(cmd *cobra.Command) string {
    99  	if cmd.Flags().Changed("app") {
   100  		sylog.Debugf("App specified. Looking for help section of %s", AppName)
   101  		return fmt.Sprintf(appHelpPath, AppName)
   102  	}
   103  
   104  	return standardHelpPath
   105  }