InstallAll runs every registered plugin through the staging Registrar, validates, and commits the survivors. FailOpen plugins that fail are skipped with a warning; the first FailClosed failure stops the loop and returns the error. Plugins are processed in registration order so the result is determi
(plugins []platform.Plugin, errOut io.Writer)
| 45 | // errOut receives warnings about FailOpen plugin skips. nil errOut |
| 46 | // means warnings are dropped (useful in tests). |
| 47 | func InstallAll(plugins []platform.Plugin, errOut io.Writer) (*InstallResult, error) { |
| 48 | if errOut == nil { |
| 49 | errOut = io.Discard |
| 50 | } |
| 51 | result := &InstallResult{ |
| 52 | Registry: hook.NewRegistry(), |
| 53 | } |
| 54 | |
| 55 | // Detect duplicate Plugin.Name. We do this up-front so the error |
| 56 | // surfaces before any Install runs; design hard-constraint #7 |
| 57 | // treats this as configuration error (fail-closed regardless of |
| 58 | // individual FailurePolicy). |
| 59 | if err := detectDuplicateNames(plugins); err != nil { |
| 60 | return nil, err |
| 61 | } |
| 62 | |
| 63 | for _, p := range plugins { |
| 64 | name, nameErr := safeCallName(p) |
| 65 | if nameErr != nil { |
| 66 | // Fail-closed on bad Name: we don't know the plugin's |
| 67 | // FailurePolicy yet (it's behind Capabilities, and we |
| 68 | // cannot trust Capabilities() before Name() succeeds). |
| 69 | return nil, nameErr |
| 70 | } |
| 71 | if err := installOne(name, p, result); err != nil { |
| 72 | // Some errors must abort regardless of FailurePolicy |
| 73 | // because they imply the plugin's FailurePolicy itself |
| 74 | // cannot be trusted (e.g. the consistency check between |
| 75 | // Restricts and FailClosed failed). |
| 76 | if isUntrustedConfigError(err) { |
| 77 | return nil, err |
| 78 | } |
| 79 | policy := readFailurePolicy(p) |
| 80 | switch policy { |
| 81 | case platform.FailClosed: |
| 82 | return nil, err |
| 83 | default: |
| 84 | fmt.Fprintf(errOut, "warning: plugin %q skipped: %v\n", name, err) |
| 85 | continue |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | return result, nil |
| 91 | } |
| 92 | |
| 93 | // isUntrustedConfigError flags errors where the plugin's declared |
| 94 | // FailurePolicy is itself part of the misconfiguration. For these the |