Jump to content


Python API - Running triggers

python perforce triggers

  • Please log in to reply
6 replies to this topic

#1 mister_wilson

mister_wilson

    Advanced Member

  • Members
  • PipPipPip
  • 119 posts
  • LocationMontreal, Quebec

Posted 10 September 2019 - 09:44 PM

Hi,

My server version is P4D/LINUX26X86_64/2018.2/1724420 (2018/11/02) and the version of the P4Python API is p4python-2017.1.1526044.

What I am trying to do is run some perforce commands from a python script located in p4 triggers, using the same username of the person that activated the trigger.
This is important for me because I want to have his username on the history of the files.

The p4 trigger is configured as follows:

Triggers:
pre_checkout command pre-user-edit "/opt/perforce/bin/python/3.4.2/bin/python3.4 /opt/perforce/triggers/prod/hl3/p4trigger_checkout.py %user% %serverport% %client% %clientcwd% %args%"

The python script code is this:
def main():
	print("Args: " , str(sys.argv))
	#sys.exit(P4PASS)

	if len(sys.argv) < 6:
		sys.exit(P4FAIL)

	user = sys.argv[1]
	serverport = sys.argv[2]
	client = sys.argv[3]
	workingdir = sys.argv[4]
	paths	 = sys.argv[5:]

	p4 = P4()
	p4.port = serverport
	p4.user = user
	p4.client = client
	p4.cwd = workingdir
	p4.connect()
	p4.run('fstat',paths)

However it seems that the code segment fails to authenticate:

Quote

'pre_checkout' validation failed: Args: ['/opt/perforce/triggers/prod/hl3/p4trigger_checkout.py', 'david.punset', '10.136.66.125:1666', 'david.punset_HL3_Progs', 'd:\\PerforceDev\\TestServer_Prog', '//hl3_stream/code/dev/main/.sa.beta.config']
Traceback (most recent call last):
File "/opt/perforce/triggers/prod/hl3/p4trigger_checkout.py", line 87, in <module>
main()
File "/opt/perforce/triggers/prod/hl3/p4trigger_checkout.py", line 56, in main
p4.run('fstat',paths)
File "/opt/perforce/bin/python/3.4.2/lib/python3.4/site-packages/P4.py", line 543, in run
result = P4API.P4Adapter.run(self, *self.__flatten(args))
P4.P4Exception: [P4#run] Errors during command execution( "p4 fstat //hl3_stream/code/dev/main/.sa.beta.config" )

[Error]: 'Perforce password (P4PASSWD) invalid or unset.'


The perforce documentation says that:

Perforce commands in trigger scripts are always run by a specific Perforce user. If no user is specified, an extra Perforce license for a user named SYSTEM (or on UNIX, the user that owns the p4d process) is assumed. To prevent this from happening:
  • Pass a %user% argument to the trigger that calls each Perforce command to ensure that each command is called by that user. For example, if Joe submits a changelist that activates trigger script trigger.pl, and trigger.pl calls the p4 changes command, the script can run the command as p4 -u %user% changes.
From my understanding, I might be missing to set a link to the tickets file on the server. If this is true, I tried but it didn’t work either:

p4.set_env('P4TICKETS',"$HOME/.p4tickets")

I received the following error:

Quote

'pre_checkout' validation failed: Args: ['/opt/perforce/triggers/prod/hl3/p4trigger_checkout.py', 'david.punset', '10.136.66.125:1666', 'david.punset_HL3_Progs', 'd:\\PerforceDev\\TestServer_Prog', '//hl3_stream/code/dev/main/.sa.beta.config']
Traceback (most recent call last):
File "/opt/perforce/triggers/prod/hl3/p4trigger_checkout.py", line 88, in <module>
main()
File "/opt/perforce/triggers/prod/hl3/p4trigger_checkout.py", line 55, in main
p4.set_env('P4TICKETS',"$HOME/.p4tickets")
P4.P4Exception: [P4.set_env()] Can't set registry on UNIX.


>> How do I properly run perforce commands from a python script via a trigger (i.e.: open for edit, revert, integrate, etc...) using the username of the user that invoked the trigger?

Please let me know if you need any additional information.

Thanks,

-Jonathan Wilson

#2 Sambwise

Sambwise

    Advanced Member

  • Members
  • PipPipPip
  • 928 posts

Posted 11 September 2019 - 12:36 AM

Your trigger will need to use superuser credentials to login as a specific user.  The basic flow is:

p4 -u SUPERUSER login NORMALUSER
p4 -u NORMALUSER fstat ...

The trigger needs to already have the password/ticket for SUPERUSER; with the Python API you probably just want to set p4.passwd within the trigger rather than trying to have the trigger modify p4d's environment.

That said, I'm a little skeptical that you want to be doing this.  The username only shows up in the history of the files if you're submitting them.  Are you really setting up a pre-edit trigger than submits files?  That sounds a bit questionable.

#3 mister_wilson

mister_wilson

    Advanced Member

  • Members
  • PipPipPip
  • 119 posts
  • LocationMontreal, Quebec

Posted 11 September 2019 - 03:08 PM

Hi Sam,

Thank you so much for the reply, it works! And yes you're right about the username showing up with the history when we submit.
We aren't setting up a pre-edit trigger that submits but we are planning to have the script lock files on another stream so we needed the username to show who locked said file(s).

#4 Sambwise

Sambwise

    Advanced Member

  • Members
  • PipPipPip
  • 928 posts

Posted 11 September 2019 - 07:37 PM

Ah, that sounds more reasonable than firing off a submit -- I remember there being long-standing feature requests for the ability to say "whenever this file gets opened, this file gets opened (and locked) too".  :)

#5 mister_wilson

mister_wilson

    Advanced Member

  • Members
  • PipPipPip
  • 119 posts
  • LocationMontreal, Quebec

Posted 12 September 2019 - 09:59 PM

Is there a way to emulate the -u <username> global option through the P4API for Python?

For example if I wanted to revert the file of another user OR lock a file as another user.

If I do something like
p4 = P4()
p4.port = serverport
p4.user = superusername
p4.password = superuserpasswd
p4.client = superuserclient
p4.connect()
p4.run_login()
p4.run('login', trigger_user)

it still requires the password of the 'trigger_user'.

#6 Sambwise

Sambwise

    Advanced Member

  • Members
  • PipPipPip
  • 928 posts

Posted 12 September 2019 - 10:30 PM

p4.user = trigger_user would be the API equivalent of p4 -u trigger_user.

You might need to open a new connection to change the user, though; note that each invocation of the p4 command line opens a new connection.

So maybe something like:

p4 = P4()
p4.port = serverport
p4.user = superusername
p4.password = superuserpasswd
p4.client = superuserclient
p4.connect()
p4.run_login()
p4.run('login', trigger_user)

p4.disconnect()
p4.user = trigger_user
p4.connect()
# run more commands here
?

When you run the "p4 login trigger_user", it should write a ticket for trigger_user into the tickets file, and a subsequent authentication attempt for trigger_user should pick up that ticket and use it to authenticate.

If that doesn't work because you're running this in a read-only environment (i.e. you can't have a tickets file), you could do something like:

trigger_ticket = p4.run('login', '-p', trigger_user)[0]
p4.disconnect()
p4.user = trigger_user
p4.password = trigger_ticket
p4.connect()

(am not running any of this code to test it so it probably needs a little help, just guessing the general shape the solution might have)

#7 mister_wilson

mister_wilson

    Advanced Member

  • Members
  • PipPipPip
  • 119 posts
  • LocationMontreal, Quebec

Posted 13 September 2019 - 02:10 PM

Thanks again Sam, that did it!





Also tagged with one or more of these keywords: python, perforce, triggers

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users