mirror of https://github.com/docker/docs.git
fixing timestamps, clearing changelists, and the Adding target byte log
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
074f52d559
commit
5015b1f47d
|
@ -238,7 +238,7 @@ func (r *NotaryRepository) AddTarget(target *Target) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("Adding target \"%s\" with sha256 \"%s\" and size %d bytes.\n", target.Name, target.Hashes["sha256"], target.Length)
|
logrus.Debugf("Adding target \"%s\" with sha256 \"%x\" and size %d bytes.\n", target.Name, target.Hashes["sha256"], target.Length)
|
||||||
|
|
||||||
meta := data.FileMeta{Length: target.Length, Hashes: target.Hashes}
|
meta := data.FileMeta{Length: target.Length, Hashes: target.Hashes}
|
||||||
metaJSON, err := json.Marshal(meta)
|
metaJSON, err := json.Marshal(meta)
|
||||||
|
@ -340,9 +340,9 @@ func (r *NotaryRepository) Publish(getPass passwordRetriever) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the changelist for this repo
|
// load the changelist for this repo
|
||||||
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
|
changelistDir := filepath.Join(r.tufRepoPath, "changelist")
|
||||||
|
cl, err := changelist.NewFileChangelist(changelistDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debug("Error initializing changelist")
|
logrus.Debug("Error initializing changelist")
|
||||||
return err
|
return err
|
||||||
|
@ -406,7 +406,18 @@ func (r *NotaryRepository) Publish(getPass passwordRetriever) error {
|
||||||
}
|
}
|
||||||
update["targets"] = targetsJSON
|
update["targets"] = targetsJSON
|
||||||
update["snapshot"] = snapshotJSON
|
update["snapshot"] = snapshotJSON
|
||||||
return remote.SetMultiMeta(update)
|
err = remote.SetMultiMeta(update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = cl.Clear("")
|
||||||
|
if err != nil {
|
||||||
|
// This is not a critical problem when only a single host is pushing
|
||||||
|
// but will cause weird behaviour if changelist cleanup is failing
|
||||||
|
// and there are multiple hosts writing to the repo.
|
||||||
|
logrus.Warn("Unable to clear changelist. You may want to manually delete the folder ", changelistDir)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *NotaryRepository) bootstrapRepo() error {
|
func (r *NotaryRepository) bootstrapRepo() error {
|
||||||
|
|
|
@ -570,6 +570,13 @@ func testPublish(t *testing.T, rootType data.KeyAlgorithm) {
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
changelistDir, err = os.Open(changelistDirPath)
|
||||||
|
assert.NoError(t, err, "could not open changelist directory")
|
||||||
|
fileInfos, err = changelistDir.Readdir(0)
|
||||||
|
assert.NoError(t, err, "could not read changelist directory")
|
||||||
|
// Should only be one file in the directory
|
||||||
|
assert.Len(t, fileInfos, 0, "wrong number of changelist files found")
|
||||||
|
|
||||||
// Create a new repo and pull from the server
|
// Create a new repo and pull from the server
|
||||||
tempBaseDir2, err := ioutil.TempDir("", "notary-test-")
|
tempBaseDir2, err := ioutil.TempDir("", "notary-test-")
|
||||||
defer os.RemoveAll(tempBaseDir2)
|
defer os.RemoveAll(tempBaseDir2)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package timestamp
|
package timestamp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -49,6 +50,10 @@ func GetOrCreateTimestampKey(gun string, store storage.MetaStore, crypto signed.
|
||||||
// a new timestamp is generated either because none exists, or because the current
|
// a new timestamp is generated either because none exists, or because the current
|
||||||
// one has expired. Once generated, the timestamp is saved in the store.
|
// one has expired. Once generated, the timestamp is saved in the store.
|
||||||
func GetOrCreateTimestamp(gun string, store storage.MetaStore, cryptoService signed.CryptoService) ([]byte, error) {
|
func GetOrCreateTimestamp(gun string, store storage.MetaStore, cryptoService signed.CryptoService) ([]byte, error) {
|
||||||
|
snapshot, err := store.GetCurrent(gun, "snapshot")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
d, err := store.GetCurrent(gun, "timestamp")
|
d, err := store.GetCurrent(gun, "timestamp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(*storage.ErrNotFound); !ok {
|
if _, ok := err.(*storage.ErrNotFound); !ok {
|
||||||
|
@ -65,11 +70,11 @@ func GetOrCreateTimestamp(gun string, store storage.MetaStore, cryptoService sig
|
||||||
logrus.Error("Failed to unmarshal existing timestamp")
|
logrus.Error("Failed to unmarshal existing timestamp")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !timestampExpired(ts) {
|
if !timestampExpired(ts) && !snapshotExpired(ts, snapshot) {
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sgnd, version, err := createTimestamp(gun, ts, store, cryptoService)
|
sgnd, version, err := CreateTimestamp(gun, ts, snapshot, store, cryptoService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error("Failed to create a new timestamp")
|
logrus.Error("Failed to create a new timestamp")
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -91,11 +96,23 @@ func timestampExpired(ts *data.SignedTimestamp) bool {
|
||||||
return time.Now().After(ts.Signed.Expires)
|
return time.Now().After(ts.Signed.Expires)
|
||||||
}
|
}
|
||||||
|
|
||||||
// createTimestamp creates a new timestamp. If a prev timestamp is provided, it
|
func snapshotExpired(ts *data.SignedTimestamp, snapshot []byte) bool {
|
||||||
|
meta, err := data.NewFileMeta(bytes.NewReader(snapshot), "sha256")
|
||||||
|
if err != nil {
|
||||||
|
// if we can't generate FileMeta from the current snapshot, we should
|
||||||
|
// continue to serve the old timestamp if it isn't time expired
|
||||||
|
// because we won't be able to generate a new one.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
hash := meta.Hashes["sha256"]
|
||||||
|
return !bytes.Equal(hash, ts.Signed.Meta["snapshot"].Hashes["sha256"])
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTimestamp creates a new timestamp. If a prev timestamp is provided, it
|
||||||
// is assumed this is the immediately previous one, and the new one will have a
|
// is assumed this is the immediately previous one, and the new one will have a
|
||||||
// version number one higher than prev. The store is used to lookup the current
|
// version number one higher than prev. The store is used to lookup the current
|
||||||
// snapshot, this function does not save the newly generated timestamp.
|
// snapshot, this function does not save the newly generated timestamp.
|
||||||
func createTimestamp(gun string, prev *data.SignedTimestamp, store storage.MetaStore, cryptoService signed.CryptoService) (*data.Signed, int, error) {
|
func CreateTimestamp(gun string, prev *data.SignedTimestamp, snapshot []byte, store storage.MetaStore, cryptoService signed.CryptoService) (*data.Signed, int, error) {
|
||||||
algorithm, public, err := store.GetTimestampKey(gun)
|
algorithm, public, err := store.GetTimestampKey(gun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// owner of gun must have generated a timestamp key otherwise
|
// owner of gun must have generated a timestamp key otherwise
|
||||||
|
@ -103,10 +120,6 @@ func createTimestamp(gun string, prev *data.SignedTimestamp, store storage.MetaS
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
key := data.NewPublicKey(algorithm, public)
|
key := data.NewPublicKey(algorithm, public)
|
||||||
snapshot, err := store.GetCurrent(gun, "snapshot")
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
sn := &data.Signed{}
|
sn := &data.Signed{}
|
||||||
err = json.Unmarshal(snapshot, sn)
|
err = json.Unmarshal(snapshot, sn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -60,3 +60,31 @@ func TestGetTimestamp(t *testing.T) {
|
||||||
_, err = GetOrCreateTimestamp("gun", store, crypto)
|
_, err = GetOrCreateTimestamp("gun", store, crypto)
|
||||||
assert.Nil(t, err, "GetTimestamp errored")
|
assert.Nil(t, err, "GetTimestamp errored")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetTimestampNewSnapshot(t *testing.T) {
|
||||||
|
store := storage.NewMemStorage()
|
||||||
|
crypto := signed.NewEd25519()
|
||||||
|
|
||||||
|
snapshot := data.SignedSnapshot{}
|
||||||
|
snapshot.Signed.Version = 0
|
||||||
|
snapJSON, _ := json.Marshal(snapshot)
|
||||||
|
|
||||||
|
store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 0, Data: snapJSON})
|
||||||
|
// create a key to be used by GetTimestamp
|
||||||
|
_, err := GetOrCreateTimestampKey("gun", store, crypto, data.ED25519Key)
|
||||||
|
assert.Nil(t, err, "GetTimestampKey errored")
|
||||||
|
|
||||||
|
ts1, err := GetOrCreateTimestamp("gun", store, crypto)
|
||||||
|
assert.Nil(t, err, "GetTimestamp errored")
|
||||||
|
|
||||||
|
snapshot = data.SignedSnapshot{}
|
||||||
|
snapshot.Signed.Version = 1
|
||||||
|
snapJSON, _ = json.Marshal(snapshot)
|
||||||
|
|
||||||
|
store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 1, Data: snapJSON})
|
||||||
|
|
||||||
|
ts2, err := GetOrCreateTimestamp("gun", store, crypto)
|
||||||
|
assert.Nil(t, err, "GetTimestamp errored")
|
||||||
|
|
||||||
|
assert.NotEqual(t, ts1, ts2, "Timestamp was not regenerated when snapshot changed")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue