rails_blob_path host: and only_path: true returns the same? - rails-activestorage

Im trying to figure out how to use Rails.application.routes.url_helpers.rails_blob_path
I have an class with
has_one_attached :logo
and then I do
Rails.application.routes.url_helpers.rails_blob_path(record.logo)
It gives me an error
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true (ArgumentError)
Ok so I try
Rails.application.routes.url_helpers.rails_blob_path(obi.logo, host: "wwww.example.com" )
=> "/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBEUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5d977f0c66fecd8c8474355813aad9490fcdfbf2/picture.png"
Which is the same outcome as
Rails.application.routes.url_helpers.rails_blob_path(obi.logo, only_path: true )
=> "/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBEUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5d977f0c66fecd8c8474355813aad9490fcdfbf2/picture.png"
When using the host: parameter I would expect it to attach "www.example.com" to the output. Why is it the same outcome as only_path: true ?

When using the host: parameter I would expect it to attach "www.example.com" to the output. Why is it the same outcome as only_path: true ?
In Rails there are two types of URL-helpers -- path and url
With suffix _path -- relative URL path
With suffix _url -- absolute URL
Rails.application.routes.url_helpers.rails_blob_url(obi.logo, host: "https://www.example.com")
# => "https://www.example.com/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBEUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5d977f0c66fecd8c8474355813aad9490fcdfbf2/picture.png"

Related

terraform code to append existing key value pair

I'd like to append a new key-value pair to an existing yaml-based structure by using terraform.
For example I have the following yaml file:
urls:
- id: site1
url: google.de
- id: site2
url: bing.com
- id: site3
url: duckduckgo.com
Now I want to add a key-value pair based on some conditions.
(It's not required to write to the file. The list will be used in a loop later on)
Expected:
urls:
- id: site1
url: google.de
secure: false
- id: site2
url: bing.com
secure: false
- id: site3
url: duckduckgo.com
secure: true
What I already tried:
locals {
x = tomap({
for k in keys(yamldecode(file("urls.yaml"))):
k => merge(
yamldecode(file("urls.yaml"))[k],
{ urls = { url = merge(yamldecode(file("urls.yaml"))[k].urls[0], { secure = false }) }}
)
})
}
Works for the first url but I wasn't able to loop over the urls to get an index.
Second approach:
locals {
x = tomap({
for k in keys(yamldecode(file("urls.yaml"))):
k => {
for l in keys(yamldecode(file("urls.yaml"))[k]):
l => l == "urls" ? <tbd> : yamldecode(file("urls.yaml"))[k][l]
}
})
}
But I wasn't able to merge or replace the structure at <tbd> if the key matches.
It always fails because of mismatches:
arguments must be maps or objects, got "tuple".
Any idea?
After a yamldecode function converts from YAMl formatted string to HCL2, the resulting type would be map(list(object)); for example:
{ "urls" = [{id="site1", url="google.de"}] }
That makes it a bit more clear how to add a key-value pair to the nested object with a for expression. We need to preserve the structure, keys, and values of the original, and add a single key value pair in the nested object.
# map constructor and iterate through yaml map
# key = "urls", urls is list of objects
{ for key, urls in yamldecode(file("urls.yaml")) : key => [
# inside list constructor now
# url_attrs is single object in list of objects
for url_attrs in urls : {
# inside object constructor now
# retain same key value pairs, and add a "secure" key value pair
id = url_attrs.id
url = url_attrs.url
secure = false
}
]
}
In HCL2 this results in (according to local testing)
{
urls = [
{
id = "site1"
secure = false
url = "google.de"
},
]
}
which is equivalent to:
urls:
- id: site1
url: google.de
secure: false
I notice the logic for the secure boolean is a placeholder and the example code always assigned false, so I have done the same above.

x-ray - Check if content of td is equal to a value

I'm learning web-scraping with node.js x-ray. I am fetching a list of proxies from a website's table. For every row in a table, I want to check if td:nth-child(7) is equal to 'no' or 'yes'. I wanna create a property in the object called _proto, with the value of true if td:nth-child(7) is 'yes' else false;
So far this is my code:
xray("https://free-proxy-list.net/", '#list tbody tr', [{
ip: 'td:nth-child(1)',
port: 'td:nth-child(2)',
code: 'td:nth-child(3)',
country: 'td:nth-child(4)',
anonymity: 'td:nth-child(5)',
google: 'td:nth-child(6)',
https: 'td:nth-child(7)'
}])((err, proxies) => {
console.log(proxies);
});
My solution looks like this:
var Xray = require('x-ray')
var x = Xray()
x("https://free-proxy-list.net/", '#list tbody tr', [{
ip: 'td:nth-child(1)',
port: 'td:nth-child(2)',
code: 'td:nth-child(3)',
country: 'td:nth-child(4)',
anonymity: 'td:nth-child(5)',
google: 'td:nth-child(6)',
https: 'td:nth-child(7)'
}])((err, proxies) => {
proxies.map(proxy => {
if (proxy.https === 'yes') {
proxy._proto = true
} else {
proxy._proto = false
}
})
console.log(proxies)
});
After getting the proxies list, the callback function checks if any of the proxy objects has a property called “https” set to “yes”. If that’s the case, it adds a new property called “_proto” and sets it to true and if that’s not the case, it adds the “_proto” property but sets its value to “false”.
In the end it console logs the new list that contains the “_proto” properties.
Let me know if this works for you and good luck on your way to mastering web scraping!

Delayed evaluation / references to atomic datatypes in data structures

In Python 3, I use serialize data to JSON like so:
import json
config = {
'server' : {
'host' : '127.0.0.1',
'port' : 12345
}
}
serialized_config = json.dumps(config)
Due to json.dumps and the fact that the format of the JSON is fixed, I cannot alter the struct
of the python data arbitralily, e.g. host needs to be a string when config is passed to json.dumps. I cannot wrap it in a list like 'host' : ['1.1.1.1]' e.g.
Now the data is way more complex than in this example, but mostly redundant (e.g. there is only one 'host' that is constant but appears in various places throughout the config.
Now I like to define some template like so:
template = {
'server' : {
'host' : SERVER_IP,
'port' : 12345
}
}
And afterwards replace all occurences of e.g. SERVER_IP with the actual server ip etc.
The point is that I don't know the value of SERVER_IP when I define the template.
The easy way would be to just shift the atomic string into a non-atomic python struct, e.g.:
server = {
'host' : '1.1.1.1',
'port' : 12345
}
template = {
'server' : server
}
...
# Here the actual value of 'host' has been set
server['host'] = '192.168.0.1'
print(json.dumps(template))
This dumps
'{"server": {"host": "192.168.0.1", "port": 12345}}'
As wanted.
However, since port etc. also change, I would prefer something like (pseudo-code):
server_ip = '1.1.1.1' # not the actual value
template = {
'server' : {
'host' : ref(server_ip), # Don't copy the string, but either delay the evaluation or somehow create a ref to the string
'port' : 12345
}
}
...
server_ip = '192.168.0.1'
I am aware that I could write code that just traverses the python data and 'manually' replaces certain strings with different values.
However, I am curious if there is some better solution.
E.g. I played around with facilitating __getattribute__ like so:
class DelayedEval:
def __init__(self, d):
self.data = d
def __getattribute__(self, key):
# Recursive matters let aside for sake of simplicity...
data = object.__getattribute__(self, 'data')
v = data[key]
try:
v = v()
except:
pass
return v
# possibly overwrite __getitem__() etc as well ...
server_ip = '1.1.1.1'
template = {
'server' : {
'host' : lambda: server_ip, # prevents 'premature evalutation'
'port' : 12345
}
}
...
server_ip = '192.168.0.1'
print(json.dumps(DelayedEval(template))) # Does not work
I am not asking for fixing this code, I am asking for any solution that solves my issue, no matter how, as long as You deem it 'better' than the bute-force approach of traverse and replace manually.
Fixing this code might solve my problem, but there might be better solutions (or none?).
I am aware that this is a rather complicated question to pose, and probably for my usecase overly complex, however, I am curious whether there would be a viable solution to this problem apart from the brute-force 'search-and-replace' approach...
Is there some way to define 'self-completing template structs' like that in Python?
One easy approach is to make the template itself a lambda function:
template = lambda: {
'server' : {
'host' : server_ip,
'port' : 12345
}
}
...
server_ip = '192.168.0.1'
print(json.dumps(template()))

Puppet DSC module: Could not evaluate: Convert property 'authenticationinfo' value from type 'INSTANCE[]' to type 'INSTANCE' failed

I'm attempting to use dsc_authenticationinfo => {"Anonymous"=>false, "Basic"=>false, "Digest"=>false, "Windows"=>true}, getting could not evaluate error below. This property is inside of dsc_xwebsite{}.
dsc_xwebsite{$app_dns_name:
dsc_ensure => 'Present',
dsc_name => $app_dns_name,
dsc_state => 'Started',
dsc_physicalpath => $app_webroot_path,
dsc_applicationpool => $app_pool_name,
dsc_bindinginfo => [{
protocol => 'HTTP',
port => 80,
hostname => $app_dns_name,
}],
dsc_authenticationinfo => {"Anonymous"=>true, "Basic"=>true, "Digest"=>true, "Windows"=>true},
}
I'm getting the following error on my windows 2012 R2 host.
Error: /Stage[main]/Profiles::Iis_tools/Dsc_xwebsite[tools-dev.domain.com]: Could not evaluate: Convert property 'authenticationinfo' value from type 'INSTANCE[]' to type 'INSTANCE' failed
At line:31, char:2
Buffer:
ls-dev.domain.com";
};^
insta
I'm not familiar with Puppet syntax, but comparing your puppet code to some working DSC below, it seems like your authentication code should be formatted more like your bind code, so
dsc_authenticationinfo =>
{"Anonymous"=>true, "Basic"=>true, "Digest"=>true, "Windows"=>true},
should be:
dsc_authenticationinfo =>
{dsc_anonymous => true, dsc_basic => true, dsc_digest => true, dsc_windows => true},
However, your error message:
"Convert property 'authenticationinfo' value from type 'INSTANCE[]' to
type 'INSTANCE' failed"
indicates you are passing an array when a single authenticationinfo is expected? Your dsc_authenticationinfo value is not in square brackets which looks correct to me; I'm hoping the code you posted and the error message are just out of sync, and the code change above will fix your issue.
For reference, this is valid DSC code. And note that BindingInfo is an array of one while AuthenticationInfo is a single instance:
xWebSite DefaultWebSite_Site
{
Name = "Default Web Site"
Ensure = "Present"
State = "Started"
ApplicationPool = "DefaultAppPool"
PhysicalPath = "%SystemDrive%\inetpub\wwwroot" # must already exist
LogPath = "D:\IISLogs"
DependsOn = "[xWebAppPool]DefaultAppPool_Pool"
BindingInfo =
#(
MSFT_xWebBindingInformation
{
Protocol = "http"
Port = "80"
IPAddress = "*"
}
)
AuthenticationInfo =
MSFT_xWebAuthenticationInformation
{
Anonymous = $true
Basic = $false
Digest = $false
Windows = $false
}
}
This was an issue with 1) documentation on Microsoft's DSC code. 2) Improper implementation in puppetlabs\dsc module. The MS documentation was fixed and the DSC module was fixed as of version 1.2.0.

Puppet relationship with a Hash

I would like to run the following code in a sequential order so that the servers_string variable is computed before the script execution.
Unfortunately puppet failed with the following error :
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Evaluation Error: Illegal relationship operand, can not form a relationship with a Hash. A Catalog type is required.
The code snippet :
$servers = [{ name => 'toto', ip => '10.0.0.1'}, { name => 'titi', ip => '10.0.0.2' }]
$servers.each | Hash $server | {
if $servers_string != "" {
$servers_string = "${servers_string},"
}
$name = $server['name']
$servers_string = "${servers_string}${name}"
}->
file { '/my/path/myscript.sh':
ensure => file,
mode => '0700',
owner => 'root',
group => 'root',
source => "puppet:///modules/${module_name}/install.sh --servers '${servers_string}'"
}
Any idea ? Thanks
Resource relationships in general and the chain operators in particular are about the order in which resources are applied to the node. They have nothing whatever to do with the order in which the catalog builder evaluates manifest files.
Manifests are always evaluated in order, left-to-right, top-to-bottom. You do not need to use chain operators to ensure that, nor can you use them to change it. Just drop the chain operator, and you'll be fine (at least in this regard).

Resources