Exemple #1
0
func (e *etcd) SaveTcpRouteMapping(tcpMapping models.TcpRouteMapping) error {
	key := generateTcpRouteMappingKey(tcpMapping)

	retries := 0
	for retries <= maxRetries {
		response, err := e.keysAPI.Get(context.Background(), key, readOpts())

		// Update
		if response != nil && err == nil {
			var existingTcpRouteMapping models.TcpRouteMapping

			err = json.Unmarshal([]byte(response.Node.Value), &existingTcpRouteMapping)
			if err != nil {
				return err
			}

			tcpMapping.ModificationTag = existingTcpRouteMapping.ModificationTag
			tcpMapping.ModificationTag.Increment()

			tcpRouteJSON, _ := json.Marshal(tcpMapping)
			_, err = e.keysAPI.Set(ctx(), key, string(tcpRouteJSON), updateOptsWithTTL(int(tcpMapping.TTL), response.Node.ModifiedIndex))
		} else if cerr, ok := err.(client.Error); ok && cerr.Code == client.ErrorCodeKeyNotFound { //create
			// Delete came in between a read and update
			if retries > 0 {
				return ErrorConflict
			}

			var tag models.ModificationTag
			tag, err = models.NewModificationTag()
			if err != nil {
				return err
			}

			tcpMapping.ModificationTag = tag
			tcpRouteMappingJSON, _ := json.Marshal(tcpMapping)
			_, err = e.keysAPI.Set(ctx(), key, string(tcpRouteMappingJSON), createOpts(int(tcpMapping.TTL)))
		}

		// return when create or update is successful
		if err == nil {
			return nil
		}

		// only retry on a compare and swap error
		if cerr, ok := err.(client.Error); ok && cerr.Code == client.ErrorCodeTestFailed {
			retries++
		} else {
			return err
		}
	}

	// number of retries exceeded
	return ErrorConflict
}
Exemple #2
0
						Expect(err).NotTo(HaveOccurred())
						Expect(fakeKeysAPI.GetCallCount()).To(Equal(1))
						Expect(fakeKeysAPI.SetCallCount()).To(Equal(1))
						_, _, json, opts := fakeKeysAPI.SetArgsForCall(0)
						Expect(json).To(ContainSubstring("\"index\":0"))
						Expect(json).To(ContainSubstring(`"router_group_guid":"router-group-guid-001"`))
						Expect(json).To(ContainSubstring(`"port":52000`))
						Expect(json).To(ContainSubstring(`"backend_port":60000`))
						Expect(json).To(ContainSubstring(`"backend_ip":"1.2.3.4"`))
						Expect(json).To(ContainSubstring(`"ttl":50`))
						Expect(opts.TTL).To(Equal(50 * time.Second))
					})

					Context("when an entry already exists", func() {
						BeforeEach(func() {
							tcpMapping.ModificationTag = models.ModificationTag{Guid: "guid", Index: 5}
							tcpRouteJson, err := json.Marshal(&tcpMapping)
							Expect(err).ToNot(HaveOccurred())
							fakeResp := &client.Response{Node: &client.Node{Value: string(tcpRouteJson)}}
							fakeKeysAPI.GetReturns(fakeResp, nil)
						})

						It("Updates the route and increments the tag index", func() {
							newTcpMapping := models.NewTcpRouteMapping("router-group-guid-001", 52000, "1.2.3.4", 60000, 50)
							err := fakeEtcd.SaveTcpRouteMapping(newTcpMapping)
							Expect(err).NotTo(HaveOccurred())
							Expect(fakeKeysAPI.GetCallCount()).To(Equal(1))
							Expect(fakeKeysAPI.SetCallCount()).To(Equal(1))
							_, _, json, _ := fakeKeysAPI.SetArgsForCall(0)
							Expect(json).To(ContainSubstring("\"index\":6"))
						})