1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

..

66 Commits

Author SHA1 Message Date
Lai Jiang 77f998ee4b Disable Travis (#231) 2019-08-16 17:13:43 -04:00
Lai Jiang c93248ec10 Update build badges to use Kokoro results for both FOSS and internal (#229) 2019-08-16 15:06:02 -04:00
Aman Sanger 3ac179aead Prober metrics collection (#222)
* Added MetricsHandler and Clock to ProbingSequences

* Minor fixes after rebase onto master

* Added metrics gathering to ProbingSequences

* Added testing of MetricsCollector method calls in ProbingSequenceTest

* Added tests on latency recording to ProbingSequenceTest

* Added response name as label to metrics
2019-08-16 13:49:50 -04:00
gbrodman 92f2f3274e Add a boolean for when a registrar has enabled registry lock (#228)
* Add a boolean for when a registrar has enabled registry lock

* enabled -> allowed

* get -> is
2019-08-16 10:46:07 -04:00
Aman Sanger 57975898d5 Prober EPP components added (#202)
* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Final Changes in .gitignore

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Fixed changes suggested by CydeWeys

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Rebased to Master and added in modified Handlers and ProbingAction

* Fixed changes suggested by CydeWeys

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Rebased to master

* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Minor syle fixes after succesful rebase onto master

* Initial Commit.

* Added Protocol Class and its Basic Unit Tests

* Fixed Gitignore to take out AutoValue generated code

* Final Changes in .gitignore

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Removed AutoVaue ignore clause from .gitignore

* Rebased to Master and added in modified Handlers and ProbingAction

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Modified license header dates

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Fixed files to pass all style tests

* Fixed changes suggested by CydeWeys

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Rebased to Master and added in modified Handlers and ProbingAction

* Fixed changes suggested by CydeWeys

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Rebased to master

* Updated issues in rebasing

* Added circular linked list to utils

* License Header added

* Refactored probing sequence to be circular linked list iterator

* Modified ProbingStep tests to reflect new ProbingStep structure.

* Added circular linked list to utils

* Added circular linked list to utils

* License Header added

* License Header added

* Refactored probing sequence to be circular linked list iterator

* Modified ProbingStep tests to reflect new ProbingStep structure.

* Added missing license header to DefaultCircularLinkedListIterator

* Fixed changes suggested by CydeWeys

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Fixed max column length to be 100

* Rebased to Master and added in modified Handlers and ProbingAction

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Fixed changes suggested by CydeWeys

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Added circular linked list to utils

* Added circular linked list to utils

* License Header added

* License Header added

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* ProbingStepTest modified to have fewer unnecessary helper methods

* Updated issues in rebasing

* Fixed max column length to be 100

* Minor changes to pass style tests

* Successful rebase onto finished web-whois branch

* Removed need for TestTokens with Mockito mocks of Tokens

* Fixed style issues in DefaultCircularLinkedListIterator and AbstractCircularLinkedListIterator

* Modified CircularList according to changes suggested by jianglai.

* Added Protocol Class and its Basic Unit Tests

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Updated build.gradle file

* Updated WebWhois tests.

* Added Basic EPP structure

* Added Basic EPP structure

* Prober Updated tests

* Prober Updated tests

* Fully functioning EPP sequences with modified WebWhois base.

* Fully functioning EPP sequences with modified WebWhois base.

* Added Modified test server infrastructure.

* Added Modified test server infrastructure.

* Allowed ActionHandler to pass status to next hanlder in pipeline (to be MetricsHandler).

* Allowed ActionHandler to pass status to next hanlder in pipeline (to be MetricsHandler).

* Javadoc on EppRequestMessage added

* Javadoc on EppRequestMessage added

* Updated EppServer to properly send successful Check responses.

* Updated EppServer to properly send successful Check responses.

* Allowed for expected failures in EPP actions.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Fully rebased branch to prober-web-whois after refactoring

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Rebased to master

* Fixed max column length to be 100

* Fixed files to pass all style tests

* Minor changes to pass style tests

* Successful rebase onto circular-list

* Epp Refactored to accomodate circular linked list PR

* Modified construction of Epp Probing Sequences to reflect CircularList change

* Renamed ProberModule provided Duration

* Removed unnecessary ServerSideException file

* Google-Java-Format run on all prober files

* Style fix on ProbingSequence and its unit tests

* Removed subclasses of EppRequestMessage and EppResponseMessage and fixed style and other minor issues

* Style changes implemented as suggested by jianglai

* Added style fixes suggested by mindhog
2019-08-15 16:03:36 -04:00
Weimin Yu 86fefa9a03 Make postgres dependency runtime (#225)
* Make postgres dependency runtime

Labeling it 'compile' unnecessarily makes psql-dependency a
public contract.
2019-08-14 12:32:07 -04:00
Shicong Huang d143cc83a0 Add Hibernate and PostgreSQL packages (#224) 2019-08-14 11:22:01 -04:00
Aman Sanger df5f450435 Prober circular list (#218)
* Fixed changes suggested by CydeWeys

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Updated build.gradle file

* Modified license header dates

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Initial Commit.

* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Final Changes in .gitignore

* Final Changes in .gitignore

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Minor Style Fix

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* fixed build issues

* fixed build issues

* fixed build issues

* fixed build issues

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Minor Style Fixes

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* Rebased to master

* Updated issues in rebasing

* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Fixed files to pass all style tests

* Fixed files to pass all style tests

* Minor syle fixes after succesful rebase onto master

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* fixed build issues

* fixed build issues

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* Added circular linked list to utils

* Added circular linked list to utils

* Added circular linked list to utils

* Added circular linked list to utils

* Added circular linked list to utils

* License Header added

* License Header added

* License Header added

* License Header added

* License Header added

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Refactored probing sequence to be circular linked list iterator

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Modified ProbingStep tests to reflect new ProbingStep structure.

* Modified ProbingStep tests to reflect new ProbingStep structure.

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* ProbingStepTest modified to have fewer unnecessary helper methods

* ProbingStepTest modified to have fewer unnecessary helper methods

* Updated issues in rebasing

* Updated issues in rebasing

* Added missing license header to DefaultCircularLinkedListIterator

* Fixed max column length to be 100

* Fixed max column length to be 100

* Minor changes to pass style tests

* Successful rebase onto finished web-whois branch

* Removed need for TestTokens with Mockito mocks of Tokens

* Fixed style issues in DefaultCircularLinkedListIterator and AbstractCircularLinkedListIterator

* Modified CircularList according to changes suggested by jianglai.

* Merge branch 'master' into prober-circular-list

* Modified ProbingSequenceTest to not expect unnecessary NullPointerException

* ProbingSequence and tests modified to reflect addition of UnrecoverableStateException and restarts on failures

* Modified ProbingSequence and its tests to reflect action generation and calling being put in the same try catch block
2019-08-12 18:41:50 -04:00
gbrodman 89a44f176c Clean up token generation (#205)
* Clean up token generation

- Allow tokenLength of 0
- If specifying a token length of 0, throw an error if numTokens > 1

* Allow generation of 0-length strings

* Allow for --tokens option to generate specific tokens

* Revert String generators and disallow 0 'length' param

* Add verifyInput method and batch the listed tokens

* Check the number of tokens created
2019-08-12 17:41:29 -04:00
gbrodman d2319b13fa Bucket RDAP metrics by type (#220)
* Bucket RDAP metrics by type

* Rename method

* Use Guava Splitter and a joining Collector

* Use Iterables.limit

* Whoops, extra paren

* Checkstyle
2019-08-12 11:11:48 -04:00
gbrodman 77259f368d Fix checkstyle in Prober (#221) 2019-08-09 14:10:36 -04:00
Aman Sanger 27b81ba898 Add full prober WebWHOIS sequence functionality (#180)
* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Fixed changes suggested by CydeWeys

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Final Changes in .gitignore

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Fixed changes suggested by CydeWeys

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Full WebWhoIs Sequence Added

* fixed build issues

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Final Changes in .gitignore

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Fixed changes suggested by CydeWeys

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues

* Fixed Travis Build Issues

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* fixed build issues

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Fixed changes suggested by CydeWeys

* Rebased to Master and added in modified Handlers and ProbingAction

* Added missing license headers and JavaDoc

* Added missing license headers and JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor fix in NewChannelAction JavaDoc

* Minor Style Fix

* Minor Style Fix

* Full WebWhoIs Sequence Added

* Full WebWhoIs Sequence Added

* fixed build issues

* fixed build issues

* Refactored by responses suggested by jianglai.

* Refactored by responses suggested by jianglai.

* Minor Style Fixes

* Minor Style Fixes

* Updated build.gradle file

* Updated build.gradle file

* Modified license header dates

* Modified license header dates

* Updated WebWhois tests.

* Updated WebWhois tests.

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* Refactored WebWhois to accomodate jianglai's suggested changes and modified tests to reflect this refactoring

* SpotlessApply run to fix style issues

* SpotlessApply run to fix style issues

* Added license header and newline where appropriate.

* Added license header and newline where appropriate.

* Javadoc style fix in tests and removed unused methods

* Javadoc style fix in tests and removed unused methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Refactored ProbingAction to minimize number of unnecessary methods

* Modified tests for WebWhois according to changes suggested by laijiang.

* Modified tests for WebWhois according to changes suggested by laijiang.

* Removed TestProvider from TestUtils.

* Removed TestProvider from TestUtils.

* Rebased to master

* Updated issues in rebasing

* Minor style change on prober/build.gradle

* Fixed warnings for java compilation

* Fixed files to pass all style tests

* Minor syle fixes after succesful rebase onto master
2019-08-08 15:17:41 -04:00
Lai Jiang c7478fc52b Fix expired access token bug in the proxy (#217)
https://github.com/google/nomulus/pull/129 migrated `GoogleCredential`
to `GoogleCredentialsBundle` and introduced a subtle bug. I don't fully
understand why but there are times when the access token is null but
`credentials.refresh()` is not called, resulting in NullPointerException
when `credentials.getAccessToken().getTokenValue()` is called.

Since the new GoogleCredentials class supports `shouldRefresh()`, we now
just rely on it to make sure that we always get a value access token.
2019-08-08 14:44:33 -04:00
Shicong Huang a68b1a12fd Implement TransactionManager for datastore (#207)
This PR created the new interface named TransactionManager which defines
methods to manage transaction. Also, the access to all transaction related
methods of Ofy.java are restricted to package private, and they will be exposed
by DatastoreTransactionManager which is the datastore implementation of
TransactionManager.
2019-08-07 12:59:08 -04:00
Weimin Yu ce791e8b97 Generate code coverage report (#216)
* Generate code coverage report

Enable jacoco, the official Gradle code coverage plugin.

The 'build' task will write a code coverage report to
build/reports/jacoco for each subproject that has tests.
We should consider publish periodical reports to a well known
location.

This change also defines a minimum coverage verification task.
The task is for experiment only, and is not added to the build
process yet.
2019-08-07 11:21:04 -04:00
gbrodman cf3f9603f7 Clean up RDAP action logs and request plain text (#213)
* Remove unused log argument

* Use the right accept-encoding

By default we request gzip and theoretically we'd decode it
automatically on our end but for some reason that's not working. I
tested this on Alpha and it worked
2019-08-06 14:00:09 -04:00
Lai Jiang 4fd32c8b5c Add a Gradle task to deploy the proxy (#214)
Also refactored some common code regarding the mapping between
environments and projects.

The script to update proxy deployments and kill all pods are lifted from
https://cs.corp.google.com/piper///depot/google3/domain/registry/tools/bashrc?l=163
2019-08-06 11:45:34 -04:00
gbrodman 3488f95990 Clean up Gradle stylings and fix issues IDed in Prober (#212) 2019-08-05 15:54:20 -04:00
Shicong Huang 8e00f85f60 Use OpenJDK8 for Gradle build (#210) 2019-08-02 17:00:35 -04:00
Shicong Huang 3cc8d83396 Hard code webdriver docker version (#208) 2019-08-01 14:02:57 -04:00
gbrodman 0a779612f6 Remove old EPP processing time metrics (#206) 2019-07-31 19:18:40 -04:00
gbrodman 545a03618b Add an underline when hovering/focusing on <a> tags (#193) 2019-07-31 17:36:53 -04:00
Ben McIlwain bcdacc88d3 Remove vestigial path for streaming EPP metrics (#184)
* Remove vestigial path for streaming EPP metrics

The relevant action was deleted last year here: google@218c451

This removes the final hanging piece.
2019-07-29 14:37:04 -04:00
gbrodman 56b10ea136 Create a Gradle task to run the test server (#192)
* Create a Gradle task to run the test server

As an artifact of the old build system, the test server relies on having
the built registrar_(bin|dbg)*(\.css)?.js in place (see ConsoleUiAction
among others). As a result, we create a Gradle task that puts those
files into the correct, readable, location before running the test
server.

* Depend on assemble rather than build

* refactor gitignores
2019-07-29 11:03:29 -04:00
Ben McIlwain 9479e1e8b9 Rename Spec11 reply-to email and also use it as sending address (#201)
* Rename Spec11 reply-to email and also use it as sending address
2019-07-26 15:30:46 -04:00
Shicong Huang 110bd9c057 Fix deploying to alpha from workstation (#198)
appengineDeployAll requires appengine.deploy.version to be set
otherwiese the deployment would fail.
2019-07-26 14:37:49 -04:00
Lai Jiang 2ae5aba7ff Rename dependency_license.gradle file (#196)
The file name confused the licensee app
(https://github.com/licensee/licensee) that GitHub uses to detect
license files. It thinks this file is also a license file and was not
able to determine is type.
2019-07-26 14:19:08 -04:00
Lai Jiang b878e5acc1 Remove port to protocol map (#200)
There's no need for it. We can get the port from the protocol.
2019-07-25 22:05:12 -04:00
gbrodman 4d0409c924 Add HTML lang tags where possible (#199) 2019-07-25 21:09:32 -04:00
gbrodman 0292887cb9 Store only interesting failures, not login failures (#188)
Login failures will happen any time that we aren't coming from a
whitelisted IP for that particular TLD. Since whitelists are out of date
(and we don't whitelist IPs for every TLD anyway) those failures aren't
interesting. Store and fully-log the interesting failures if one
happened.
2019-07-24 10:55:55 -04:00
Lai Jiang 464f6ba90a Add a missing space (#197) 2019-07-24 10:50:27 -04:00
Lai Jiang 0ab0a8c2e6 Use positive booleans to improve readability (#190)
This allows us to use lgtm.com to scan for vulnerabilities.
2019-07-23 22:30:46 -04:00
Lai Jiang 2cc4e5fa94 Add a badge for LGTM analysis results (#194) 2019-07-23 21:42:19 -04:00
gbrodman 47a890253e Revert "Use parallel Gradle builds by default (#189)" (#195)
This reverts commit 5dfd96d26d.
2019-07-23 18:12:04 -04:00
Lai Jiang b452b0628d Add customized .lgtm.yml (#191)
* Add customized .lgtm.yml
2019-07-23 17:09:05 -04:00
gbrodman 5dfd96d26d Use parallel Gradle builds by default (#189) 2019-07-23 15:27:30 -04:00
Shicong Huang e2a673d914 Bring back the old GoogleCredential for Drive API (#187)
Using the new GoogleCredentials to access Drive API caused 403 forbidden
exception. So, this PR brought back the old GoogleCredential to
temporarily resolve the production issue while we are figuring out the
long term fix.

TESTED=Deployed to alpha and verified exportPremiumTerms succeeded, see
https://paste.googleplex.com/6153215760400384.
2019-07-23 11:31:35 -04:00
gbrodman bf29d159f9 Fix a few deprecations (#186) 2019-07-22 14:12:55 -04:00
Lai Jiang e17cb52bf7 Fail gracefully when copying detailed reports (#181)
* Fail gracefully when copying detailed reports

When the detailed reports are copied from GCS to registrars' Drive
folders, do not fail the entire copy operation when a single registrar
fails. Instead, send an alert email about the failure, and continue to copy the
rest of the reports.

Also, instead of creating duplicates, overwrite the existing files on
Drive.

BUG=127690361
2019-07-22 14:09:49 -04:00
Lai Jiang 7352f9b4a6 Remove unused local variable (#185) 2019-07-22 10:04:16 -04:00
Lai Jiang 5da48184f9 Merge beam and GAE configs deployment to one GCB job (#182)
* Merge beam and GAE configs deployment to one GCB job

Deployment of GAE configs requires that the credential used by gcloud to
have GAE admin role of the project to be managed. We do not want to
grant the GCB service account that role, because it would all *any* GCB
job to deploy anything to GAE. Instead we use a dedicated credential
originally created to deploy beam pipelines. This credential is
encrypted by KMS and stored on GCS. Since the beam pipeline deployment
GCB job already does the decryption, it make sense to add the config
deployment step there as well. The beam deployment steps are tweaked to
use the nomulus tool docker image instead of the jar file.

Also moved the content of deploy_configs_to_env.sh to the GCB yaml file
itself because the shell script is not uploaded to GC Bat the same time
as the yaml file when the job is triggered by Spinnaker.

Lastly, due to b/137891685, using GCB to deploy cron jobs does not work
as we cannot use service account credential to deploy to projects under
google.com.
2019-07-19 16:54:56 -04:00
gbrodman 5bd2ccd210 Add a Cloud Build task to update YAML configs (#177)
* Add a Cloud Build task to update YAML configs

* CR responses

* Move config deployment to a script

* Pin builder version

* Create different beam and deploy-config files per environment

* Update comments and make a for loop
2019-07-18 12:15:15 -04:00
Lai Jiang 8fd5ab2bec Build proxy image in Gradle (#179) 2019-07-17 20:38:03 -04:00
Lai Jiang 30f6113b05 Upgrade to Gradle 5.5.1 (#178)
Also make the default wrapper type "all" instead of "binary". This is
helpful for IDEs to understand the gradle script.
2019-07-17 17:37:44 -04:00
Michael Muller bd48041961 Build docker image of nomulus tool (#142)
* Build docker image of nomulus tool

In the course of "gradle build", build a docker image of nomulus tool so that
users can run this to allow us to bundle the java version with the image.
2019-07-16 20:18:44 -04:00
gbrodman 39ceda628c Don't extend expiration times for deleted domains (#160)
* Don't extend expiration times for deleted domains

* Flip order and add a comment

* oops forgot a period

* Use END_OF_TIME

* Add tests for expiration times of domains with pending transfers

* Add test for transfer during autorenew and clean up other tests

* Clarify tests

* Add domain expiration check in EppLifecycleDomainTest

* Add a comment and format test files
2019-07-16 18:34:21 -04:00
Aman Sanger 0e9b75e5e9 Created Prober subproject and setup basic ActionHandler and its unit tests (#133)
* Initial Commit.

* Deleted unfinished features. Added ActionHandler and its Unit Tests.

* Included prober subproject in settings.gradle

* Added Protocol Class and its Basic Unit Tests

* Added Changes Suggested by jianglai

* Fixed Gitignore to take out AutoValue generated code

* Removed AutoValue java files

* Added gitignore within prober

* Removed all generated java

* Final Changes in .gitignore

* Added Ssl and WebWhois Action Handlers and their unit tests in addition to the ProbingAction class

* Fixed build.gradle changes requested

* Removed Files irrelevant to current pull request

* Minor fixes to ActionHandler, as responded in comments, removed package-info, and updated settings.gradle

* Fully Updated ActionHandler (missing updated JavaDoc)

* Added changed Protocol and both Inbound and Outbound Markers

* Removed AutoVaue ignore clause from .gitignore

* removed unneccessary dependencies in build.gradle

* Fixed Javadoc and comments for ActionHandler

* Fixed comments and JavaDoc on other files

* EOL added

* Removed Unnecessary Files

* fixed .gradle files styles

* Merge remote-tracking branch 'upstream/master'

* Removed outbound message from ActionHandler's fields and renamed Marker Interfaces

* Fixed javadoc for Marker Interfaced

* Modified Comments on ActionHandler

* Removed LocalAddress from Protocol

* Fixed Travis Build Issues
2019-07-16 10:35:14 -04:00
Lai Jiang c1207464d8 Fix a typo (#174) 2019-07-15 17:49:22 -04:00
Weimin Yu 62eab98921 Unused deps check (#171)
* Save for later

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.

* Check for unused dependencies

Add a task to check for unused dependencies in
dependencies.gradle. This file should only contain
dependencies explicitly added to a configuration
in root project or some subprojects.
2019-07-15 16:19:34 -04:00
Shicong Huang 633dd887f4 Fix permission issue in Beam pipeline deployment (#170) 2019-07-15 16:13:42 -04:00
Lai Jiang 650f1fdd52 Bump lodash from 4.17.11 to 4.17.14 (#173) 2019-07-15 11:26:12 -04:00
gbrodman b0f6a498fd Bump the version of the AppEngine Gradle plugin (#169)
* Bump the version of the AppEngine Gradle plugin

* deploy should depend on deployAll
2019-07-15 11:25:23 -04:00
gbrodman 77590dcd8e Add a metric for EPP processing time regardless of ID/TLD (#163)
* Add a metric for EPP processing time regardless of ID/TLD

* Change name to request_time

* Record EPP processing time by traffic type

* grammar

* request type

* semicolon
2019-07-11 14:28:37 -04:00
Weimin Yu 29e4d8de05 Check dependencies' open-source licenses (#165)
* Check dependencies' open-source licenses

Use jk1/Gradle-License-Report to verify that all
dependencies have open-source licenses.

Note that the following dependencies are not checked:

Dependencies of official Gradle plugins
Dependencies declared in buildscript block
Dependencies of jk1/Gradle-License-Report itself
2019-07-11 12:08:08 -04:00
Weimin Yu 242a560f20 Remove the maybeRuntime configuration (#164)
* Remove the maybeRuntime configuration

It contains dependencies present in the bazel
build but not needed for compile. We now know
they are not needed in runtime either.
2019-07-10 16:56:53 -04:00
gbrodman 3903abd9de Move and/or delete a bunch of random resources (#152) 2019-07-09 17:38:24 -04:00
Shicong Huang 8371cb838c Add a 30s timeout for all webdriver tests (#161)
Sometimes, the webdriver tests get stuck forever for no reason. It could
be some issue in the test container but it is hard to root cause it. So,
adding a 30s timeout can either trigger the retry earlier or let the
test just fail.
2019-07-09 14:42:32 -04:00
Shicong Huang 8dd6797614 Read golden images from src directly (#159)
This PR prevents Gradle from copying the golden images
to build/resources/test, so the screenshot test would
read golden images from src/test/resources directly and
display the path in test log if the test fails. Because
the path pointing to the actual file in src/ folder,
the engineer can easily find it.
2019-07-09 10:49:20 -04:00
Lai Jiang 730f108e13 Upgrade to Gradle 5.5 (#158) 2019-07-08 12:56:43 -04:00
gbrodman e5bafddd2f Move JS and CSS files to a Javascript source dir (#156) 2019-07-05 12:01:16 -04:00
Lai Jiang 82f51accbd Set beam deployment environment in GCB trigger (#157) 2019-07-03 16:28:28 -04:00
Shicong Huang 6536631857 Remove injected credentials from invoice pipeline (#155)
We got non-serialization object error when deploying the invoicing
pipeline. It turns out that Beam requires every field in the pipeline
object is serilizable. However, it is non-trivial to make
GoogleCredentialsBundle serilizable because almost all of its
dependency are not serilizable and not contraled by us. Also,
it is non-necessary to inject the credential as the spec11
pipeline also writes output to GCS without having injected
credential. So, removing the injected variable can solve the
problem.

TESTED=First reproduced the problem locally by deploying the invoicing pipeline with the previous code; applied this change and successfully deploy the pipeline without having any issue.
2019-07-03 15:12:48 -04:00
gbrodman 1be92968bf Attempt login to MosAPI via all available TLDs (#141)
* Attempt login to MosAPI via all available TLDs

There's no reason why we should need a TLD as input here because it
doesn't actually matter which one we use (they all have the same
password).

* Refactor the TLD loop and change cron jobs

* Re-throw the last exception if one exists

* Fix tests and exception

* Remove alpha cron job
2019-07-03 14:25:39 -04:00
Ben McIlwain 0564b207f2 Prevent accidentally using full Drive URL as folder ID (#144)
* Prevent accidentally using full Drive URL as folder ID
2019-07-03 14:22:15 -04:00
gbrodman 8afc4f4d3d Enforce that source files end in a newline (#153) 2019-07-03 12:16:11 -04:00
guyben13 888bc158fe Add explanation on how to use the MoSAPI endpoint (#137)
* Add explanation on how to use the MoSAPI endpoint

* Add a $ before each command so that it's clearer
2019-07-02 18:20:53 -04:00
306 changed files with 12032 additions and 1034 deletions
+3
View File
@@ -4,3 +4,6 @@ python/
.*/
repos/**
**/.idea/
*.jar
!third_party/**/*.jar
!/gradle/wrapper/**/*.jar
+6
View File
@@ -100,3 +100,9 @@ nomulus.iws
node_modules/**
!node_modules/soyutils_usegoog.js
/repos/
# Compiled JS/CSS code
core/**/registrar_bin*.js
core/**/registrar_dbg*.js
core/**/registrar_bin*.css
core/**/registrar_dbg*.css
+4
View File
@@ -0,0 +1,4 @@
extraction:
java:
prepare:
packages: "npm"
-78
View File
@@ -1,78 +0,0 @@
# Copyright 2018 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Collecting report files from a travis build to GCS requires setting the
# "CREDZ" and "REPORT_GCS_BUCKET" environment variables in your travis
# repository.
#
# The report destination can be any GCS path (e.g. "gcs://bucket-name/path").
# You'll want to select "Display value in build log", otherwise travis will
# hide the bucket name in the URL that is displayed.
#
# The CREDZ variable should be the contents of a json credentials file for
# a service account with write access to the bucket, escaped for bash shell
# usage (usually just wrapping it in single quotes should suffice).
language: java
jdk:
# Our builds fail against Oracle Java for reasons yet unknown.
- openjdk8
# Caching options suggested by a random article.
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -f $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/google-cloud-sdk/
# WebDriver tests need Chrome and ChromeDriver provisioned by the docker image
services:
- docker
env:
global:
# Disable fancy status information (looks bad on travis and exceeds logfile
# quota)
- TERM=dumb
# Do not prompt for user input when using any SDK methods.
- CLOUDSDK_CORE_DISABLE_PROMPTS=1
install:
- |
if [ ! -d $HOME/google-cloud-sdk/bin ]
then
# The install script errors if this directory already exists,
# but Travis already creates it when we mark it as cached.
rm -rf $HOME/google-cloud-sdk
# The install script is overly verbose, which sometimes causes
# problems on Travis, so ignore stdout.
curl https://sdk.cloud.google.com | bash
fi
# This line is critical. We setup the SDK to take precedence in our
# environment over the old SDK that is already on the machine.
- source $HOME/google-cloud-sdk/path.bash.inc
- gcloud components install app-engine-java
- gcloud version
# Specialize gradle build to use an up-to-date gradle and the /gradle
# directory.
# The "travis_wait 45" lets our build spend up to 45 minutes without writing
# output, instead of the default 10.
# See notes on the CREDZ and REPORT_GCS_BUCKET environment variable in the
# comments at the top of the file.
script: echo "$CREDZ" >credz.json && chmod 755 ./gradlew && travis_wait 45 ./gradlew build --continue -P uploaderDestination="$REPORT_GCS_DESTINATION" -P uploaderCredentialsFile=credz.json -P uploaderMultithreadedUpload=yes -P mavenUrl=https://storage.googleapis.com/domain-registry-maven-repository/maven -P pluginsUrl=https://storage.googleapis.com/domain-registry-maven-repository/plugins
-1
View File
@@ -1,4 +1,3 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
+3 -3
View File
@@ -1,8 +1,8 @@
# Nomulus
| Internal Build | FOSS Build | License | Code Search |
|----------------|------------|---------|-------------|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[![Build Status for the open source build](https://travis-ci.org/google/nomulus.svg?branch=master)](https://travis-ci.org/google/nomulus)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/jianglai/nomulus/blob/master/LICENSE)|[![Link to Source Graph](https://github.com/sourcegraph/sourcegraph/blob/master/ui/assets/img/sourcegraph-logo.svg)](https://sourcegraph.com/github.com/google/nomulus)|
| Internal Build | FOSS Build | LGTM | License | Code Search |
|----------------|------------|------|---------|-------------|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/internal/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[![Build Status for the open source build](https://storage.googleapis.com/domain-registry-kokoro/foss/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[![Total alerts](https://img.shields.io/lgtm/alerts/g/google/nomulus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/google/nomulus/alerts/)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Source Graph](https://github.com/sourcegraph/sourcegraph/blob/master/ui/assets/img/sourcegraph-logo.svg)](https://sourcegraph.com/github.com/google/nomulus)|
![Nomulus logo](./nomulus-logo.png)
+13 -20
View File
@@ -12,25 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
def environments = ['production', 'sandbox', 'alpha', 'crash']
def projects = ['production': 'domain-registry',
'sandbox' : 'domain-registry-sandbox',
'alpha' : 'domain-registry-alpha',
'crash' : 'domain-registry-crash']
def environment = rootProject.findProperty("environment")
if (environment == null) {
environment = 'production'
}
def gcpProject = projects[environment]
if (gcpProject == null) {
throw new GradleException("-Penvironment must be one of ${environments}.")
}
apply from: "${rootDir.path}/projects.gradle"
apply plugin: 'war'
def environment = rootProject.environment
def gcpProject = rootProject.gcpProject
// Set this directory before applying the appengine plugin so that the
// plugin will recognize this as an app-engine standard app (and also
// obtains the appengine-web.xml from the correct location)
@@ -75,7 +62,13 @@ if (project.path == ":services:default") {
appengine {
deploy {
project = gcpProject
// appengineDeployAll task requires the version to be set. So,
// this config lets gcloud select a version name when deploying
// to alpha or sandbox from our workstation.
if (!rootProject.prodOrSandboxEnv) {
version = 'GCLOUD_CONFIG'
}
projectId = gcpProject
}
}
@@ -83,6 +76,6 @@ dependencies {
compile project(':core')
}
rootProject.deploy.dependsOn appengineDeploy
rootProject.deploy.dependsOn appengineDeployAll
rootProject.stage.dependsOn appengineStage
appengineDeploy.dependsOn rootProject.verifyDeployment
appengineDeployAll.dependsOn rootProject.verifyDeployment
+76 -12
View File
@@ -13,7 +13,7 @@
// limitations under the License.
buildscript {
if (project.disableDependencyLocking.toBoolean() == false) {
if (rootProject.enableDependencyLocking.toBoolean()) {
// Lock buildscript dependencies.
configurations.classpath {
resolutionStrategy.activateDependencyLocking()
@@ -21,7 +21,7 @@ buildscript {
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.6.1"
classpath 'org.sonatype.aether:aether-api:1.13.1'
classpath 'org.sonatype.aether:aether-impl:1.13.1'
@@ -44,6 +44,12 @@ plugins {
id 'idea'
id 'com.diffplug.gradle.spotless' version '3.18.0'
id 'jacoco'
}
wrapper {
distributionType = Wrapper.DistributionType.ALL
}
apply plugin: google.registry.gradle.plugin.ReportUploaderPlugin
@@ -71,6 +77,19 @@ reportUploader {
apply from: 'dependencies.gradle'
apply from: 'dependency_lic.gradle'
// Custom task to run checkLicense in buildSrc, which is not triggered
// by root project tasks. A shell task is used because buildSrc tasks
// cannot be referenced in the same way as tasks from a regular included
// build.
task checkBuildSrcLicense(type:Exec) {
workingDir "${rootDir}/buildSrc"
commandLine '../gradlew', 'checkLicense'
}
tasks.checkLicense.dependsOn(tasks.checkBuildSrcLicense)
tasks.build.dependsOn(tasks.checkLicense)
// Provide defaults for all of the project properties.
// showAllOutput: boolean. If true, dump all test output during the build.
@@ -92,10 +111,10 @@ task deploy {
task verifyDeployment {
group = 'deployment'
description = 'Ensure that one can only deploy to alpha.'
description = 'Ensure that one cannot deploy to production or sandbox.'
doFirst {
if (rootProject.findProperty("environment") != 'alpha') {
throw new GradleException("Can only deploy to alpha.");
if (rootProject.prodOrSandboxEnv) {
throw new GradleException("Cannot deploy to production or sandbox.");
}
}
}
@@ -152,16 +171,17 @@ subprojects {
}
}
if (rootProject.disableDependencyLocking.toBoolean() == false) {
if (rootProject.enableDependencyLocking.toBoolean()) {
buildscript {
// Lock buildscript dependencies.
configurations.classpath {
resolutionStrategy.activateDependencyLocking()
}
}
// Lock application dependencies.
dependencyLocking {
lockAllConfigurations()
// Lock application dependencies except for the gradle-license-report
// plugin. See dependency_lic.gradle for more information.
configurations.findAll { it.name != 'dependencyLicenseReport' }.each {
it.resolutionStrategy.activateDependencyLocking()
}
}
@@ -218,9 +238,7 @@ subprojects {
}
}
if (project.name == 'util') return
if (project.name == 'proxy') return
if (project.name == 'core') return
if (['util', 'proxy', 'core', 'prober'].contains(project.name)) return
test {
testLogging.showStandardStreams = Boolean.parseBoolean(showAllOutput)
@@ -237,3 +255,49 @@ subprojects {
}
}
}
task checkDependenciesDotGradle {
def buildSrcDepsFile = File.createTempFile('buildSrc', 'deps')
buildSrcDepsFile.deleteOnExit()
dependsOn createGetBuildSrcDirectDepsTask(buildSrcDepsFile)
doLast {
Set<String> depsInUse = []
allprojects {
configurations.all {
it.dependencies.findAll { it.group != null }.each {
// Note: .toString() is required since GString should
// not be mixed with Java Strings.
depsInUse.add("${it.group}:${it.name}".toString())
}
}
}
if (buildSrcDepsFile.exists()) {
depsInUse.addAll(buildSrcDepsFile.readLines())
}
def unusedDeps =
rootProject.dependencyMap.keySet()
.findAll { !depsInUse.contains(it) }
.toSorted()
if (unusedDeps.isEmpty()) {
return
}
logger.error(
"Unused dependencies in dependencies.gradle:\n${unusedDeps.toListString()}")
throw new IllegalStateException(
"The dependencies.gradle file should only contain direct dependencies.")
}
}
tasks.build.dependsOn(tasks.checkDependenciesDotGradle)
def createGetBuildSrcDirectDepsTask(outputFileName) {
return tasks
.create(
"getBuildSrcDeps_${java.util.UUID.randomUUID()}".toString(),
Exec) {
workingDir "${rootDir}/buildSrc"
commandLine '../gradlew', 'exportDenpendencies',
"-PdependencyExportFile=${outputFileName}"
}
}
+21 -2
View File
@@ -13,7 +13,7 @@
// limitations under the License.
buildscript {
if (rootProject.disableDependencyLocking.toBoolean() == false) {
if (project.enableDependencyLocking.toBoolean()) {
// Lock buildscript dependencies.
configurations.classpath {
resolutionStrategy.activateDependencyLocking()
@@ -32,7 +32,7 @@ plugins {
id 'com.diffplug.gradle.spotless' version '3.18.0'
}
if (rootProject.disableDependencyLocking.toBoolean() == false) {
if (rootProject.enableDependencyLocking.toBoolean()) {
// Lock application dependencies.
dependencyLocking {
lockAllConfigurations()
@@ -52,6 +52,7 @@ repositories {
}
apply from: '../dependencies.gradle'
apply from: '../dependency_lic.gradle'
apply from: '../java_common.gradle'
sourceSets {
@@ -88,3 +89,21 @@ gradle.projectsEvaluated {
options.compilerArgs << "-Xlint:unchecked"
}
}
task exportDenpendencies {
def outputFileProperty = 'dependencyExportFile'
def output = project.hasProperty(outputFileProperty)
? new PrintStream(
new File(project.getProperty(outputFileProperty)))
: System.out
doLast {
project.configurations.all {
it.dependencies.findAll {
it.group != null
}.each {
output.println("${it.group}:${it.name}")
}
}
}
}
+1 -1
View File
@@ -1 +1 @@
disableDependencyLocking=false
enableDependencyLocking=false
@@ -0,0 +1,187 @@
{
"allowedLicenses": [
{
"moduleLicense": "Apache Software License, Version 1.1"
},
{
"moduleLicense": "Apache 2"
},
{
"moduleLicense": "Apache 2.0"
},
{
"moduleLicense": "Apache-2.0"
},
{
"moduleLicense": "Apache License 2.0"
},
{
"moduleLicense": "Apache License v2.0"
},
{
"moduleLicense": "Apache License, Version 2.0"
},
{
"moduleLicense": "Apache Software License - Version 2.0"
},
{
"moduleLicense": "The Apache License, Version 2.0"
},
{
"moduleLicense": "The Apache Software License, Version 2.0"
},
{
"moduleLicense": "The Apache Software License, version 2.0"
},
{
"moduleLicense": "Bouncy Castle Licence"
},
{
"moduleLicense": "BSD"
},
{
"moduleLicense": "BSD-2-Clause"
},
{
"moduleLicense": "BSD 2-Clause License"
},
{
"moduleLicense": "BSD 2-Clause license"
},
{
"moduleLicense": "BSD 3-clause"
},
{
"moduleLicense": "BSD 3-Clause"
},
{
"moduleLicense": "BSD 3-Clause License"
},
{
"moduleLicense": "BSD 3-clause New License"
},
{
"moduleLicense": "The 3-Clause BSD License"
},
{
"moduleLicense": "BSD License"
},
{
"moduleLicense": "BSD New License"
},
{
"moduleLicense": "BSD New license"
},
{
"moduleLicense": "BSD style"
},
{
"moduleLicense": "New BSD License"
},
{
"moduleLicense": "Revised BSD"
},
{
"moduleLicense": "The BSD License"
},
{
"moduleLicense": "CC0 1.0 Universal License"
},
{
"moduleLicense": "CDDL 1.1"
},
{
"moduleLicense": "CDDL + GPLv2 with classpath exception"
},
{
"moduleLicense": "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0"
},
{
"moduleLicense": "https://glassfish.java.net/public/CDDL+GPL_1_1.html, https://glassfish.java.net/public/CDDL+GPL_1_1.html"
},
{
"moduleLicense": "CDDL+GPL License"
},
{
"moduleLicense": "\\n Dual license consisting of the CDDL v1.1 and GPL v2\\n "
},
{
"moduleLicense": "Eclipse Public License - Version 1.0"
},
{
"moduleLicense": "Eclipse Public License - v 1.0"
},
{
"moduleLicense": "Eclipse Public License 1.0"
},
{
"moduleLicense": "Eclipse Public License v1.0"
},
{
"moduleLicense": "Google App Engine Terms of Service"
},
{
"moduleLicense": "GNU General Public License, version 2, with the Classpath Exception"
},
{
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
},
{
"moduleLicense": "GNU Library General Public License v2.1 or later"
},
{
"moduleLicense": "GPL2 w/ CPE"
},
{
"moduleLicense": "GNU Lesser Public License"
},
{
"moduleLicense": "The Go license"
},
{
"moduleLicense": "GWT Terms"
},
{
"moduleLicense": "ICU License"
},
{
"moduleLicense": "The JSON License"
},
{
"moduleLicense": "LGPL-2.1+"
},
{
"moduleLicense": "LGPL, version 2.1"
},
{
"moduleLicense": "MIT"
},
{
"moduleLicense": "MIT License"
},
{
"moduleLicense": "MIT license"
},
{
"moduleLicense": "The MIT License"
},
{
"moduleLicense": "The MIT license"
},
{
"moduleLicense": "The PostgreSQL License"
},
{
"moduleLicense": "Mozilla Public License Version 2.0"
},
{
"moduleLicense": "Public Domain"
},
{
"moduleLicense": "PUBLIC DOMAIN"
},
{
"moduleLicense": "The W3C Software License"
}
]
}
@@ -0,0 +1,32 @@
{
"bundles" : [
{
"bundleName" : "Apache 2.0",
"licenseName" : "Apache 2.0",
"licenseUrl" : "http://www.apache.org/licenses/LICENSE-2.0"
},
{
"bundleName" : "MIT License",
"licenseName" : "MIT License",
"licenseUrl" : "http://www.opensource.org/licenses/mit-license.php"
}
],
"transformationRules" : [
{
"bundleName" : "Apache 2.0",
"licenseUrlPattern" : "http://www.apache.org/licenses/LICENSE-2.0"
},
{
"bundleName" : "Apache 2.0",
"licenseUrlPattern" : "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"bundleName" : "MIT License",
"licenseUrlPattern" : "http://www.opensource.org/licenses/mit-license.php"
},
{
"bundleName" : "MIT License",
"licenseUrlPattern" : "http://www.opensource.org/licenses/MIT"
}
]
}
+8 -4
View File
@@ -78,10 +78,15 @@ PRESUBMITS = {
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
("java", "js", "soy", "sql", "py", "sh", "gradle"), {
".git", "/build/", "/generated/", "node_modules/",
"JUnitBackports.java"
"JUnitBackports.java", "registrar_bin.", "registrar_dbg."
}, REQUIRED):
"File did not include the license header.",
# Files must end in a newline
PresubmitCheck(r".*\n$", ("java", "js", "soy", "sql", "py", "sh", "gradle"),
{"node_modules/"}, REQUIRED):
"Source files must end in a newline.",
# System.(out|err).println should only appear in tools/
PresubmitCheck(
r".*\bSystem\.(out|err)\.print", "java", {
@@ -143,7 +148,7 @@ PRESUBMITS = {
PresubmitCheck(
r".*(innerHTML|outerHTML)\s*(=|[+]=)([^=]|$)",
"js",
{"/node_modules/"},
{"/node_modules/", "registrar_bin."},
):
"Do not assign directly to the dom. Use goog.dom.setTextContent to set"
" to plain text, goog.dom.removeChildren to clear, or "
@@ -151,14 +156,13 @@ PRESUBMITS = {
PresubmitCheck(
r".*console\.(log|info|warn|error)",
"js",
{"/node_modules/", "google/registry/ui/js/util.js"},
{"/node_modules/", "google/registry/ui/js/util.js", "registrar_bin."},
):
"JavaScript files should not include console logging."
}
def get_files():
result = []
for root, dirnames, filenames in os.walk("."):
for filename in filenames:
yield os.path.join(root, filename)
+3
View File
@@ -0,0 +1,3 @@
FROM gcr.io/distroless/java:debug
ADD build/libs/nomulus.jar /nomulus.jar
ENTRYPOINT ["/usr/bin/java", "-jar", "/nomulus.jar"]
+31 -69
View File
@@ -25,6 +25,7 @@ def screenshotsForGoldensDir = "${project.buildDir}/screenshots_for_goldens"
def newGoldensDir = "${project.buildDir}/new_golden_images"
def goldensDir =
"${javaTestDir}/google/registry/webdriver/goldens/chrome-linux"
def jsDir = "${project.projectDir}/src/main/javascript"
// Tests that conflict with (mostly unidentified) members of the main test
// suite. It is unclear if they are offenders (i.e., those that pollute global
@@ -96,14 +97,14 @@ sourceSets {
}
}
processTestResources {
exclude '**/webdriver/*'
}
configurations {
css
jaxb
soy
// Label for all dependencies inherited from Bazel build but not used in
// either compile or testRuntime. However, they may be needed at runtime.
// TODO(weiminyu): identify runtime dependencies and remove the rest.
maybeRuntime
closureCompiler
// Exclude non-canonical servlet-api jars. Our AppEngine deployment uses
@@ -139,53 +140,38 @@ dependencies {
"${rootDir}/third_party/objectify/v4_1/objectify-4.1.3.jar")
testImplementation project(':third_party')
testRuntime files(sourceSets.test.resources.srcDirs)
compile deps['com.beust:jcommander']
compile deps['com.google.api-client:google-api-client']
maybeRuntime deps['com.google.api-client:google-api-client-appengine']
maybeRuntime deps['com.google.api-client:google-api-client-jackson2']
compile deps['com.google.monitoring-client:metrics']
compile deps['com.google.monitoring-client:stackdriver']
compile deps['com.google.api-client:google-api-client-java6']
maybeRuntime deps['com.google.api-client:google-api-client-servlet']
compile deps['com.google.apis:google-api-services-admin-directory']
compile deps['com.google.apis:google-api-services-appengine']
compile deps['com.google.apis:google-api-services-bigquery']
maybeRuntime deps['com.google.apis:google-api-services-clouddebugger']
compile deps['com.google.apis:google-api-services-cloudkms']
maybeRuntime deps['com.google.apis:google-api-services-cloudresourcemanager']
compile deps['com.google.apis:google-api-services-dataflow']
compile deps['com.google.apis:google-api-services-dns']
compile deps['com.google.apis:google-api-services-drive']
compile deps['com.google.apis:google-api-services-groupssettings']
compile deps['com.google.apis:google-api-services-monitoring']
compile deps['com.google.apis:google-api-services-sheets']
maybeRuntime deps['com.google.apis:google-api-services-storage']
testCompileOnly deps['com.google.appengine:appengine-api-1.0-sdk']
maybeRuntime deps['com.google.appengine:appengine-api-labs']
maybeRuntime deps['com.google.appengine:appengine-api-stubs']
testCompile deps['com.google.appengine:appengine-api-stubs']
compile deps['com.google.appengine.tools:appengine-gcs-client']
compile deps['com.google.appengine.tools:appengine-mapreduce']
compile deps['com.google.appengine.tools:appengine-pipeline']
compile deps['com.google.appengine:appengine-remote-api']
maybeRuntime deps['com.google.appengine:appengine-tools-sdk']
compile deps['com.google.auth:google-auth-library-credentials']
compile deps['com.google.auth:google-auth-library-oauth2-http']
maybeRuntime deps['com.google.auto:auto-common']
maybeRuntime deps['com.google.auto.factory:auto-factory']
compile deps['com.google.code.gson:gson']
compile deps['com.google.auto.value:auto-value-annotations']
maybeRuntime deps['com.google.cloud.bigdataoss:gcsio']
maybeRuntime deps['com.google.cloud.bigdataoss:util']
compile deps['com.google.code.findbugs:jsr305']
compile deps['com.google.dagger:dagger']
maybeRuntime deps['com.google.dagger:dagger-producers']
compile deps['com.google.errorprone:error_prone_annotations']
maybeRuntime deps['com.google.errorprone:javac-shaded']
compile deps['com.google.flogger:flogger']
runtime deps['com.google.flogger:flogger-system-backend']
maybeRuntime deps['com.google.gdata:core']
maybeRuntime deps['com.google.googlejavaformat:google-java-format']
compile deps['com.google.guava:guava']
gradleLint.ignore('unused-dependency') {
compile deps['com.google.gwt:gwt-user']
@@ -194,89 +180,48 @@ dependencies {
compile deps['com.google.http-client:google-http-client-appengine']
compile deps['com.google.http-client:google-http-client-jackson2']
compile deps['com.google.oauth-client:google-oauth-client']
maybeRuntime deps['com.google.oauth-client:google-oauth-client-appengine']
compile deps['com.google.oauth-client:google-oauth-client-java6']
compile deps['com.google.oauth-client:google-oauth-client-jetty']
maybeRuntime deps['com.google.oauth-client:google-oauth-client-servlet']
maybeRuntime deps['com.google.protobuf:protobuf-java']
compile deps['com.google.re2j:re2j']
compile deps['com.google.template:soy']
maybeRuntime deps['com.googlecode.charts4j:charts4j']
compile deps['com.googlecode.json-simple:json-simple']
compile deps['com.jcraft:jsch']
maybeRuntime deps['com.jcraft:jzlib']
maybeRuntime deps['com.squareup:javapoet']
maybeRuntime deps['com.squareup:javawriter']
maybeRuntime deps['com.sun.activation:javax.activation']
maybeRuntime deps['com.thoughtworks.paranamer:paranamer']
testCompile deps['com.thoughtworks.qdox:qdox']
maybeRuntime deps['commons-codec:commons-codec']
maybeRuntime deps['commons-logging:commons-logging']
compile deps['dnsjava:dnsjava']
maybeRuntime deps['io.netty:netty-buffer']
maybeRuntime deps['io.netty:netty-codec']
maybeRuntime deps['io.netty:netty-codec-http']
maybeRuntime deps['io.netty:netty-common']
maybeRuntime deps['io.netty:netty-handler']
maybeRuntime deps['io.netty:netty-resolver']
maybeRuntime deps['io.netty:netty-tcnative']
maybeRuntime deps['io.netty:netty-tcnative-boringssl-static']
maybeRuntime deps['io.netty:netty-transport']
maybeRuntime deps['it.unimi.dsi:fastutil']
maybeRuntime deps['javax.annotation:jsr250-api']
runtime deps['org.glassfish.jaxb:jaxb-runtime']
testCompile deps['javax.annotation:jsr250-api']
compile deps['javax.inject:javax.inject']
compile deps['javax.mail:mail']
compile deps['javax.servlet:servlet-api']
compile deps['javax.xml.bind:jaxb-api']
maybeRuntime deps['javax.xml.soap:javax.xml.soap-api']
compile deps['jline:jline']
compile deps['joda-time:joda-time']
compile deps['org.apache.avro:avro']
maybeRuntime deps['org.apache.beam:beam-runners-direct-java']
testCompile deps['org.apache.beam:beam-runners-direct-java']
compile deps['org.apache.beam:beam-runners-google-cloud-dataflow-java']
maybeRuntime deps['org.apache.beam:beam-sdks-common-runner-api']
compile deps['org.apache.beam:beam-sdks-java-core']
compile deps['org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core']
compile deps['org.apache.beam:beam-sdks-java-io-google-cloud-platform']
maybeRuntime deps['org.apache.commons:commons-compress']
testCompile deps['org.apache.commons:commons-text']
maybeRuntime deps['org.apache.ftpserver:ftplet-api']
testCompile deps['org.apache.ftpserver:ftplet-api']
maybeRuntime deps['org.apache.ftpserver:ftpserver-core']
testCompile deps['org.apache.ftpserver:ftpserver-core']
compile deps['org.apache.httpcomponents:httpclient']
compile deps['org.apache.httpcomponents:httpcore']
maybeRuntime deps['org.apache.mina:mina-core']
maybeRuntime deps['org.apache.sshd:sshd-core']
testCompile deps['org.apache.sshd:sshd-core']
maybeRuntime deps['org.apache.sshd:sshd-scp']
testCompile deps['org.apache.sshd:sshd-scp']
maybeRuntime deps['org.apache.sshd:sshd-sftp']
testCompile deps['org.apache.sshd:sshd-sftp']
maybeRuntime deps['org.apache.tomcat:tomcat-annotations-api']
testCompile deps['org.apache.tomcat:tomcat-annotations-api']
compile deps['org.bouncycastle:bcpg-jdk15on']
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
compile deps['org.bouncycastle:bcprov-jdk15on']
maybeRuntime deps['org.codehaus.jackson:jackson-core-asl']
maybeRuntime deps['org.codehaus.jackson:jackson-mapper-asl']
compile deps['org.joda:joda-money']
compile deps['org.json:json']
maybeRuntime deps['org.khronos:opengl-api']
maybeRuntime deps['org.mortbay.jetty:jetty']
testCompile deps['org.mortbay.jetty:jetty']
maybeRuntime deps['org.mortbay.jetty:jetty-util']
testCompile deps['org.seleniumhq.selenium:selenium-api']
testCompile deps['org.seleniumhq.selenium:selenium-chrome-driver']
testCompile deps['org.seleniumhq.selenium:selenium-java']
testCompile deps['org.seleniumhq.selenium:selenium-remote-driver']
maybeRuntime deps['org.slf4j:slf4j-api']
testCompile deps['org.testcontainers:selenium']
maybeRuntime deps['org.tukaani:xz']
maybeRuntime deps['org.xerial.snappy:snappy-java']
compile deps['xerces:xmlParserAPIs']
compile deps['xpp3:xpp3']
@@ -302,8 +247,10 @@ dependencies {
testCompile deps['org.hamcrest:hamcrest-all']
testCompile deps['org.hamcrest:hamcrest-core']
testCompile deps['org.hamcrest:hamcrest-library']
compile deps['org.hibernate:hibernate-core']
testCompile deps['junit:junit']
testCompile deps['org.mockito:mockito-core']
runtime deps['org.postgresql:postgresql']
// Indirect dependency found by undeclared-dependency check. Such
// dependencies should go after all other compile and testCompile
@@ -480,7 +427,7 @@ task soyToJS {
}
task stylesheetsToJavascript {
def cssSourceDir = "${javaDir}/google/registry/ui/css"
def cssSourceDir = "${jsDir}/google/registry/ui/css"
def outputDir = "${resourcesDir}/google/registry/ui/css"
inputs.dir cssSourceDir
outputs.dir outputDir
@@ -533,8 +480,8 @@ task compileProdJS(type: JavaExec) {
def outputDir = "${resourcesDir}/google/registry/ui"
def nodeModulesDir = "${rootDir}/node_modules"
def cssSourceDir = "${resourcesDir}/google/registry/ui/css"
def jsSourceDir = "${javaDir}/google/registry/ui/js"
def externsDir = "${javaDir}/google/registry/ui/externs"
def jsSourceDir = "${jsDir}/google/registry/ui/js"
def externsDir = "${jsDir}/google/registry/ui/externs"
def soySourceDir = "${generatedDir}/google/registry/ui/soy"
[nodeModulesDir, cssSourceDir, jsSourceDir, externsDir, soySourceDir].each {
@@ -700,10 +647,25 @@ test {
}.dependsOn(fragileTest, outcastTest)
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
createUberJar('gtechTool', 'gtech_tool', 'google.registry.tools.GtechTool')
project.nomulus.dependsOn project(':third_party').jar
project.gtechTool.dependsOn project(':third_party').jar
project.build.dependsOn nomulus
project.build.dependsOn gtechTool
task buildToolImage(dependsOn: nomulus, type: Exec) {
commandLine 'docker', 'build', '-t', 'nomulus-tool', '.'
}
task copyJsFilesForTestServer(dependsOn: assemble, type: Copy) {
// Unfortunately the test server relies on having some compiled JS/CSS
// in place, so copy it over here
from "${resourcesDir}/google/registry/ui/"
include '**/*.js'
include '**/*.css'
into "${project.projectDir}/src/main/resources/google/registry/ui/"
}
task runTestServer(dependsOn: copyJsFilesForTestServer, type: JavaExec) {
main = 'google.registry.server.RegistryTestServerMain'
classpath = sourceSets.test.runtimeClasspath
}
project.build.dependsOn buildToolImage
project.build.dependsOn ':stage'
@@ -19,6 +19,7 @@ import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
import static google.registry.backup.ExportCommitLogDiffAction.LOWER_CHECKPOINT_TIME_PARAM;
import static google.registry.backup.ExportCommitLogDiffAction.UPPER_CHECKPOINT_TIME_PARAM;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import com.google.common.flogger.FluentLogger;
@@ -63,7 +64,7 @@ public final class CommitLogCheckpointAction implements Runnable {
final CommitLogCheckpoint checkpoint = strategy.computeCheckpoint();
logger.atInfo().log(
"Generated candidate checkpoint for time: %s", checkpoint.getCheckpointTime());
ofy()
tm()
.transact(
() -> {
DateTime lastWrittenTime = CommitLogCheckpointRoot.loadRoot().getLastWrittenTime();
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
@@ -276,7 +277,7 @@ public final class DeleteOldCommitLogsAction implements Runnable {
return;
}
DeletionResult deletionResult = ofy().transactNew(() -> {
DeletionResult deletionResult = tm().transactNew(() -> {
CommitLogManifest manifest = ofy().load().key(manifestKey).now();
// It is possible that the same manifestKey was run twice, if a shard had to be restarted
// or some weird failure. If this happens, we want to exit immediately.
@@ -39,6 +39,7 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_DELETE;
import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_DELETE_FAILURE;
import static google.registry.model.reporting.HistoryEntry.Type.HOST_DELETE;
import static google.registry.model.reporting.HistoryEntry.Type.HOST_DELETE_FAILURE;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.model.transfer.TransferStatus.SERVER_CANCELLED;
import static java.math.RoundingMode.CEILING;
import static java.util.concurrent.TimeUnit.DAYS;
@@ -308,7 +309,7 @@ public class DeleteContactsAndHostsAction implements Runnable {
final boolean hasNoActiveReferences = !Iterators.contains(values, true);
logger.atInfo().log("Processing async deletion request for %s", deletionRequest.key());
DeletionResult result =
ofy()
tm()
.transactNew(
() -> {
DeletionResult deletionResult =
@@ -329,7 +330,7 @@ public class DeleteContactsAndHostsAction implements Runnable {
private DeletionResult attemptToDeleteResource(
DeletionRequest deletionRequest, boolean hasNoActiveReferences) {
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
EppResource resource =
ofy().load().key(deletionRequest.key()).now().cloneProjectedAtTime(now);
// Double-check transactionally that the resource is still active and in PENDING_DELETE.
@@ -19,6 +19,7 @@ import static google.registry.config.RegistryEnvironment.PRODUCTION;
import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN;
import static google.registry.mapreduce.inputs.EppResourceInputs.createEntityInput;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import com.google.appengine.tools.mapreduce.Mapper;
@@ -124,7 +125,7 @@ public class DeleteLoadTestDataAction implements Runnable {
Key.create(EppResourceIndex.create(Key.create(resource)));
final Key<? extends ForeignKeyIndex<?>> fki = ForeignKeyIndex.createKey(resource);
int numEntitiesDeleted =
ofy()
tm()
.transact(
() -> {
// This ancestor query selects all descendant entities.
@@ -23,6 +23,7 @@ import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexD
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.getTldsOfType;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_TLDS;
import static org.joda.time.DateTimeZone.UTC;
@@ -219,7 +220,7 @@ public class DeleteProberDataAction implements Runnable {
final Key<? extends ForeignKeyIndex<?>> fki = ForeignKeyIndex.createKey(domain);
int entitiesDeleted =
ofy()
tm()
.transact(
() -> {
// This ancestor query selects all descendant HistoryEntries, BillingEvents,
@@ -245,16 +246,16 @@ public class DeleteProberDataAction implements Runnable {
}
private void softDeleteDomain(final DomainBase domain) {
ofy().transactNew(() -> {
tm().transactNew(() -> {
DomainBase deletedDomain = domain
.asBuilder()
.setDeletionTime(ofy().getTransactionTime())
.setDeletionTime(tm().getTransactionTime())
.setStatusValues(null)
.build();
HistoryEntry historyEntry = new HistoryEntry.Builder()
.setParent(domain)
.setType(DOMAIN_DELETE)
.setModificationTime(ofy().getTransactionTime())
.setModificationTime(tm().getTransactionTime())
.setBySuperuser(true)
.setReason("Deletion of prober data")
.setClientId(registryAdminClientId)
@@ -23,6 +23,7 @@ import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
import static google.registry.model.domain.Period.Unit.YEARS;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_AUTORENEW;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
@@ -150,7 +151,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
}
int numBillingEventsSaved = 0;
try {
numBillingEventsSaved = ofy().transactNew(() -> {
numBillingEventsSaved = tm().transactNew(() -> {
ImmutableSet.Builder<OneTime> syntheticOneTimesBuilder =
new ImmutableSet.Builder<>();
final Registry tld = Registry.get(getTldFromDomainName(recurring.getTargetId()));
@@ -183,7 +184,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
HistoryEntry historyEntry = new HistoryEntry.Builder()
.setBySuperuser(false)
.setClientId(recurring.getClientId())
.setModificationTime(ofy().getTransactionTime())
.setModificationTime(tm().getTransactionTime())
.setParent(domainKey)
.setPeriod(Period.create(1, YEARS))
.setReason("Domain autorenewal by ExpandRecurringBillingEventsAction")
@@ -308,7 +309,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
logger.atInfo().log(
"Recurring event expansion %s complete for billing event range [%s, %s).",
isDryRun ? "(dry run) " : "", cursorTime, executionTime);
ofy()
tm()
.transact(
() -> {
Cursor cursor = ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now();
@@ -15,6 +15,7 @@
package google.registry.batch;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.appengine.tools.mapreduce.Mapper;
import com.google.common.collect.ImmutableList;
@@ -69,7 +70,7 @@ public class ResaveAllEppResourcesAction implements Runnable {
@Override
public final void map(final Key<EppResource> resourceKey) {
ofy()
tm()
.transact(
() -> {
EppResource projectedResource =
@@ -77,7 +78,7 @@ public class ResaveAllEppResourcesAction implements Runnable {
.load()
.key(resourceKey)
.now()
.cloneProjectedAtTime(ofy().getTransactionTime());
.cloneProjectedAtTime(tm().getTransactionTime());
ofy().save().entity(projectedResource).now();
});
getContext().incrementCounter(String.format("%s entities re-saved", resourceKey.getKind()));
@@ -18,6 +18,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESAVE_TIMES;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
@@ -73,11 +74,11 @@ public class ResaveEntityAction implements Runnable {
public void run() {
logger.atInfo().log(
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
ofy().transact(() -> {
tm().transact(() -> {
ImmutableObject entity = ofy().load().key(resourceKey).now();
ofy().save().entity(
(entity instanceof EppResource)
? ((EppResource) entity).cloneProjectedAtTime(ofy().getTransactionTime()) : entity
? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime()) : entity
);
if (!resaveTimes.isEmpty()) {
asyncTaskEnqueuer.enqueueAsyncResave(entity, requestedTime, resaveTimes);
@@ -14,6 +14,7 @@
package google.registry.beam.invoicing;
import com.google.auth.oauth2.GoogleCredentials;
import google.registry.beam.invoicing.BillingEvent.InvoiceGroupingKey;
import google.registry.beam.invoicing.BillingEvent.InvoiceGroupingKey.InvoiceGroupingKeyCoder;
import google.registry.config.CredentialModule.LocalCredential;
@@ -57,35 +58,31 @@ import org.apache.beam.sdk.values.TypeDescriptors;
*/
public class InvoicingPipeline implements Serializable {
@Inject
@Config("projectId")
String projectId;
private final String projectId;
private final String beamBucketUrl;
private final String invoiceTemplateUrl;
private final String beamStagingUrl;
private final String billingBucketUrl;
private final String invoiceFilePrefix;
private final GoogleCredentials googleCredentials;
@Inject
@Config("apacheBeamBucketUrl")
String beamBucketUrl;
@Inject
@Config("invoiceTemplateUrl")
String invoiceTemplateUrl;
@Inject
@Config("beamStagingUrl")
String beamStagingUrl;
@Inject
@Config("billingBucketUrl")
String billingBucketUrl;
@Inject
@Config("invoiceFilePrefix")
String invoiceFilePrefix;
@Inject @LocalCredential
GoogleCredentialsBundle credentialsBundle;
@Inject
InvoicingPipeline() {}
public InvoicingPipeline(
@Config("projectId") String projectId,
@Config("apacheBeamBucketUrl") String beamBucketUrl,
@Config("invoiceTemplateUrl") String invoiceTemplateUrl,
@Config("beamStagingUrl") String beamStagingUrl,
@Config("billingBucketUrl") String billingBucketUrl,
@Config("invoiceFilePrefix") String invoiceFilePrefix,
@LocalCredential GoogleCredentialsBundle googleCredentialsBundle) {
this.projectId = projectId;
this.beamBucketUrl = beamBucketUrl;
this.invoiceTemplateUrl = invoiceTemplateUrl;
this.beamStagingUrl = beamStagingUrl;
this.billingBucketUrl = billingBucketUrl;
this.invoiceFilePrefix = invoiceFilePrefix;
this.googleCredentials = googleCredentialsBundle.getGoogleCredentials();
}
/** Custom options for running the invoicing pipeline. */
interface InvoicingPipelineOptions extends DataflowPipelineOptions {
@@ -105,12 +102,15 @@ public class InvoicingPipeline implements Serializable {
public void deploy() {
// We can't store options as a member variable due to serialization concerns.
InvoicingPipelineOptions options = PipelineOptionsFactory.as(InvoicingPipelineOptions.class);
options.setGcpCredential(credentialsBundle.getGoogleCredentials());
options.setProject(projectId);
options.setRunner(DataflowRunner.class);
// This causes p.run() to stage the pipeline as a template on GCS, as opposed to running it.
options.setTemplateLocation(invoiceTemplateUrl);
options.setStagingLocation(beamStagingUrl);
// This credential is used when Dataflow deploys the template to GCS in target GCP project.
// So, make sure the credential has write permission to GCS in that project.
options.setGcpCredential(googleCredentials);
Pipeline p = Pipeline.create(options);
PCollection<BillingEvent> billingEvents =
@@ -17,9 +17,12 @@ package google.registry.beam.spec11;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.beam.BeamUtils.getQueryFromFile;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auto.value.AutoValue;
import google.registry.beam.spec11.SafeBrowsingTransforms.EvaluateSafeBrowsingFn;
import google.registry.config.CredentialModule.LocalCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.GoogleCredentialsBundle;
import google.registry.util.Retrier;
import google.registry.util.SqlTemplate;
import java.io.Serializable;
@@ -77,26 +80,29 @@ public class Spec11Pipeline implements Serializable {
/** The JSON object field we put the threat match array for Spec11 reports. */
public static final String THREAT_MATCHES_FIELD = "threatMatches";
@Inject
@Config("projectId")
String projectId;
private final String projectId;
private final String beamStagingUrl;
private final String spec11TemplateUrl;
private final String reportingBucketUrl;
private final GoogleCredentials googleCredentials;
private final Retrier retrier;
@Inject
@Config("beamStagingUrl")
String beamStagingUrl;
@Inject
@Config("spec11TemplateUrl")
String spec11TemplateUrl;
@Inject
@Config("reportingBucketUrl")
String reportingBucketUrl;
@Inject Retrier retrier;
@Inject
Spec11Pipeline() {}
public Spec11Pipeline(
@Config("projectId") String projectId,
@Config("beamStagingUrl") String beamStagingUrl,
@Config("spec11TemplateUrl") String spec11TemplateUrl,
@Config("reportingBucketUrl") String reportingBucketUrl,
@LocalCredential GoogleCredentialsBundle googleCredentialsBundle,
Retrier retrier
) {
this.projectId = projectId;
this.beamStagingUrl = beamStagingUrl;
this.spec11TemplateUrl = spec11TemplateUrl;
this.reportingBucketUrl = reportingBucketUrl;
this.googleCredentials = googleCredentialsBundle.getGoogleCredentials();
this.retrier = retrier;
}
/** Custom options for running the spec11 pipeline. */
interface Spec11PipelineOptions extends DataflowPipelineOptions {
@@ -134,6 +140,9 @@ public class Spec11Pipeline implements Serializable {
// This causes p.run() to stage the pipeline as a template on GCS, as opposed to running it.
options.setTemplateLocation(spec11TemplateUrl);
options.setStagingLocation(beamStagingUrl);
// This credential is used when Dataflow deploys the template to GCS in target GCP project.
// So, make sure the credential has write permission to GCS in that project.
options.setGcpCredential(googleCredentials);
Pipeline p = Pipeline.create(options);
PCollection<Subdomain> domains =
@@ -16,6 +16,7 @@ package google.registry.config;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.collect.ImmutableList;
import dagger.Module;
@@ -68,6 +69,29 @@ public abstract class CredentialModule {
return GoogleCredentialsBundle.create(credential);
}
/**
* Provides the default {@link GoogleCredential} from the Google Cloud runtime for G Suite
* Drive API.
* TODO(b/138195359): Deprecate this credential once we figure out how to use
* {@link GoogleCredentials} for G Suite Drive API.
*/
@GSuiteDriveCredential
@Provides
@Singleton
public static GoogleCredential provideGSuiteDriveCredential(
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes) {
GoogleCredential credential;
try {
credential = GoogleCredential.getApplicationDefault();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (credential.createScopedRequired()) {
credential = credential.createScoped(requiredScopes);
}
return credential;
}
/**
* Provides a {@link GoogleCredentialsBundle} from the service account's JSON key file.
*
@@ -118,6 +142,13 @@ public abstract class CredentialModule {
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultCredential {}
/** Dagger qualifier for the credential for G Suite Drive API. */
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface GSuiteDriveCredential {}
/**
* Dagger qualifier for a credential from a service account's JSON key, to be used in non-request
* threads.
@@ -894,9 +894,9 @@ public final class RegistryConfig {
* @see google.registry.reporting.spec11.Spec11EmailUtils
*/
@Provides
@Config("spec11ReplyToEmailAddress")
public static InternetAddress provideSpec11ReplyToEmailAddress(RegistryConfigSettings config) {
return parseEmailAddress(config.misc.spec11ReplyToEmailAddress);
@Config("spec11OutgoingEmailAddress")
public static InternetAddress provideSpec11OutgoingEmailAddress(RegistryConfigSettings config) {
return parseEmailAddress(config.misc.spec11OutgoingEmailAddress);
}
/**
@@ -173,7 +173,7 @@ public class RegistryConfigSettings {
public static class Misc {
public String sheetExportId;
public String alertRecipientEmailAddress;
public String spec11ReplyToEmailAddress;
public String spec11OutgoingEmailAddress;
public int asyncDeleteDelaySeconds;
public int transientFailureRetries;
}
@@ -357,9 +357,9 @@ misc:
# Address we send alert summary emails to.
alertRecipientEmailAddress: email@example.com
# Address to which the Spec 11 emails to registrars should be replied. This needs
# to be a deliverable email address in case the registrars want to contact us.
spec11ReplyToEmailAddress: reply-to@example.com
# Address from which Spec 11 emails to registrars are sent. This needs
# to be a deliverable email address to handle replies from registrars as well.
spec11OutgoingEmailAddress: abuse@example.com
# How long to delay processing of asynchronous deletions. This should always
# be longer than eppResourceCachingSeconds, to prevent deleted contacts or
@@ -13,11 +13,6 @@
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>backend-servlet</servlet-name>
<url-pattern>/_dr/task/metrics</url-pattern>
</servlet-mapping>
<!-- RDE -->
<!--
@@ -112,8 +112,6 @@
<target>backend</target>
</cron>
<!--
TODO(b/134576418) enable this cron job once we're sure the Action works
<cron>
<url><![CDATA[/_dr/task/updateRegistrarRdapBaseUrls]]></url>
<description>
@@ -122,7 +120,6 @@
<schedule>every day 02:34</schedule>
<target>backend</target>
</cron>
-->
<cron>
<url><![CDATA[/_dr/task/deleteOldCommitLogs]]></url>
@@ -14,16 +14,16 @@
package google.registry.export;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.drive.Drive;
import dagger.Component;
import dagger.Module;
import dagger.Provides;
import google.registry.config.CredentialModule;
import google.registry.config.CredentialModule.DefaultCredential;
import google.registry.config.CredentialModule.GSuiteDriveCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.storage.drive.DriveConnection;
import google.registry.util.GoogleCredentialsBundle;
import javax.inject.Singleton;
/** Dagger module for Google {@link Drive} service connection objects. */
@@ -32,13 +32,13 @@ public final class DriveModule {
@Provides
static Drive provideDrive(
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
@GSuiteDriveCredential GoogleCredential googleCredential,
@Config("projectId") String projectId) {
return new Drive.Builder(
credentialsBundle.getHttpTransport(),
credentialsBundle.getJsonFactory(),
credentialsBundle.getHttpRequestInitializer())
googleCredential.getTransport(),
googleCredential.getJsonFactory(),
googleCredential)
.setApplicationName(projectId)
.build();
}
@@ -17,6 +17,7 @@ package google.registry.export;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.RegistrarUtils.normalizeClientId;
@@ -163,7 +164,7 @@ public final class SyncGroupMembersAction implements Runnable {
registrarsToSave.add(result.getKey().asBuilder().setContactsRequireSyncing(false).build());
}
}
ofy().transactNew(() -> ofy().save().entities(registrarsToSave.build()));
tm().transactNew(() -> ofy().save().entities(registrarsToSave.build()));
return errors;
}
@@ -25,6 +25,7 @@ import static google.registry.model.registrar.RegistrarContact.Type.LEGAL;
import static google.registry.model.registrar.RegistrarContact.Type.MARKETING;
import static google.registry.model.registrar.RegistrarContact.Type.TECH;
import static google.registry.model.registrar.RegistrarContact.Type.WHOIS;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.base.Joiner;
@@ -152,7 +153,7 @@ class SyncRegistrarsSheet {
return builder.build();
})
.collect(toImmutableList()));
ofy()
tm()
.transact(
() -> ofy().save().entity(Cursor.createGlobal(SYNC_REGISTRAR_SHEET, executionTime)));
}
@@ -39,6 +39,13 @@ public class EppMetrics {
LabelDescriptor.create("tld", "The TLD acted on by the command (if applicable)."),
LabelDescriptor.create("status", "The return status of the command."));
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
ImmutableSet.of(
LabelDescriptor.create("command", "The name of the command."),
LabelDescriptor.create("traffic_type",
"The traffic type of the command; one of CANARY, PROBER, or REAL."),
LabelDescriptor.create("status", "The return status of the command."));
private static final IncrementableMetric eppRequestsByRegistrar =
MetricRegistryImpl.getDefault()
.newIncrementableMetric(
@@ -55,23 +62,18 @@ public class EppMetrics {
"count",
LABEL_DESCRIPTORS_BY_TLD);
private static final EventMetric processingTimeByRegistrar =
private static final EventMetric requestTime =
MetricRegistryImpl.getDefault()
.newEventMetric(
"/epp/processing_time",
"EPP Processing Time By Registrar",
"/epp/request_time",
"EPP Request Time",
"milliseconds",
LABEL_DESCRIPTORS_BY_REGISTRAR,
LABEL_DESCRIPTORS,
DEFAULT_FITTER);
private static final EventMetric processingTimeByTld =
MetricRegistryImpl.getDefault()
.newEventMetric(
"/epp/processing_time_by_tld",
"EPP Processing Time By TLD",
"milliseconds",
LABEL_DESCRIPTORS_BY_TLD,
DEFAULT_FITTER);
private enum TrafficType {
CANARY, PROBER, REAL
}
@Inject
public EppMetrics() {}
@@ -97,15 +99,18 @@ public class EppMetrics {
metric.getStatus().isPresent() ? String.valueOf(metric.getStatus().get().code) : "";
long processingTime =
metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis();
processingTimeByRegistrar.record(
processingTime,
metric.getCommandName().orElse(""),
metric.getClientId().orElse(""),
eppStatusCode);
processingTimeByTld.record(
processingTime,
metric.getCommandName().orElse(""),
metric.getTld().orElse(""),
eppStatusCode);
String commandName = metric.getCommandName().orElse("");
String tld = metric.getTld().orElse("");
requestTime.record(processingTime, commandName, getTrafficType(tld).toString(), eppStatusCode);
}
private static TrafficType getTrafficType(String tld) {
if (tld.endsWith("canary.test")) {
return TrafficType.CANARY;
} else if (tld.endsWith(".test")) {
return TrafficType.PROBER;
} else {
return TrafficType.REAL;
}
}
}
@@ -14,7 +14,7 @@
package google.registry.flows;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.xml.XmlTransformer.prettyPrint;
import com.google.common.base.Strings;
@@ -80,7 +80,7 @@ public class FlowRunner {
return eppOutput;
}
try {
return ofy()
return tm()
.transact(
() -> {
try {
@@ -19,6 +19,7 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.EppResourceUtils.queryForLinkedDomains;
import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -77,7 +78,7 @@ public final class ResourceFlowUtils {
final Function<DomainBase, ImmutableSet<?>> getPotentialReferences) throws EppException {
// Enter a transactionless context briefly.
EppException failfastException =
ofy()
tm()
.doTransactionless(
() -> {
final ForeignKeyIndex<R> fki =
@@ -20,6 +20,7 @@ import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostal
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
import static google.registry.model.EppResourceUtils.createRepoId;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.googlecode.objectify.Key;
import google.registry.config.RegistryConfig.Config;
@@ -71,7 +72,7 @@ public final class ContactCreateFlow implements TransactionalFlow {
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Create command = (Create) resourceCommand;
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
verifyResourceDoesNotExist(ContactResource.class, targetId, now, clientId);
ContactResource newContact =
new ContactResource.Builder()
@@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
@@ -84,7 +85,7 @@ public final class ContactDeleteFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
failfastForAsyncDelete(targetId, now, ContactResource.class, DomainBase::getReferencedContacts);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
@@ -93,7 +94,7 @@ public final class ContactDeleteFlow implements TransactionalFlow {
verifyResourceOwnership(clientId, existingContact);
}
asyncTaskEnqueuer.enqueueAsyncDelete(
existingContact, ofy().getTransactionTime(), clientId, trid, isSuperuser);
existingContact, tm().getTransactionTime(), clientId, trid, isSuperuser);
ContactResource newContact =
existingContact.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
historyBuilder
@@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createGainingTransf
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.ResourceTransferUtils.approvePendingTransfer;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
@@ -78,7 +79,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
verifyHasPendingTransfer(existingContact);
@@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createLosingTransfe
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
@@ -74,7 +75,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
verifyHasPendingTransfer(existingContact);
@@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createGainingTransf
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
@@ -72,7 +73,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
verifyHasPendingTransfer(existingContact);
@@ -24,6 +24,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createLosingTransfe
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
@@ -91,7 +92,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(gainingClientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyAuthInfoPresentForResourceTransfer(authInfo);
verifyAuthInfo(authInfo.get(), existingContact);
@@ -25,6 +25,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
@@ -92,7 +93,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Update command = (Update) resourceCommand;
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
@@ -42,11 +42,11 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActi
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.EppResourceUtils.createDomainRepoId;
import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE;
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
@@ -221,7 +221,7 @@ public class DomainCreateFlow implements TransactionalFlow {
extensionManager.validate();
validateClientIsLoggedIn(clientId);
verifyRegistrarIsActive(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DomainCommand.Create command = cloneAndLinkReferences((Create) resourceCommand, now);
Period period = command.getPeriod();
verifyUnitIsYears(period);
@@ -34,6 +34,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PE
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.ADD_FIELDS;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.RENEW_FIELDS;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.union;
@@ -140,7 +141,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
// Loads the target resource if it exists
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
Registry registry = Registry.get(existingDomain.getTld());
@@ -28,7 +28,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.validateRegistrationPeriod;
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
import com.google.common.collect.ImmutableList;
@@ -137,7 +137,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
extensionManager.validate();
validateClientIsLoggedIn(clientId);
verifyRegistrarIsActive(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
Renew command = (Renew) resourceCommand;
// Loads the target resource if it exists
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
@@ -27,6 +27,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNo
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexDeletionTime;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.collect.ImmutableList;
@@ -133,7 +134,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
validateClientIsLoggedIn(clientId);
verifyRegistrarIsActive(clientId);
Update command = (Update) resourceCommand;
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
FeesAndCredits feesAndCredits =
pricingLogic.getRestorePrice(Registry.get(existingDomain.getTld()), targetId, now);
@@ -29,6 +29,7 @@ import static google.registry.model.ResourceTransferUtils.approvePendingTransfer
import static google.registry.model.domain.DomainBase.extendRegistrationWithCap;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@@ -102,7 +103,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain);
@@ -27,6 +27,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferRes
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.collect.ImmutableSet;
@@ -87,7 +88,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain);
@@ -28,6 +28,7 @@ import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_NACKED;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@@ -89,7 +90,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
Registry registry = Registry.get(existingDomain.getTld());
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now);
@@ -32,6 +32,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferSer
import static google.registry.model.domain.DomainBase.extendRegistrationWithCap;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -143,7 +144,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
extensionManager.validate();
validateClientIsLoggedIn(gainingClientId);
verifyRegistrarIsActive(gainingClientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class);
@@ -38,7 +38,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRegistrantAll
import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
@@ -154,7 +154,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
verifyUpdateAllowed(command, existingDomain, now);
@@ -22,6 +22,7 @@ import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomain
import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership;
import static google.registry.model.EppResourceUtils.createRepoId;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.CollectionUtils.union;
@@ -103,7 +104,7 @@ public final class HostCreateFlow implements TransactionalFlow {
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Create command = (Create) resourceCommand;
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
verifyResourceDoesNotExist(HostResource.class, targetId, now, clientId);
// The superordinate domain of the host object if creating an in-bailiwick host, or null if
// creating an external host. This is looked up before we actually create the Host object so
@@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.host.HostFlowUtils.validateHostName;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
@@ -85,7 +86,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
validateHostName(targetId);
failfastForAsyncDelete(targetId, now, HostResource.class, DomainBase::getNameservers);
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
@@ -101,7 +102,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
verifyResourceOwnership(clientId, owningResource);
}
asyncTaskEnqueuer.enqueueAsyncDelete(
existingHost, ofy().getTransactionTime(), clientId, trid, isSuperuser);
existingHost, tm().getTransactionTime(), clientId, trid, isSuperuser);
HostResource newHost =
existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
historyBuilder
@@ -28,6 +28,7 @@ import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomain
import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership;
import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.google.common.collect.ImmutableSet;
@@ -129,7 +130,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
Update command = (Update) resourceCommand;
Change change = command.getInnerChange();
String suppliedNewHostName = change.getFullyQualifiedHostName();
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
validateHostName(targetId);
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
boolean isHostRename = suppliedNewHostName != null;
@@ -271,7 +272,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
}
// We must also enqueue updates for all domains that use this host as their nameserver so
// that their NS records can be updated to point at the new name.
asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, ofy().getTransactionTime());
asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, tm().getTransactionTime());
}
}
@@ -21,6 +21,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAG
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.poll.PollMessageExternalKeyConverter.makePollMessageExternalId;
import static google.registry.model.poll.PollMessageExternalKeyConverter.parsePollMessageExternalId;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import com.googlecode.objectify.Key;
@@ -78,7 +79,7 @@ public class PollAckFlow implements TransactionalFlow {
throw new InvalidMessageIdException(messageId);
}
final DateTime now = ofy().getTransactionTime();
final DateTime now = tm().getTransactionTime();
// Load the message to be acked. If a message is queued to be delivered in the future, we treat
// it as if it doesn't exist yet. Same for if the message ID year isn't the same as the actual
@@ -124,7 +125,7 @@ public class PollAckFlow implements TransactionalFlow {
// acked, then we return a special status code indicating that. Note that the query will
// include the message being acked.
int messageCount = ofy().doTransactionless(() -> getPollMessagesQuery(clientId, now).count());
int messageCount = tm().doTransactionless(() -> getPollMessagesQuery(clientId, now).count());
if (!includeAckedMessageInCount) {
messageCount--;
}
@@ -33,6 +33,7 @@ import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIE
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING;
import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableMap;
@@ -182,7 +183,7 @@ public final class KmsUpdater {
*/
private static void persistEncryptedValues(
final ImmutableMap<String, EncryptResponse> encryptedValues) {
ofy()
tm()
.transact(
() -> {
for (Map.Entry<String, EncryptResponse> entry : encryptedValues.entrySet()) {
@@ -22,6 +22,7 @@ import static com.google.common.collect.Sets.union;
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@@ -325,13 +326,13 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
@Override
public EppResource load(Key<? extends EppResource> key) {
return ofy().doTransactionless(() -> ofy().load().key(key).now());
return tm().doTransactionless(() -> ofy().load().key(key).now());
}
@Override
public Map<Key<? extends EppResource>, EppResource> loadAll(
Iterable<? extends Key<? extends EppResource>> keys) {
return ofy().doTransactionless(() -> loadMultiple(keys));
return tm().doTransactionless(() -> loadMultiple(keys));
}
};
@@ -21,6 +21,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableList;
@@ -236,7 +237,7 @@ public final class OteAccountBuilder {
*/
public ImmutableMap<String, String> buildAndPersist() {
// save all the entitiesl in a single transaction
ofy().transact(this::saveAllEntities);
tm().transact(this::saveAllEntities);
return clientIdToTld;
}
@@ -249,7 +250,7 @@ public final class OteAccountBuilder {
/** Saves all the OT&amp;E entities we created. */
private void saveAllEntities() {
ofy().assertInTransaction();
tm().assertInTransaction();
ImmutableList<Registry> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
ImmutableList<RegistrarContact> contacts = contactsBuilder.build();
@@ -17,6 +17,7 @@ package google.registry.model.common;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.appengine.api.users.User;
import com.google.common.base.Splitter;
@@ -55,13 +56,13 @@ public class GaeUserIdConverter extends ImmutableObject {
try {
// Perform these operations in a transactionless context to avoid enlisting in some outer
// transaction (if any).
ofy().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now());
tm().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now());
// The read must be done in its own transaction to avoid reading from the session cache.
return ofy()
return tm()
.transactNew(() -> ofy().load().entity(gaeUserIdConverter).safe().user.getUserId());
} finally {
ofy().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now());
tm().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now());
}
}
}
@@ -28,6 +28,7 @@ import static google.registry.util.CollectionUtils.forceEmptyToNull;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.earliestOf;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
@@ -376,10 +377,10 @@ public class DomainBase extends EppResource
Optional<DateTime> newLastEppUpdateTime = Optional.empty();
// There is no transfer. Do any necessary autorenews.
// There is no transfer. Do any necessary autorenews for active domains.
Builder builder = asBuilder();
if (isBeforeOrAt(registrationExpirationTime, now)) {
if (isBeforeOrAt(registrationExpirationTime, now) && END_OF_TIME.equals(getDeletionTime())) {
// Autorenew by the number of years between the old expiration time and now.
DateTime lastAutorenewTime = leapSafeAddYears(
registrationExpirationTime,
@@ -15,9 +15,9 @@
package google.registry.model.domain.fee;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import java.util.Locale;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
@@ -47,7 +47,7 @@ public class FeeExtensionCommandDescriptor extends ImmutableObject {
public CommandName getCommand() {
// Require the xml string to be lowercase.
if (command != null && CharMatcher.javaLowerCase().matchesAllOf(command)) {
if (command != null && command.toLowerCase(Locale.ENGLISH).equals(command)) {
try {
return CommandName.valueOf(Ascii.toUpperCase(command));
} catch (IllegalArgumentException e) {
@@ -15,9 +15,9 @@
package google.registry.model.domain.fee12;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import java.util.Locale;
import java.util.Optional;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
@@ -83,7 +83,7 @@ public class FeeCheckCommandExtensionItemV12 extends FeeCheckCommandExtensionIte
@Override
public CommandName getCommandName() {
// Require the xml string to be lowercase.
if (commandName != null && CharMatcher.javaLowerCase().matchesAllOf(commandName)) {
if (commandName != null && commandName.toLowerCase(Locale.ENGLISH).equals(commandName)) {
try {
return CommandName.valueOf(Ascii.toUpperCase(commandName));
} catch (IllegalArgumentException e) {
@@ -19,6 +19,7 @@ import static com.google.common.collect.Maps.filterValues;
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.TypeUtils.instantiate;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -188,7 +189,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
@Override
public Optional<ForeignKeyIndex<?>> load(Key<ForeignKeyIndex<?>> key) {
return Optional.ofNullable(ofy().doTransactionless(() -> ofy().load().key(key).now()));
return Optional.ofNullable(tm().doTransactionless(() -> ofy().load().key(key).now()));
}
@Override
@@ -196,7 +197,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
Iterable<? extends Key<ForeignKeyIndex<?>>> keys) {
ImmutableSet<Key<ForeignKeyIndex<?>>> typedKeys = ImmutableSet.copyOf(keys);
Map<Key<ForeignKeyIndex<?>>, ForeignKeyIndex<?>> existingFkis =
ofy().doTransactionless(() -> ofy().load().keys(typedKeys));
tm().doTransactionless(() -> ofy().load().keys(typedKeys));
// ofy() omits keys that don't have values in Datastore, so re-add them in
// here with Optional.empty() values.
return Maps.asMap(
@@ -250,7 +251,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
public static <E extends EppResource> Map<String, ForeignKeyIndex<E>> loadCached(
Class<E> clazz, Iterable<String> foreignKeys, final DateTime now) {
if (!RegistryConfig.isEppResourceCachingEnabled()) {
return ofy().doTransactionless(() -> load(clazz, foreignKeys, now));
return tm().doTransactionless(() -> load(clazz, foreignKeys, now));
}
ImmutableList<Key<ForeignKeyIndex<?>>> fkiKeys =
Streams.stream(foreignKeys)
@@ -28,10 +28,9 @@ import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.Work;
import google.registry.model.BackupGroupRoot;
import google.registry.model.ImmutableObject;
import google.registry.model.transaction.TransactionManager.Work;
import google.registry.util.Clock;
import java.util.HashSet;
import java.util.Map;
@@ -40,7 +39,7 @@ import java.util.Set;
import org.joda.time.DateTime;
/** Wrapper for {@link Work} that associates a time with each attempt. */
class CommitLoggedWork<R> extends VoidWork {
class CommitLoggedWork<R> implements Runnable {
private final Work<R> work;
private final Clock clock;
@@ -74,8 +73,8 @@ class CommitLoggedWork<R> extends VoidWork {
*/
protected ImmutableSet<ImmutableObject> mutations = ImmutableSet.of();
/** Lifecycle marker to track whether {@link #vrun} has been called. */
private boolean vrunCalled;
/** Lifecycle marker to track whether {@link #run} has been called. */
private boolean runCalled;
CommitLoggedWork(Work<R> work, Clock clock) {
this.work = work;
@@ -87,26 +86,26 @@ class CommitLoggedWork<R> extends VoidWork {
}
boolean hasRun() {
return vrunCalled;
return runCalled;
}
R getResult() {
checkState(vrunCalled, "Cannot call getResult() before vrun()");
checkState(runCalled, "Cannot call getResult() before run()");
return result;
}
CommitLogManifest getManifest() {
checkState(vrunCalled, "Cannot call getManifest() before vrun()");
checkState(runCalled, "Cannot call getManifest() before run()");
return manifest;
}
ImmutableSet<ImmutableObject> getMutations() {
checkState(vrunCalled, "Cannot call getMutations() before vrun()");
checkState(runCalled, "Cannot call getMutations() before run()");
return mutations;
}
@Override
public void vrun() {
public void run() {
// The previous time will generally be null, except when using transactNew.
TransactionInfo previous = Ofy.TRANSACTION_INFO.get();
// Set the time to be used for "now" within the transaction.
@@ -117,7 +116,7 @@ class CommitLoggedWork<R> extends VoidWork {
} finally {
Ofy.TRANSACTION_INFO.set(previous);
}
vrunCalled = true;
runCalled = true;
}
/** Records all mutations enrolled by this transaction to a {@link CommitLogManifest} entry. */
@@ -0,0 +1,86 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.ofy;
import static google.registry.model.ofy.ObjectifyService.ofy;
import google.registry.model.transaction.TransactionManager;
import org.joda.time.DateTime;
/** Datastore implementation of {@link TransactionManager}. */
public class DatastoreTransactionManager implements TransactionManager {
private Ofy injectedOfy;
/** Constructs an instance. */
public DatastoreTransactionManager(Ofy injectedOfy) {
this.injectedOfy = injectedOfy;
}
private Ofy getOfy() {
return injectedOfy == null ? ofy() : injectedOfy;
}
@Override
public boolean inTransaction() {
return getOfy().inTransaction();
}
@Override
public void assertInTransaction() {
getOfy().assertInTransaction();
}
@Override
public <T> T transact(Work<T> work) {
return getOfy().transact(work);
}
@Override
public void transact(Runnable work) {
getOfy().transact(work);
}
@Override
public <T> T transactNew(Work<T> work) {
return getOfy().transactNew(work);
}
@Override
public void transactNew(Runnable work) {
getOfy().transactNew(work);
}
@Override
public <R> R transactNewReadOnly(Work<R> work) {
return getOfy().transactNewReadOnly(work);
}
@Override
public void transactNewReadOnly(Runnable work) {
getOfy().transactNewReadOnly(work);
}
@Override
public <R> R doTransactionless(Work<R> work) {
return getOfy().doTransactionless(work);
}
@Override
public DateTime getTransactionTime() {
return getOfy().getTransactionTime();
}
}
@@ -32,13 +32,13 @@ import com.google.common.flogger.FluentLogger;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.cmd.Deleter;
import com.googlecode.objectify.cmd.Loader;
import com.googlecode.objectify.cmd.Saver;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.VirtualEntity;
import google.registry.model.ofy.ReadOnlyWork.KillTransactionException;
import google.registry.model.transaction.TransactionManager.Work;
import google.registry.util.Clock;
import google.registry.util.NonFinalForTesting;
import google.registry.util.Sleeper;
@@ -111,11 +111,11 @@ public class Ofy {
ofy().clear();
}
public boolean inTransaction() {
boolean inTransaction() {
return ofy().getTransaction() != null;
}
public void assertInTransaction() {
void assertInTransaction() {
checkState(inTransaction(), "Must be called in a transaction");
}
@@ -194,7 +194,7 @@ public class Ofy {
}
/** Execute a transaction. */
public <R> R transact(Work<R> work) {
<R> R transact(Work<R> work) {
// If we are already in a transaction, don't wrap in a CommitLoggedWork.
return inTransaction() ? work.run() : transactNew(work);
}
@@ -205,7 +205,7 @@ public class Ofy {
* <p>This overload is used for transactions that don't return a value, formerly implemented using
* VoidWork.
*/
public void transact(Runnable work) {
void transact(Runnable work) {
transact(
() -> {
work.run();
@@ -214,7 +214,7 @@ public class Ofy {
}
/** Pause the current transaction (if any) and complete this one before returning to it. */
public <R> R transactNew(Work<R> work) {
<R> R transactNew(Work<R> work) {
// Wrap the Work in a CommitLoggedWork so that we can give transactions a frozen view of time
// and maintain commit logs for them.
return transactCommitLoggedWork(new CommitLoggedWork<>(work, getClock()));
@@ -226,7 +226,7 @@ public class Ofy {
* <p>This overload is used for transactions that don't return a value, formerly implemented using
* VoidWork.
*/
public void transactNew(Runnable work) {
void transactNew(Runnable work) {
transactNew(
() -> {
work.run();
@@ -246,7 +246,10 @@ public class Ofy {
true;
attempt++, sleepMillis *= 2) {
try {
ofy().transactNew(work);
ofy().transactNew(() -> {
work.run();
return null;
});
return work.getResult();
} catch (TransientFailureException
| TimestampInversionException
@@ -295,10 +298,13 @@ public class Ofy {
}
/** A read-only transaction is useful to get strongly consistent reads at a shared timestamp. */
public <R> R transactNewReadOnly(Work<R> work) {
<R> R transactNewReadOnly(Work<R> work) {
ReadOnlyWork<R> readOnlyWork = new ReadOnlyWork<>(work, getClock());
try {
ofy().transactNew(readOnlyWork);
ofy().transactNew(() -> {
readOnlyWork.run();
return null;
});
} catch (TransientFailureException | DatastoreTimeoutException | DatastoreFailureException e) {
// These are always retryable for a read-only operation.
return transactNewReadOnly(work);
@@ -309,7 +315,7 @@ public class Ofy {
throw new AssertionError(); // How on earth did we get here?
}
public void transactNewReadOnly(Runnable work) {
void transactNewReadOnly(Runnable work) {
transactNewReadOnly(
() -> {
work.run();
@@ -318,7 +324,7 @@ public class Ofy {
}
/** Execute some work in a transactionless context. */
public <R> R doTransactionless(Work<R> work) {
<R> R doTransactionless(Work<R> work) {
try {
com.googlecode.objectify.ObjectifyService.push(
com.googlecode.objectify.ObjectifyService.ofy().transactionless());
@@ -347,7 +353,7 @@ public class Ofy {
}
/** Get the time associated with the start of this particular transaction attempt. */
public DateTime getTransactionTime() {
DateTime getTransactionTime() {
assertInTransaction();
return TRANSACTION_INFO.get().transactionTime;
}
@@ -14,7 +14,7 @@
package google.registry.model.ofy;
import com.googlecode.objectify.Work;
import google.registry.model.transaction.TransactionManager.Work;
import google.registry.util.Clock;
/** Wrapper for {@link Work} that disallows mutations and fails the transaction at the end. */
@@ -30,8 +30,8 @@ class ReadOnlyWork<R> extends CommitLoggedWork<R> {
}
@Override
public void vrun() {
super.vrun();
public void run() {
super.run();
throw new KillTransactionException();
}
@@ -19,6 +19,7 @@ import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.rde.RdeNamingUtils.makePartialName;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.base.VerifyException;
import com.googlecode.objectify.annotation.Entity;
@@ -70,7 +71,7 @@ public final class RdeRevision extends ImmutableObject {
public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) {
checkArgument(revision >= 0, "Negative revision: %s", revision);
String triplet = makePartialName(tld, date, mode);
ofy().assertInTransaction();
tm().assertInTransaction();
RdeRevision object = ofy().load().type(RdeRevision.class).id(triplet).now();
if (revision == 0) {
verify(object == null, "RdeRevision object already created: %s", object);
@@ -31,6 +31,7 @@ import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.assertTldsExist;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
@@ -206,7 +207,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
private static final Supplier<ImmutableMap<String, Registrar>> CACHE_BY_CLIENT_ID =
memoizeWithShortExpiration(
() ->
ofy()
tm()
.doTransactionless(
() -> Maps.uniqueIndex(loadAll(), Registrar::getClientId)));
@@ -408,6 +409,9 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
*/
boolean contactsRequireSyncing = true;
/** Whether or not registry lock is allowed for this registrar. */
boolean registryLockAllowed = false;
@NonFinalForTesting
private static Supplier<byte[]> saltSupplier =
() -> {
@@ -544,6 +548,10 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
return contactsRequireSyncing;
}
public boolean isRegistryLockAllowed() {
return registryLockAllowed;
}
public String getUrl() {
return url;
}
@@ -868,7 +876,9 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
return this;
}
public Builder setDriveFolderId(String driveFolderId) {
public Builder setDriveFolderId(@Nullable String driveFolderId) {
checkArgument(driveFolderId == null || !driveFolderId.contains("/"),
"Drive folder ID must not be a full URL");
getInstance().driveFolderId = driveFolderId;
return this;
}
@@ -892,6 +902,11 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
return this;
}
public Builder setRegistryLockAllowed(boolean registryLockAllowed) {
getInstance().registryLockAllowed = registryLockAllowed;
return this;
}
/** Build the registrar, nullifying empty fields. */
@Override
public Registrar build() {
@@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.difference;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registrar.Registrar.checkValidEmail;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
import static java.util.stream.Collectors.joining;
@@ -154,7 +155,7 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable {
*/
public static void updateContacts(
final Registrar registrar, final Set<RegistrarContact> contacts) {
ofy()
tm()
.transact(
() -> {
ofy()
@@ -24,6 +24,7 @@ import static com.google.common.collect.Maps.filterValues;
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.base.Joiner;
@@ -52,7 +53,7 @@ public final class Registries {
private static Supplier<ImmutableMap<String, TldType>> createFreshCache() {
return memoizeWithShortExpiration(
() ->
ofy()
tm()
.doTransactionless(
() -> {
ImmutableMap.Builder<String, TldType> builder =
@@ -21,6 +21,7 @@ import static com.google.common.base.Predicates.not;
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
@@ -222,7 +223,7 @@ public class Registry extends ImmutableObject implements Buildable {
// Enter a transactionless context briefly; we don't want to enroll every TLD in a
// transaction that might be wrapping this call.
return Optional.ofNullable(
ofy()
tm()
.doTransactionless(
() -> ofy()
.load()
@@ -22,6 +22,7 @@ import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCache
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.google.common.annotations.VisibleForTesting;
@@ -150,7 +151,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
new CacheLoader<String, PremiumList>() {
@Override
public PremiumList load(final String name) {
return ofy().doTransactionless(() -> loadPremiumList(name));
return tm().doTransactionless(() -> loadPremiumList(name));
}
});
}
@@ -174,7 +175,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
new CacheLoader<Key<PremiumListRevision>, PremiumListRevision>() {
@Override
public PremiumListRevision load(final Key<PremiumListRevision> revisionKey) {
return ofy().doTransactionless(() -> ofy().load().key(revisionKey).now());
return tm().doTransactionless(() -> ofy().load().key(revisionKey).now());
}
});
@@ -214,7 +215,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
new CacheLoader<Key<PremiumListEntry>, Optional<PremiumListEntry>>() {
@Override
public Optional<PremiumListEntry> load(final Key<PremiumListEntry> entryKey) {
return ofy()
return tm()
.doTransactionless(() -> Optional.ofNullable(ofy().load().key(entryKey).now()));
}
});
@@ -27,6 +27,7 @@ import static google.registry.model.registry.label.DomainLabelMetrics.PremiumLis
import static google.registry.model.registry.label.PremiumList.cachePremiumListEntries;
import static google.registry.model.registry.label.PremiumList.cachePremiumListRevisions;
import static google.registry.model.registry.label.PremiumList.cachePremiumLists;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static org.joda.time.DateTimeZone.UTC;
import com.google.auto.value.AutoValue;
@@ -151,12 +152,12 @@ public final class PremiumListUtils {
// Save the new child entities in a series of transactions.
for (final List<PremiumListEntry> batch : partition(parentedEntries, TRANSACTION_BATCH_SIZE)) {
ofy().transactNew(() -> ofy().save().entities(batch));
tm().transactNew(() -> ofy().save().entities(batch));
}
// Save the new PremiumList and revision itself.
PremiumList updated = ofy().transactNew(() -> {
DateTime now = ofy().getTransactionTime();
PremiumList updated = tm().transactNew(() -> {
DateTime now = tm().getTransactionTime();
// Assert that the premium list hasn't been changed since we started this process.
PremiumList existing = ofy().load()
.type(PremiumList.class)
@@ -201,7 +202,7 @@ public final class PremiumListUtils {
/** Deletes the PremiumList and all of its child entities. */
public static void deletePremiumList(final PremiumList premiumList) {
ofy().transactNew(() -> ofy().delete().entity(premiumList));
tm().transactNew(() -> ofy().delete().entity(premiumList));
deleteRevisionAndEntriesOfPremiumList(premiumList);
cachePremiumLists.invalidate(premiumList.getName());
}
@@ -214,9 +215,9 @@ public final class PremiumListUtils {
partition(
ofy().load().type(PremiumListEntry.class).ancestor(premiumList.revisionKey).keys(),
TRANSACTION_BATCH_SIZE)) {
ofy().transactNew(() -> ofy().delete().keys(batch));
tm().transactNew(() -> ofy().delete().keys(batch));
}
ofy().transactNew(() -> ofy().delete().key(premiumList.getRevisionKey()));
tm().transactNew(() -> ofy().delete().key(premiumList.getRevisionKey()));
}
/**
@@ -16,6 +16,7 @@ package google.registry.model.server;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import com.google.auto.value.AutoValue;
@@ -176,10 +177,10 @@ public class Lock extends ImmutableObject implements Serializable {
// access to resources like GCS that can't be transactionally rolled back. Therefore, the lock
// must be definitively acquired before it is used, even when called inside another transaction.
AcquireResult acquireResult =
ofy()
tm()
.transactNew(
() -> {
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
Lock lock = ofy().load().type(Lock.class).id(lockId).now();
@@ -217,7 +218,7 @@ public class Lock extends ImmutableObject implements Serializable {
/** Release the lock. */
public void release() {
// Just use the default clock because we aren't actually doing anything that will use the clock.
ofy()
tm()
.transact(
() -> {
// To release a lock, check that no one else has already obtained it and if not
@@ -231,7 +232,7 @@ public class Lock extends ImmutableObject implements Serializable {
logger.atInfo().log("Deleting lock: %s", lockId);
ofy().deleteWithoutBackup().entity(Lock.this);
lockMetrics.recordRelease(
resourceName, tld, new Duration(acquiredTime, ofy().getTransactionTime()));
resourceName, tld, new Duration(acquiredTime, tm().getTransactionTime()));
} else {
logger.atSevere().log(
"The lock we acquired was transferred to someone else before we"
@@ -15,6 +15,7 @@
package google.registry.model.server;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
@@ -54,7 +55,7 @@ public class ServerSecret extends CrossTldSingleton {
return secret;
}
// Slow path - transactionally create a new ServerSecret (once per app setup).
return ofy().transact(() -> {
return tm().transact(() -> {
// Check again for an existing secret within the transaction to avoid races.
ServerSecret secret1 = ofy().load().entity(new ServerSecret()).now();
if (secret1 == null) {
@@ -22,6 +22,7 @@ import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
@@ -92,7 +93,7 @@ public class SignedMarkRevocationList extends ImmutableObject {
private static final Supplier<SignedMarkRevocationList> CACHE =
memoizeWithShortExpiration(
() ->
ofy()
tm()
.transactNewReadOnly(
() -> {
Iterable<SignedMarkRevocationList> shards =
@@ -150,7 +151,7 @@ public class SignedMarkRevocationList extends ImmutableObject {
/** Save this list to Datastore in sharded form. Returns {@code this}. */
public SignedMarkRevocationList save() {
ofy()
tm()
.transact(
() -> {
ofy()
@@ -21,6 +21,7 @@ import static com.google.common.base.Verify.verify;
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.annotations.VisibleForTesting;
@@ -111,7 +112,7 @@ public class ClaimsListShard extends ImmutableObject {
Concurrent.transform(
shardKeys,
key ->
ofy()
tm()
.transactNewReadOnly(
() -> {
ClaimsListShard claimsListShard = ofy().load().key(key).now();
@@ -188,7 +189,7 @@ public class ClaimsListShard extends ImmutableObject {
Concurrent.transform(
CollectionUtils.partitionMap(labelsToKeys, shardSize),
(final ImmutableMap<String, String> labelsToKeysShard) ->
ofy()
tm()
.transactNew(
() -> {
ClaimsListShard shard = create(creationTime, labelsToKeysShard);
@@ -199,7 +200,7 @@ public class ClaimsListShard extends ImmutableObject {
}));
// Persist the new revision, thus causing the newly created shards to go live.
ofy()
tm()
.transactNew(
() -> {
verify(
@@ -16,6 +16,7 @@ package google.registry.model.tmch;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.googlecode.objectify.annotation.Entity;
import google.registry.model.annotations.NotBackedUp;
@@ -48,11 +49,11 @@ public final class TmchCrl extends CrossTldSingleton {
* and actually newer than the one currently in Datastore.
*/
public static void set(final String crl, final String url) {
ofy()
tm()
.transactNew(
() -> {
TmchCrl tmchCrl = new TmchCrl();
tmchCrl.updated = ofy().getTransactionTime();
tmchCrl.updated = tm().getTransactionTime();
tmchCrl.crl = checkNotNull(crl, "crl");
tmchCrl.url = checkNotNull(url, "url");
ofy().saveWithoutBackup().entity(tmchCrl);
@@ -0,0 +1,84 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.transaction;
import org.joda.time.DateTime;
/**
* This interface defines the methods to execute database operations with or without a transaction.
*/
public interface TransactionManager {
/** This functional interface defines a method to execute a work and return the result. */
@FunctionalInterface
interface Work<R> {
R run();
}
/** Returns {@code true} if the caller is in a transaction.
*
* <p>Note that this function is kept for backward compatibility. We will review the use case
* later when adding the cloud sql implementation.
*/
boolean inTransaction();
/** Throws {@link IllegalStateException} if the caller is not in a transaction.
*
* <p>Note that this function is kept for backward compatibility. We will review the use case
* later when adding the cloud sql implementation.
*/
void assertInTransaction();
/** Executes the work in a transaction and returns the result. */
<T> T transact(Work<T> work);
/** Executes the work in a transaction. */
void transact(Runnable work);
/** Pauses the current transaction (if any), executes the work in a new transaction
* and returns the result.
*
* <p>Note that this function is kept for backward compatibility. We will review the use case
* later when adding the cloud sql implementation.
*/
<T> T transactNew(Work<T> work);
/** Pauses the current transaction (if any) and executes the work in a new transaction.
*
* <p>Note that this function is kept for backward compatibility. We will review the use case
* later when adding the cloud sql implementation.
*/
void transactNew(Runnable work);
/** Executes the work in a read-only transaction and returns the result.
*
* <p>Note that this function is kept for backward compatibility. We will review the use case
* later when adding the cloud sql implementation.
*/
<R> R transactNewReadOnly(Work<R> work);
/** Executes the work in a read-only transaction.
*
* <p>Note that this function is kept for backward compatibility. We will review the use case
* later when adding the cloud sql implementation.
*/
void transactNewReadOnly(Runnable work);
/** Executes the work in a transactionless context. */
<R> R doTransactionless(Work<R> work);
/** Returns the time associated with the start of this particular transaction attempt. */
DateTime getTransactionTime();
}
@@ -0,0 +1,37 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.transaction;
import google.registry.model.ofy.DatastoreTransactionManager;
/** Factory class to create {@link TransactionManager} instance. */
public class TransactionManagerFactory {
private static final TransactionManager TM = createTransactionManager();
private TransactionManagerFactory() {}
private static TransactionManager createTransactionManager() {
// TODO: Conditionally returns the corresponding implementation once we have
// CloudSqlTransactionManager
return new DatastoreTransactionManager(null);
}
/** Returns {@link TransactionManager} instance. */
public static TransactionManager tm() {
return TM;
}
}
@@ -17,6 +17,7 @@ package google.registry.model.translators;
import static com.google.common.base.MoreObjects.firstNonNull;
import static google.registry.config.RegistryConfig.getCommitLogDatastoreRetention;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableSortedMap;
@@ -62,7 +63,7 @@ public final class CommitLogRevisionsTranslatorFactory
@Override
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> transformBeforeSave(
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions) {
DateTime now = ofy().getTransactionTime();
DateTime now = tm().getTransactionTime();
DateTime threshold = now.minus(getCommitLogDatastoreRetention());
DateTime preThresholdTime = firstNonNull(revisions.floorKey(threshold), START_OF_TIME);
return new ImmutableSortedMap.Builder<DateTime, Key<CommitLogManifest>>(Ordering.natural())
@@ -15,7 +15,7 @@
package google.registry.model.translators;
import static com.google.common.base.MoreObjects.firstNonNull;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static org.joda.time.DateTimeZone.UTC;
import google.registry.model.CreateAutoTimestamp;
@@ -46,7 +46,7 @@ public class CreateAutoTimestampTranslatorFactory
/** Save a timestamp, setting it to the current time if it did not have a previous value. */
@Override
public Date saveValue(CreateAutoTimestamp pojoValue) {
return firstNonNull(pojoValue.getTimestamp(), ofy().getTransactionTime()).toDate();
return firstNonNull(pojoValue.getTimestamp(), tm().getTransactionTime()).toDate();
}};
}
}
@@ -14,7 +14,7 @@
package google.registry.model.translators;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static org.joda.time.DateTimeZone.UTC;
import google.registry.model.UpdateAutoTimestamp;
@@ -46,7 +46,7 @@ public class UpdateAutoTimestampTranslatorFactory
/** Save a timestamp, setting it to the current time. */
@Override
public Date saveValue(UpdateAutoTimestamp pojoValue) {
return ofy().getTransactionTime().toDate();
return tm().getTransactionTime().toDate();
}};
}
}
@@ -14,8 +14,10 @@
package google.registry.rdap;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.client.http.GenericUrl;
@@ -23,6 +25,7 @@ import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.flogger.FluentLogger;
@@ -34,8 +37,9 @@ import com.google.gson.JsonObject;
import com.googlecode.objectify.Key;
import google.registry.keyring.api.KeyModule;
import google.registry.model.registrar.Registrar;
import google.registry.model.registry.Registries;
import google.registry.model.registry.Registry.TldType;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import java.io.IOException;
import java.io.InputStream;
@@ -56,7 +60,18 @@ import javax.inject.Inject;
* <p>It is a "login/query/logout" system where you login using the ICANN Reporting credentials, get
* a cookie you then send to get the list and finally logout.
*
* <p>The username is [TLD]_ry. It could be any "real" TLD.
* <p>For clarity, this is how one would contact this endpoint "manually", from a whitelisted IP
* server:
*
* <p>$ curl [base]/login -I --user [tld]_ry:[password]
*
* <p>get the id=xxx value from the reply
*
* <p>$ curl [base]/registrarRdapBaseUrl/list -b 'id=xxx'
*
* <p>$ curl [base]/logout -b 'id=xxx'
*
* <p>where [base] is https://mosapi.icann.org/mosapi/v1/[tld]
*/
@Action(
service = Action.Service.BACKEND,
@@ -75,41 +90,29 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
@Inject HttpTransport httpTransport;
@Inject @KeyModule.Key("icannReportingPassword") String password;
/**
* The TLD for which we make the request.
*
* <p>The actual value doesn't matter, as long as it's a TLD that has access to the ICANN
* Reporter. It's just used to login.
*/
@Inject @Parameter("tld") String tld;
@Inject
UpdateRegistrarRdapBaseUrlsAction() {}
private String loginAndGetId(HttpRequestFactory requestFactory) {
try {
logger.atInfo().log("Logging in to MoSAPI");
HttpRequest request =
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
HttpResponse response = request.execute();
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) throws IOException {
logger.atInfo().log("Logging in to MoSAPI");
HttpRequest request =
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
HttpResponse response = request.execute();
Optional<HttpCookie> idCookie =
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
.findAny();
checkState(
idCookie.isPresent(),
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
response.getStatusCode(),
response.getHeaders());
return idCookie.get().getValue();
} catch (IOException e) {
throw new UncheckedIOException("Error logging in to MoSAPI server: " + e.getMessage(), e);
}
Optional<HttpCookie> idCookie =
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
.findAny();
checkState(
idCookie.isPresent(),
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
response.getStatusCode(),
response.getHeaders());
return idCookie.get().getValue();
}
private void logout(HttpRequestFactory requestFactory, String id) {
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
try {
HttpRequest request =
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGOUT_URL, tld)));
@@ -122,13 +125,13 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
}
}
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
String id = loginAndGetId(requestFactory);
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(
String tld, String id, HttpRequestFactory requestFactory) {
String content;
try {
HttpRequest request =
requestFactory.buildGetRequest(new GenericUrl(String.format(LIST_URL, tld)));
request.getHeaders().setAcceptEncoding("identity");
request.getHeaders().setCookie(String.format("%s=%s", COOKIE_ID, id));
HttpResponse response = request.execute();
@@ -139,7 +142,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
throw new UncheckedIOException(
"Error reading RDAP list from MoSAPI server: " + e.getMessage(), e);
} finally {
logout(requestFactory, id);
logout(requestFactory, id, tld);
}
logger.atInfo().log("list reply: '%s'", content);
@@ -160,12 +163,42 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
return builder.build();
}
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
// All TLDs have the same data, so just keep trying until one works
// (the expectation is that all / any should work)
ImmutableList<String> tlds = ImmutableList.sortedCopyOf(Registries.getTldsOfType(TldType.REAL));
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
Throwable finalThrowable = null;
for (String tld : tlds) {
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
String id;
try {
id = loginAndGetId(requestFactory, tld);
} catch (Throwable e) {
// Login failures are bad but not unexpected for certain TLDs. We shouldn't store those
// but rather should only store useful Throwables.
logger.atWarning().log("Error logging in to MoSAPI server: " + e.getMessage());
continue;
}
try {
return getRdapBaseUrlsPerIanaIdWithTld(tld, id, requestFactory);
} catch (Throwable throwable) {
logger.atWarning().log(
String.format(
"Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
finalThrowable = throwable;
}
}
throw new RuntimeException(
String.format("Error contacting MosAPI server. Tried TLDs %s", tlds), finalThrowable);
}
@Override
public void run() {
ImmutableSetMultimap<String, String> ianaToBaseUrls = getRdapBaseUrlsPerIanaId();
for (Key<Registrar> registrarKey : ofy().load().type(Registrar.class).keys()) {
ofy()
tm()
.transact(
() -> {
Registrar registrar = ofy().load().key(registrarKey).now();
@@ -15,6 +15,7 @@
package google.registry.rde;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.common.flogger.FluentLogger;
import google.registry.model.common.Cursor;
@@ -98,7 +99,7 @@ class EscrowTaskRunner {
task.runWithLock(nextRequiredRun);
DateTime nextRun = nextRequiredRun.plus(interval);
logger.atInfo().log("Rolling cursor forward to %s.", nextRun);
ofy().transact(() -> ofy().save().entity(Cursor.create(cursorType, nextRun, registry)));
tm().transact(() -> ofy().save().entity(Cursor.create(cursorType, nextRun, registry)));
return null;
};
String lockName = String.format("EscrowTaskRunner %s", task.getClass().getSimpleName());
@@ -16,6 +16,7 @@ package google.registry.rde;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import com.google.common.collect.ImmutableSetMultimap;
@@ -106,7 +107,7 @@ public final class PendingDepositChecker {
final Registry registry,
final CursorType cursorType,
final DateTime initialValue) {
return ofy()
return tm()
.transact(
() -> {
Cursor cursor = ofy().load().key(Cursor.createKey(cursorType, registry)).now();
@@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Verify.verify;
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.appengine.tools.cloudstorage.GcsFilename;
@@ -202,7 +203,7 @@ public final class RdeStagingReducer extends Reducer<PendingDeposit, DepositFrag
logger.atInfo().log("Manual operation; not advancing cursor or enqueuing upload task");
return;
}
ofy()
tm()
.transact(
() -> {
Registry registry = Registry.get(tld);
@@ -22,6 +22,7 @@ import static google.registry.model.common.Cursor.CursorType.RDE_UPLOAD_SFTP;
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.rde.RdeMode.FULL;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static java.util.Arrays.asList;
@@ -169,11 +170,11 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
() -> upload(xmlFilename, xmlLength, watermark, name), JSchException.class);
logger.atInfo().log(
"Updating RDE cursor '%s' for TLD '%s' following successful upload.", RDE_UPLOAD_SFTP, tld);
ofy()
tm()
.transact(
() -> {
Cursor updatedSftpCursor =
Cursor.create(RDE_UPLOAD_SFTP, ofy().getTransactionTime(), Registry.get(tld));
Cursor.create(RDE_UPLOAD_SFTP, tm().getTransactionTime(), Registry.get(tld));
ofy().save().entity(updatedSftpCursor);
});
response.setContentType(PLAIN_TEXT_UTF_8);
@@ -22,6 +22,7 @@ import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.appengine.tools.cloudstorage.GcsFilename;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.common.io.ByteStreams;
@@ -38,6 +39,7 @@ import google.registry.util.Retrier;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;
/** Copy all registrar detail reports in a given bucket's subdirectory from GCS to Drive. */
@@ -95,6 +97,8 @@ public final class CopyDetailReportsAction implements Runnable {
response.setPayload(String.format("Failure, encountered %s", e.getMessage()));
return;
}
ImmutableMap.Builder<String, Throwable> copyErrorsBuilder =
new ImmutableMap.Builder<String, Throwable>();
for (String detailReportName : detailReportObjectNames) {
// The standard report format is "invoice_details_yyyy-MM_registrarId_tld.csv
// TODO(larryruili): Determine a safer way of enforcing this.
@@ -117,7 +121,7 @@ public final class CopyDetailReportsAction implements Runnable {
try (InputStream input =
gcsUtils.openInputStream(
new GcsFilename(billingBucket, invoiceDirectoryPrefix + detailReportName))) {
driveConnection.createFile(
driveConnection.createOrUpdateFile(
detailReportName,
MediaType.CSV_UTF_8,
driveFolderId,
@@ -129,15 +133,31 @@ public final class CopyDetailReportsAction implements Runnable {
},
IOException.class);
} catch (Throwable e) {
emailUtils.sendAlertEmail(
String alertMessage =
String.format(
"Warning: CopyDetailReportsAction failed.\nEncountered: %s on file: %s",
getRootCause(e).getMessage(), detailReportName));
throw e;
"Warning: CopyDetailReportsAction failed for registrar %s.\n"
+ "Encountered: %s on file: %s",
registrarId, getRootCause(e).getMessage(), detailReportName);
copyErrorsBuilder.put(registrarId, e);
logger.atSevere().withCause(e).log(alertMessage);
}
}
response.setStatus(SC_OK);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload("Copied detail reports.");
StringBuilder payload = new StringBuilder().append("Copied detail reports.\n");
ImmutableMap<String, Throwable> copyErrors = copyErrorsBuilder.build();
if (!copyErrors.isEmpty()) {
payload.append("The following errors were encountered:\n");
payload.append(
copyErrors.entrySet().stream()
.map(
entrySet ->
String.format(
"Registrar: %s\nError: %s\n",
entrySet.getKey(), entrySet.getValue().getMessage()))
.collect(Collectors.joining()));
}
response.setPayload(payload.toString());
emailUtils.sendAlertEmail(payload.toString());
}
}
@@ -59,22 +59,19 @@ public class Spec11EmailUtils {
private final SendEmailService emailService;
private final InternetAddress outgoingEmailAddress;
private final InternetAddress alertRecipientAddress;
private final InternetAddress spec11ReplyToAddress;
private final ImmutableList<String> spec11WebResources;
private final String registryName;
@Inject
Spec11EmailUtils(
SendEmailService emailService,
@Config("gSuiteOutgoingEmailAddress") InternetAddress outgoingEmailAddress,
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
@Config("spec11ReplyToEmailAddress") InternetAddress spec11ReplyToAddress,
@Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress,
@Config("spec11WebResources") ImmutableList<String> spec11WebResources,
@Config("registryName") String registryName) {
this.emailService = emailService;
this.outgoingEmailAddress = outgoingEmailAddress;
this.outgoingEmailAddress = spec11OutgoingEmailAddress;
this.alertRecipientAddress = alertRecipientAddress;
this.spec11ReplyToAddress = spec11ReplyToAddress;
this.spec11WebResources = spec11WebResources;
this.registryName = registryName;
}
@@ -149,7 +146,7 @@ public class Spec11EmailUtils {
.setContentType(MediaType.HTML_UTF_8)
.setFrom(outgoingEmailAddress)
.addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId()))
.setBcc(spec11ReplyToAddress)
.setBcc(outgoingEmailAddress)
.build());
}
@@ -172,7 +169,7 @@ public class Spec11EmailUtils {
ImmutableMap.of(
"date", date.toString(),
"registry", registryName,
"replyToEmail", spec11ReplyToAddress.getAddress(),
"replyToEmail", outgoingEmailAddress.getAddress(),
"threats", threatMatchMap,
"resources", spec11WebResources);
renderer.setData(data);
@@ -16,12 +16,17 @@ package google.registry.request;
import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.monitoring.metrics.EventMetric;
import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import google.registry.request.auth.AuthLevel;
import java.util.List;
import java.util.stream.Collectors;
import org.joda.time.Duration;
class RequestMetrics {
@@ -50,7 +55,7 @@ class RequestMetrics {
Duration duration, String path, Action.Method method, AuthLevel authLevel, boolean success) {
requestDurationMetric.record(
duration.getMillis(),
path,
truncatePath(path),
String.valueOf(method),
String.valueOf(authLevel),
String.valueOf(success));
@@ -58,4 +63,15 @@ class RequestMetrics {
"Action called for path=%s, method=%s, authLevel=%s, success=%s. Took: %.3fs",
path, method, authLevel, success, duration.getMillis() / 1000d);
}
private static String truncatePath(String path) {
// We want to bucket RDAP requests by type to use less metric space,
// e.g. "/rdap/domains" rather than "/rdap/domains/foo.tld"
if (path.startsWith("/rdap")) {
List<String> splitPath = Splitter.on("/").omitEmptyStrings().splitToList(path);
return Streams.stream(Iterables.limit(splitPath, 2))
.collect(Collectors.joining("/", "/", "/"));
}
return path;
}
}
@@ -54,6 +54,10 @@ public class DriveConnection {
/**
* Creates a file with the given parent.
*
* <p>If a file with the same path already exists, a duplicate is created. If overwriting the
* existing file is the desired behavior, use {@link #createOrUpdateFile(String, MediaType,
* String, byte[])} instead.
*
* @returns the file id.
*/
public String createFile(String title, MediaType mimeType, String parentFolderId, byte[] bytes)
@@ -16,7 +16,7 @@ package google.registry.tmch;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
@@ -47,7 +47,7 @@ public final class LordnTaskUtils {
* Enqueues a task in the LORDN queue representing a line of CSV for LORDN export.
*/
public static void enqueueDomainBaseTask(DomainBase domain) {
ofy().assertInTransaction();
tm().assertInTransaction();
// This method needs to use ofy transactionTime as the DomainBase's creationTime because
// CreationTime isn't yet populated when this method is called during the resource flow.
String tld = domain.getTld();
@@ -55,12 +55,12 @@ public final class LordnTaskUtils {
getQueue(QUEUE_SUNRISE).add(TaskOptions.Builder
.withTag(tld)
.method(Method.PULL)
.payload(getCsvLineForSunriseDomain(domain, ofy().getTransactionTime())));
.payload(getCsvLineForSunriseDomain(domain, tm().getTransactionTime())));
} else {
getQueue(QUEUE_CLAIMS).add(TaskOptions.Builder
.withTag(tld)
.method(Method.PULL)
.payload(getCsvLineForClaimsDomain(domain, ofy().getTransactionTime())));
.payload(getCsvLineForClaimsDomain(domain, tm().getTransactionTime())));
}
}
@@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.flows.poll.PollFlowUtils.getPollMessagesQuery;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.poll.PollMessageExternalKeyConverter.makePollMessageExternalId;
import static google.registry.model.transaction.TransactionManagerFactory.tm;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -85,7 +86,7 @@ final class AckPollMessagesCommand implements CommandWithRemoteApi {
public void run() {
QueryKeys<PollMessage> query = getPollMessagesQuery(clientId, clock.nowUtc()).keys();
for (List<Key<PollMessage>> keys : Iterables.partition(query, BATCH_SIZE)) {
ofy()
tm()
.transact(
() -> {
// Load poll messages and filter to just those of interest.
@@ -100,7 +100,7 @@ public class AuthModule {
AbstractDataStoreFactory dataStoreFactory) {
try {
return new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(), jsonFactory, clientSecrets, requiredOauthScopes)
new NetHttpTransport(), jsonFactory, clientSecrets, requiredOauthScopes)
.setDataStoreFactory(dataStoreFactory)
.build();
} catch (IOException ex) {
@@ -52,7 +52,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
@Parameter(
names = {"--contact"},
description = "Contact ID for the request. This will be used for registrant, admin contact,"
description = "Contact ID for the request. This will be used for registrant, admin contact, "
+ "and tech contact.",
required = true)
private String contact;
@@ -234,10 +234,17 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
arity = 1)
private Boolean contactsRequireSyncing;
@Nullable
@Parameter(
names = "--registry_lock_allowed",
description = "Whether this registrar is allowed to use registry lock",
arity = 1)
private Boolean registryLockAllowed;
@Nullable
@Parameter(
names = "--drive_folder_id",
description = "Id of this registrar's folder in Drive",
description = "Id (not full URL) of this registrar's folder in Drive",
converter = OptionalStringParameter.class,
validateWith = OptionalStringParameter.class)
Optional<String> driveFolderId;
@@ -393,6 +400,7 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
}
Optional.ofNullable(blockPremiumNames).ifPresent(builder::setBlockPremiumNames);
Optional.ofNullable(contactsRequireSyncing).ifPresent(builder::setContactsRequireSyncing);
Optional.ofNullable(registryLockAllowed).ifPresent(builder::setRegistryLockAllowed);
Optional.ofNullable(phonePasscode).ifPresent(builder::setPhonePasscode);
Optional.ofNullable(icannReferralEmail).ifPresent(builder::setIcannReferralEmail);
Optional.ofNullable(whoisServer).ifPresent(builder::setWhoisServer);

Some files were not shown because too many files have changed in this diff Show More