provider/digital_ocean.go
func (p *DigitalOceanProvider) submitChanges(changes []*DigitalOceanChange) error {
	// return early if there is nothing to change
	if len(changes) == 0 {
		return nil
	}

	zones, err := p.Zones()
	if err != nil {
		return err
	}

	// separate into per-zone change sets to be passed to the API.
	changesByZone := digitalOceanChangesByZone(zones, changes)
	for zoneName, changes := range changesByZone {
		records, err := p.fetchRecords(zoneName)
		if err != nil {
			log.Errorf("Failed to list records in the zone: %s", zoneName)
			continue
		}
		for _, change := range changes {
			logFields := log.Fields{
				"record": change.ResourceRecordSet.Name,
				"type":   change.ResourceRecordSet.Type,
				"ttl":    change.ResourceRecordSet.TTL,
				"action": change.Action,
				"zone":   zoneName,
			}

			log.WithFields(logFields).Info("Changing record.")

			if p.DryRun {
				continue
			}

			change.ResourceRecordSet.Name = strings.TrimSuffix(change.ResourceRecordSet.Name, "."+zoneName)

			// record at the root should be defined as @ instead of
			// the full domain name
			if change.ResourceRecordSet.Name == zoneName {
				change.ResourceRecordSet.Name = "@"
			}

			// for some reason the DO API requires the '.' at the end of "data" in case of CNAME request
			// Example: {"type":"CNAME","name":"hello","data":"www.example.com."}
			if change.ResourceRecordSet.Type == endpoint.RecordTypeCNAME {
				change.ResourceRecordSet.Data += "."
			}

			switch change.Action {
			case DigitalOceanCreate:
				_, _, err = p.Client.CreateRecord(context.TODO(), zoneName,
					&godo.DomainRecordEditRequest{
						Data: change.ResourceRecordSet.Data,
						Name: change.ResourceRecordSet.Name,
						Type: change.ResourceRecordSet.Type,
						TTL:  change.ResourceRecordSet.TTL,
					})
				if err != nil {
					return err
				}
			case DigitalOceanDelete:
				recordID := p.getRecordID(records, change.ResourceRecordSet)
				_, err = p.Client.DeleteRecord(context.TODO(), zoneName, recordID)
				if err != nil {
					return err
				}
			case DigitalOceanUpdate:
				recordID := p.getRecordID(records, change.ResourceRecordSet)
				_, _, err = p.Client.EditRecord(context.TODO(), zoneName, recordID,
					&godo.DomainRecordEditRequest{
						Data: change.ResourceRecordSet.Data,
						Name: change.ResourceRecordSet.Name,
						Type: change.ResourceRecordSet.Type,
						TTL:  change.ResourceRecordSet.TTL,
					})
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}
func (p *DigitalOceanProvider) submitChanges(changes []*DigitalOceanChange) error {
	// return early if there is nothing to change
	if len(changes) == 0 {
		return nil
	}

	zones, err := p.Zones()
	if err != nil {
		return err
	}

	// separate into per-zone change sets to be passed to the API.
	changesByZone := digitalOceanChangesByZone(zones, changes)
	for zoneName, changes := range changesByZone {
		records, err := p.fetchRecords(zoneName)
		if err != nil {
			log.Errorf("Failed to list records in the zone: %s", zoneName)
			continue
		}
		for _, change := range changes {
			logFields := log.Fields{
				"record": change.ResourceRecordSet.Name,
				"type":   change.ResourceRecordSet.Type,
				"ttl":    change.ResourceRecordSet.TTL,
				"action": change.Action,
				"zone":   zoneName,
			}

			log.WithFields(logFields).Info("Changing record.")

			if p.DryRun {
				continue
			}

			change.ResourceRecordSet.Name = strings.TrimSuffix(change.ResourceRecordSet.Name, "."+zoneName)

			// record at the root should be defined as @ instead of
			// the full domain name
			if change.ResourceRecordSet.Name == zoneName {
				change.ResourceRecordSet.Name = "@"
			}

			// for some reason the DO API requires the '.' at the end of "data" in case of CNAME request
			// Example: {"type":"CNAME","name":"hello","data":"www.example.com."}
			if change.ResourceRecordSet.Type == endpoint.RecordTypeCNAME {
				change.ResourceRecordSet.Data += "."
			}

			switch change.Action {
			case DigitalOceanCreate:
				_, _, err = p.Client.CreateRecord(context.TODO(), zoneName,
					&godo.DomainRecordEditRequest{
						Data: change.ResourceRecordSet.Data,
						Name: change.ResourceRecordSet.Name,
						Type: change.ResourceRecordSet.Type,
						TTL:  change.ResourceRecordSet.TTL,
					})
				if err != nil {
					return err
				}
			case DigitalOceanDelete:
				recordID := p.getRecordID(records, change.ResourceRecordSet)
				_, err = p.Client.DeleteRecord(context.TODO(), zoneName, recordID)
				if err != nil {
					return err
				}
			case DigitalOceanUpdate:
				recordID := p.getRecordID(records, change.ResourceRecordSet)
				_, _, err = p.Client.EditRecord(context.TODO(), zoneName, recordID,
					&godo.DomainRecordEditRequest{
						Data: change.ResourceRecordSet.Data,
						Name: change.ResourceRecordSet.Name,
						Type: change.ResourceRecordSet.Type,
						TTL:  change.ResourceRecordSet.TTL,
					})
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}
func ( p * DigitalOceanProvider ) submitChanges ( changes [ ] * DigitalOceanChange ) error { // return early if there is nothing to change if len ( changes ) == 0 { return nil } zones , err := p . Zones ( ) if err != nil { return err } // separate into per-zone change sets to be passed to the API. changesByZone := digitalOceanChangesByZone ( zones , changes ) for zoneName , changes := range changesByZone { records , err := p . fetchRecords ( zoneName ) if err != nil { log . Errorf ( " " , zoneName ) continue } for _ , change := range changes { logFields := log . Fields { " " : change . ResourceRecordSet . Name , " " : change . ResourceRecordSet . Type , " " : change . ResourceRecordSet . TTL , " " : change . Action , " " : zoneName , } log . WithFields ( logFields ) . Info ( " " ) if p . DryRun { continue } change . ResourceRecordSet . Name = strings . TrimSuffix ( change . ResourceRecordSet . Name , " " + zoneName ) // record at the root should be defined as @ instead of // the full domain name if change . ResourceRecordSet . Name == zoneName { change . ResourceRecordSet . Name = " " } // for some reason the DO API requires the '.' at the end of "data" in case of CNAME request // Example: {"type":"CNAME","name":"hello","data":"www.example.com."} if change . ResourceRecordSet . Type == endpoint . RecordTypeCNAME { change . ResourceRecordSet . Data += " " } switch change . Action { case DigitalOceanCreate : _ , _ , err = p . Client . CreateRecord ( context . TODO ( ) , zoneName , & godo . DomainRecordEditRequest { Data : change . ResourceRecordSet . Data , Name : change . ResourceRecordSet . Name , Type : change . ResourceRecordSet . Type , TTL : change . ResourceRecordSet . TTL , } ) if err != nil { return err } case DigitalOceanDelete : recordID := p . getRecordID ( records , change . ResourceRecordSet ) _ , err = p . Client . DeleteRecord ( context . TODO ( ) , zoneName , recordID ) if err != nil { return err } case DigitalOceanUpdate : recordID := p . getRecordID ( records , change . ResourceRecordSet ) _ , _ , err = p . Client . EditRecord ( context . TODO ( ) , zoneName , recordID , & godo . DomainRecordEditRequest { Data : change . ResourceRecordSet . Data , Name : change . ResourceRecordSet . Name , Type : change . ResourceRecordSet . Type , TTL : change . ResourceRecordSet . TTL , } ) if err != nil { return err } } } } return nil }
// submitChanges takes a zone and a collection of Changes and sends them as a single transaction.
submitChanges takes a zone and a collection of Changes and sends them as a single transaction .