func()

in agent/pluginmanager/acspluginmanager/acspluginmanager.go [1087:1197]


func (pm *PluginManager) VerifyPlugin(fetchOptions *VerifyFetchOptions, executeParams *ExecuteParams) (exitCode int, err error) {
	const funcName = "VerifyPlugin"
	log.GetLogger().WithFields(log.Fields{
		"fetchOptions":  fetchOptions,
		"executeParams": executeParams,
	}).Infoln("Enter VerifyPlugin")

	// pull package
	unzipdir := filepath.Join(pm.pluginRoot, "verify_plugin_test")
	exitCode, err = func(packageUrl string, timeoutInSeconds int) (int, error) {
		ctx := context.Background()
		var cancel context.CancelFunc
		if timeoutInSeconds > 0 {
			ctx, cancel = context.WithTimeout(ctx, time.Duration(timeoutInSeconds)*time.Second)
			defer cancel()
		}

		log.GetLogger().Infoln("Downloading package from ", packageUrl)
		filePath, err := func(packageUrl string, timeoutInSeconds int) (string, error) {
			fileName := packageUrl[strings.LastIndex(packageUrl, "/")+1:]
			filePath := filepath.Join(pm.pluginRoot, fileName)
			if len(packageUrl) > 4 && packageUrl[:4] == "http" {
				return filePath, util.HttpDownloadContext(ctx, packageUrl, filePath)
			} else {
				return filePath, FileProtocolDownload(packageUrl, filePath)
			}
		}(packageUrl, timeoutInSeconds)
		if err != nil {
			exitcode, _ := errProcess(funcName, DOWNLOAD_FAIL, err, fmt.Sprintf("Downloading package failed, url is [%s], err is [%s]", packageUrl, err.Error()))
			return exitcode, err
		}

		pathutil.MakeSurePath(unzipdir)
		log.GetLogger().Infoln("Unzip package...")
		if err := zipfile.UnzipContext(ctx, filePath, unzipdir, false); err != nil {
			exitcode, _ := errProcess(funcName, UNZIP_ERR, err, fmt.Sprintf("Unzip package err, url is [%s], err is [%s]", packageUrl, err.Error()))
			return exitcode, err
		}

		os.RemoveAll(filePath)

		return 0, nil
	}(fetchOptions.Url, fetchOptions.FetchTimeoutInSeconds)
	if err != nil {
		return
	}

	configPath := filepath.Join(unzipdir, "config.json")
	if !fileutil.CheckFileIsExist(configPath) {
		err = errors.New("Can not find the config.json")
		exitCode, _ = errProcess(funcName, PLUGIN_FORMAT_ERR, err, fmt.Sprintf("File config.json not exist, %s.", configPath))
		return
	}
	config := pluginConfig{}
	var content []byte
	if content, err = fuzzyjson.UnmarshalFile(configPath, &config); err != nil {
		exitCode, _ = errProcess(funcName, UNMARSHAL_ERR, err, fmt.Sprintf("Unmarshal config.json err, config.json is [%s], err is [%s]", string(content), err.Error()))
		return
	}
	// 检查系统类型和架构是否符合
	if config.OsType != "" && strings.ToLower(config.OsType) != "both" && strings.ToLower(config.OsType) != osutil.GetOsType() {
		err = errors.New("Plugin ostype not suit for this system")
		exitCode, _ = errProcess(funcName, PLUGIN_FORMAT_ERR, err, fmt.Sprintf("Plugin ostype[%s] not suit for this system[%s], url is [%s]", config.OsType, osutil.GetOsType(), fetchOptions.Url))
		return
	}
	localArch, _ := GetArch()
	if config.Arch != "" && strings.ToLower(config.Arch) != "all" && strings.ToLower(config.Arch) != localArch {
		err = errors.New("Plugin arch not suit for this system")
		exitCode, _ = errProcess(funcName, PLUGIN_FORMAT_ERR, err, fmt.Sprintf("Plugin arch[%s] not suit for this system[%s], url is [%s]", config.Arch, localArch, fetchOptions.Url))
		return
	}

	cmdPath := filepath.Join(unzipdir, config.RunPath)
	if !fileutil.CheckFileIsExist(cmdPath) {
		err = errors.New("Can not find the cmd file")
		exitCode, _ = errProcess(funcName, PLUGIN_FORMAT_ERR, err, fmt.Sprintf("Executable file not exist, %s.", cmdPath))
		return
	}
	if osutil.GetOsType() != osutil.OSWin {
		if err = os.Chmod(cmdPath, os.FileMode(0o744)); err != nil {
			exitCode, _ = errProcess(funcName, EXECUTABLE_PERMISSION_ERR, err, "Make plugin file executable err: "+err.Error())
			return
		}
	}

	executionTimeoutInSeconds := 60
	if t, err := strconv.Atoi(config.Timeout); err != nil {
		fmt.Println("config.Timeout is invalid: ", config.Timeout)
	} else {
		executionTimeoutInSeconds = t
	}
	if executeParams.OptionalExecutionTimeoutInSeconds != nil {
		executionTimeoutInSeconds = *executeParams.OptionalExecutionTimeoutInSeconds
	}

	// 执行插件时要注入的环境变量
	env := []string{
		// 当前执行的插件的执行目录
		"PLUGIN_DIR=" + unzipdir,
		// 如果已有同名插件,表示已有同名插件的执行目录;否则为空
		"PRE_PLUGIN_DIR=",
	}
	var options []process.CmdOption
	options, err = prepareCmdOptions(executeParams)
	if err != nil {
		exitCode, _ = errProcess(funcName, EXECUTE_FAILED, err, fmt.Sprintf("Failed to set execution options: %s", err.Error()))
		return
	}
	exitCode, _, err = pm.executePlugin(cmdPath, executeParams.SplitArgs(), executionTimeoutInSeconds, env, false, options...)
	return
}