Can py3_image run under non-root user? - bazel

I need to build a py3_image container run under non-root user (because of MustRunAsNonRoot Kubernetes policy). Is it possible under py3_image?

container_image has a user attribute which does this. The go_image example has an example of using it in a language image. For py3_image, it would look something like this:
container_image(
name = "user_image",
# `py_image` defaults to "#py3_image_base//image". You'll need to
# either use a base image with another user included or add the user
# entry via a tarball (like the go example) or something.
base = "#some_custom_base//image",
user = "some_user",
)
py3_image(
name = "example",
# Override the base image.
base = ":user_image",
[all the other attrs the same before]
)

Related

image_path returns bad url if called from within renderer within redis job

Rails 6 app with ActiveStorage has a application helper that returns the profile image of a user.
module ApplicationHelper
def profile_picture_with_class user, css_class, shape, width = 100
if (shape == :square)
placeholder_pic = "blank_profile_square.jpg"
else
placeholder_pic = "blank_profile_round.png"
end
image_path = user.profile_image.present? ? user.profile_image : placeholder_pic
image_tag(image_path, width: width, class: css_class)
end
end
When this applicationHelper is called from within the app it works fine. If however a redis job uses this applicationHelper the returned image_tag is going to instead of my apps actual host (localhost:3000 in dev) and this creates a very broken link.
I'm guessing since this is firing off inside a redis job it doesnt know what the host is so its prepending something else. How can I get it to understand to use the correct host and active storage type (disk vs blob)
Thanks.
Comparison of the two created links:
Example:
Redis returns this:
http://example.org/rails/active_storage/blobs/<big_long_chunk>/new-chimney-crown.jpg
When run within a view it returns this:
http://localhost:3000/rails/active_storage/disk/<big_long_chunk>/new-chimney-crown.jpg?content_type=image%2Fjpeg&disposition=inline%3B+filename%3D%22new-chimney-crown.jpg%22%3B+filename%2A%3DUTF-8%27%27new-chimney-crown.jpg
Edit: I'm pretty sure it has something to do with this:
https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions
This is the redis job, I believe that when image_path is called from within ChatMessagesController.render it is not understanding the current host.
def perform(chat_message)
ActionCable.server.broadcast "stream:#{chat_message.stream.id}", {
chat_message: ChatMessagesController.render(chat_message)
}
def perform(chat_message)
# ChatMessagesController.renderer.defaults[:http_host] = ENV['RAILS_APPLICATION_URL'].presence || 'http://localhost:3000'
renderer = ChatMessagesController.renderer.new(
http_host: ENV['RAILS_APPLICATION_URL'].presence || 'http://localhost:3000' ,
https: Rails.env.production?
)
ActionCable.server.broadcast "stream:#{chat_message.stream.id}", {
chat_message: renderer.render(chat_message)
}
end
So the defaults for whatever reason are reset to example.com while its running. If I create a renderer and specifically set its host (and ssl) it seems to work fine. SSL must be set correctly as well or it won't work.

Where are cpu tags taken into account

https://bazel.googlesource.com/bazel/+show/master/CHANGELOG.md mentions, that there are cpu tags. Of course now the question to me is where else these tags are being taken into account.
Posting the commit message here as I think it answers the question perfectly:
TLDR: You can increase the CPU reservation for tests by adding a "cpu:" (e.g. "cpu:4" for four cores) tag to their rule in a BUILD file. This can be used if tests would otherwise overwhelm your system if there's too much parallelism.
This lets users specify that their test needs a minimum of CPU cores
to run and not be flaky. Example for a reservation of 4 CPUs:
sh_test(
name = "test",
size = "large",
srcs = ["test.sh"],
tags = ["cpu:4"],
)
This could also be used by remote execution strategies to tune their
resource adjustment.
As of 2017-06-21 the following alternating options are possible:
genrule: Setting tags same as in sh_test.
Example:
genrule(
name = "foo",
srcs = [],
outs = ["foo.h"],
cmd = "./$(location create_foo.pl) > \"$#\"",
tools = ["create_foo.pl"],
tags = ["cpu:4"],
)
Skylark rules: This can work as long as you do NOT use Workers. See.
For Skylark rules cpu can be set manually for any created action individually. This is accomplished by setting execution_requirements.
Example:
ctx.action(
execution_requirements = {
"cpu:4": "", # This is no mistake - you really encode the value in the dict key and an empty string in dict value
},
)

Azure SDK Ruby Set Container ACL

I'm using https://github.com/Azure/azure-sdk-for-ruby in my Rails application. I need to set the container policy but I don't know how to create a Signed Identifier instance for the set_container_acl method.
The comments say to pass in an array of "Azure::Entity::SignedIdentifier instances" but when I try to create an instance I get "uninitialized constant Azure::Storage::Entity". Scoured the net/documentation can't find anything about it.
After digging around in the azure gem files I was able to find a signed identifier file in the service directory. It's not loaded with azure for some reason so you have to require it.
require 'azure'
require 'azure/service/signed_identifier'
def some_method
# Some code here. Create blobs instance.
# blobs = Azure::Blob::BlobService.new
sas = Azure::Service::SignedIdentifier.new
sas.id = identifier
policy = sas.access_policy
policy.start = (Time.now - 5 * 60).utc.iso8601
policy.expiry = (Time.now + 1.years).utc.iso8601
policy.permission = "r"
identifiers = [sas]
options = { timeout: 60, signed_identifiers: identifiers }
container, signed = blobs.set_container_acl(container_name, "", options)
end

Setting the Notebook to post Notes within in Evernote w/ RoR

How do you make sure a Note is created in a specific NoteBook that is not the default?
In the client sample code that Evernote provides they show this
client = EvernoteOAuth::Client.new(token: authToken)
# List all of the notebooks in the user's account
note_store = client.note_store
notebooks = note_store.listNotebooks(authToken)
puts "Found #{notebooks.size} notebooks:"
defaultNotebook = notebooks.first
notebooks.each do |notebook|
puts " * #{notebook.name}"
end
puts
puts "Creating a new note in the default notebook: #{defaultNotebook.name}"
puts
But the variable defaultNotebook does not get used again. The note get's posted at the end with
createdNote = note_store.createNote(authToken, note)
I guess that in the demo the defaultNotebook is assumed for any notes that get posted.
There isn't a setNotebook method, but there is a getNotebook one. Which the code demo for that is as follows.
client = EvernoteOAuth::Client.new(token: authtoken)
note_store = client.note_store
# We can ignore the creation here
notebook = Evernote::EDAM::Type::Notebook.new
notebook.name = "Notebook 1402371893"
created_notebook = note_store.createNotebook(notebook)
# Here we see it is retrieved with the guid
note_store.getNotebook(created_notebook.guid)
So does the getNotebook method act as setting the notebook on the note_store instance which I can then create Notes within? I have a feeling it's that simple. I'll give it a try.
EDIT
Here are more details on the way I'm trying to implement the usage of setting the Notebook that receives the Notes:
client = EvernoteOAuth::Client.new( token: user.evernote_token )
noteStore = client.note_store
if user.evernote_notebook.length.zero?
notebook = Evernote::EDAM::Type::Notebook.new()
notebook.name = "MyBook"
user.update_attribute( :evernote_notebook,
noteStore.createNotebook( user.evernote_token, notebook ).guid )
else
noteStore.getNotebook( user.evernote_notebook )
end
createdNote = noteStore.createNote( user.evernote_token, note )
image.update_attribute( :evernote_guid, createdNote.guid )
The purpose is to know the Notebook is set and the Note will be placed there.
NOTE THIS CODE WORKS --BUT-- The Note's in the wrong folder. It's in default and not the one I selected.
Here's the working answer
note = Evernote::EDAM::Type::Note.new()
client = EvernoteOAuth::Client.new( token: user.evernote_token )
noteStore = client.note_store
if user.evernote_notebook.length.zero?
notebook = Evernote::EDAM::Type::Notebook.new()
notebook.name = "MyBook"
user.update_attribute( :evernote_notebook,
noteStore.createNotebook( user.evernote_token, notebook ).guid )
end
note.notebookGuid = user.evernote_notebook
createdNote = noteStore.createNote( user.evernote_token, note )
image.update_attribute( :evernote_guid, createdNote.guid )
How do you make sure a Note is created in a specific NoteBook that is not the default?
If you want to create a note in a specific notebook, just set the 'notebookGuid' attribute of the note.
note.notebookGuid = created_notebook.guid
If you don't explicitly set the notebookGuid attribute, the note will be created in the default notebook of the account.
The getNotebook method only retrieves the notebook you specified.

How to test method that uses a image in tmp folder with Rails

I am trying to test (with rspec) a method that will decide color given a png file. In my application this file is in the /tmp folder. But how do I do that in test?
def decide_background(background, screenshot_path)
background = background.delete(" ")
self.screenshot = screenshot_path
self.background = background
unless screenshot_path.nil? || screenshot_path.empty?
image = ChunkyPNG::Image.from_file(screenshot_path)
background = ImageManipulation::get_bg_from_edges(image).delete(" ")
unless background.empty?
self.background = background
end
end
if self.background == 'rgba(0,0,0,0)'
self.background = 'rgb(255,255,255)'
end
self.save
end
This method receives two parameters:
1 - background: String of type 'rgb(0,0,0)'
2 - screenshot_path: Path to where screenshot is stored, located in /tmp/#{name_of_file}
I want to make sure that the method actually stores the correct background. So, I guess I would need to mock ImageManipulation::get_bg_from_edges(image).delete(" ") to avoid the dependency, because I am not testing that method. But how would I do that?
Also, how would I pass the screenshot_path? Should I create a file in my /tmp folder for this unit test?
Given that this is a unit test, you should mock from_file. There's no benefit in testing ChunkyPNG; I trust its authors already tested it for you. In your examples for this method:
image = double image # ha, I said "double image"
expect(ChunkyPNG::Image).to receive(:from_file).with(# whatever screenshot path should be) { image }
expect(ImageManipulation).to receive(:get_bg_from_edges).with(image) { # whatever background you like }
You probably want an integration test that hits this code too (in fact I'd have written that first), and then you would actually want an image on the disk to read. Whether you'd need to put it there as part of the integration test setup or whether your app should put it there depends on your app.

Resources