createNewLayer creates a new layer newLayerID for (index, trusted) on top of parentLayer (which may be ""). If the layer cannot be committed yet, the function returns (nil, nil).
(index int, trusted trustedLayerIdentityData, parentLayer, newLayerID string)
| 1078 | // createNewLayer creates a new layer newLayerID for (index, trusted) on top of parentLayer (which may be ""). |
| 1079 | // If the layer cannot be committed yet, the function returns (nil, nil). |
| 1080 | func (s *storageImageDestination) createNewLayer(index int, trusted trustedLayerIdentityData, parentLayer, newLayerID string) (*storage.Layer, error) { |
| 1081 | s.lock.Lock() |
| 1082 | diffOutput, ok := s.lockProtected.diffOutputs[index] |
| 1083 | s.lock.Unlock() |
| 1084 | if ok { |
| 1085 | // Typically, we compute a trusted DiffID value to authenticate the layer contents, see the detailed explanation |
| 1086 | // in PutBlobPartial. If the user has opted out of that, but we know a trusted DiffID value |
| 1087 | // (e.g. from a BlobInfoCache), set it in diffOutput. |
| 1088 | // That way it will be persisted in storage even if the cache is deleted; also |
| 1089 | // we can use the value below to avoid the untrustedUncompressedDigest logic. |
| 1090 | if diffOutput.UncompressedDigest == "" && trusted.diffID != "" { |
| 1091 | diffOutput.UncompressedDigest = trusted.diffID |
| 1092 | } |
| 1093 | |
| 1094 | var untrustedUncompressedDigest digest.Digest |
| 1095 | if diffOutput.UncompressedDigest == "" { |
| 1096 | d, err := s.untrustedLayerDiffID(index) |
| 1097 | if err != nil { |
| 1098 | var diffIDUnknownErr untrustedLayerDiffIDUnknownError |
| 1099 | switch { |
| 1100 | case errors.Is(err, errUntrustedLayerDiffIDNotYetAvailable): |
| 1101 | logrus.Debugf("Skipping commit for layer %q, manifest not yet available", newLayerID) |
| 1102 | return nil, nil |
| 1103 | case errors.As(err, &diffIDUnknownErr): |
| 1104 | // If untrustedLayerDiffIDUnknownError, the input image is schema1, has no TOC annotations, |
| 1105 | // so we should have !trusted.layerIdentifiedByTOC, i.e. we should have set |
| 1106 | // diffOutput.UncompressedDigest above in this function, at the very latest. |
| 1107 | // |
| 1108 | // Or, maybe, the input image is OCI, and has invalid/missing DiffID values in config. In that case |
| 1109 | // commitLayer should have already refused this image when dealing with the “view” ambiguity. |
| 1110 | return nil, fmt.Errorf("internal error: layer %d for blob %s was partially-pulled with unknown UncompressedDigest, but we don't have a DiffID in config", |
| 1111 | index, trusted.logString()) |
| 1112 | default: |
| 1113 | return nil, err |
| 1114 | } |
| 1115 | } |
| 1116 | |
| 1117 | untrustedUncompressedDigest = d |
| 1118 | // While the contents of the digest are untrusted, make sure at least the _format_ is valid, |
| 1119 | // because we are going to write it to durable storage in expectedLayerDiffIDFlag . |
| 1120 | if err := untrustedUncompressedDigest.Validate(); err != nil { |
| 1121 | return nil, err |
| 1122 | } |
| 1123 | } |
| 1124 | |
| 1125 | flags := make(map[string]interface{}) |
| 1126 | if untrustedUncompressedDigest != "" { |
| 1127 | flags[expectedLayerDiffIDFlag] = untrustedUncompressedDigest.String() |
| 1128 | logrus.Debugf("Setting uncompressed digest to %q for layer %q", untrustedUncompressedDigest, newLayerID) |
| 1129 | } |
| 1130 | |
| 1131 | args := storage.ApplyStagedLayerOptions{ |
| 1132 | ID: newLayerID, |
| 1133 | ParentLayer: parentLayer, |
| 1134 | |
| 1135 | DiffOutput: diffOutput, |
| 1136 | DiffOptions: &graphdriver.ApplyDiffWithDifferOpts{ |
| 1137 | Flags: flags, |
no test coverage detected