| Conditions | 15 |
| Total Lines | 83 |
| Code Lines | 48 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like providers.*ExternalCredentialsProvider.getCredentials often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | package providers |
||
| 80 | func (provider *ExternalCredentialsProvider) getCredentials() (session *sessionCredentials, err error) { |
||
| 81 | args := strings.Fields(provider.processCommand) |
||
| 82 | if len(args) == 0 { |
||
| 83 | err = errors.New("process_command is empty") |
||
| 84 | return |
||
| 85 | } |
||
| 86 | |||
| 87 | // 确保 options 不为 nil,并设置默认超时时间 |
||
| 88 | timeout := 60 * 1000 // 默认 60 秒 |
||
| 89 | if provider.options != nil && provider.options.Timeout > 0 { |
||
| 90 | timeout = provider.options.Timeout |
||
| 91 | } |
||
| 92 | |||
| 93 | var cancelFunc func() |
||
| 94 | ctx, cancelFunc := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Millisecond) |
||
| 95 | defer cancelFunc() |
||
| 96 | |||
| 97 | cmd := exec.CommandContext(ctx, args[0], args[1:]...) |
||
| 98 | cmd.Env = os.Environ() |
||
| 99 | |||
| 100 | // 创建一个buffer来捕获标准输出 |
||
| 101 | var stdoutBuf bytes.Buffer |
||
| 102 | cmd.Stdout = &stdoutBuf |
||
| 103 | |||
| 104 | // 创建一个buffer来捕获标准错误输出 |
||
| 105 | var stderrBuf bytes.Buffer |
||
| 106 | cmd.Stderr = &stderrBuf |
||
| 107 | |||
| 108 | // Start the command |
||
| 109 | if err := cmd.Start(); err != nil { |
||
| 110 | return nil, fmt.Errorf("failed to execute external command: %w\nstderr: %s", err, stderrBuf.String()) |
||
| 111 | } |
||
| 112 | |||
| 113 | done := make(chan error, 1) |
||
| 114 | go func() { |
||
| 115 | done <- cmd.Wait() |
||
| 116 | }() |
||
| 117 | |||
| 118 | select { |
||
| 119 | case <-ctx.Done(): |
||
| 120 | // 超时了,context 会自动终止命令 |
||
| 121 | <-done |
||
| 122 | return nil, fmt.Errorf("command process timed out after %d milliseconds", timeout) |
||
| 123 | case execError := <-done: |
||
| 124 | if execError != nil { |
||
| 125 | // 检查是否是超时导致的错误 |
||
| 126 | if errors.Is(execError, context.DeadlineExceeded) { |
||
| 127 | return nil, fmt.Errorf("command process timed out after %d milliseconds", timeout) |
||
| 128 | } |
||
| 129 | return nil, fmt.Errorf("failed to execute external command: %w\nstderr: %s", execError, stderrBuf.String()) |
||
| 130 | } |
||
| 131 | } |
||
| 132 | |||
| 133 | // 只解析标准输出 |
||
| 134 | buf := stdoutBuf.Bytes() |
||
| 135 | |||
| 136 | // 解析得到凭证响应 |
||
| 137 | var resp externalCredentialResponse |
||
| 138 | err = json.Unmarshal(buf, &resp) |
||
| 139 | if err != nil { |
||
| 140 | fmt.Println(provider.processCommand) |
||
| 141 | fmt.Println(string(buf)) |
||
| 142 | return nil, fmt.Errorf("failed to parse external command output: %w", err) |
||
| 143 | } |
||
| 144 | |||
| 145 | // 验证返回的凭证数据 |
||
| 146 | if resp.AccessKeyId == "" || resp.AccessKeySecret == "" { |
||
| 147 | return nil, fmt.Errorf("invalid credential response: access_key_id or access_key_secret is empty") |
||
| 148 | } |
||
| 149 | |||
| 150 | // 根据 mode 验证 SecurityToken |
||
| 151 | if resp.Mode == "StsToken" && resp.SecurityToken == "" { |
||
| 152 | return nil, fmt.Errorf("invalid StsToken credential response: sts_token is empty") |
||
| 153 | } |
||
| 154 | |||
| 155 | session = &sessionCredentials{ |
||
| 156 | AccessKeyId: resp.AccessKeyId, |
||
| 157 | AccessKeySecret: resp.AccessKeySecret, |
||
| 158 | SecurityToken: resp.SecurityToken, |
||
| 159 | Expiration: resp.Expiration, |
||
| 160 | } |
||
| 161 | |||
| 162 | return |
||
| 163 | } |
||
| 254 |